diff options
Diffstat (limited to 'servers')
105 files changed, 2408 insertions, 1740 deletions
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index 9800707849..8851e1419b 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -125,7 +125,7 @@ class AudioStreamMicrophone : public AudioStream { GDCLASS(AudioStreamMicrophone, AudioStream); friend class AudioStreamPlaybackMicrophone; - Set<AudioStreamPlaybackMicrophone *> playbacks; + RBSet<AudioStreamPlaybackMicrophone *> playbacks; protected: static void _bind_methods(); @@ -192,7 +192,7 @@ private: float weight; }; - Set<AudioStreamPlaybackRandomizer *> playbacks; + RBSet<AudioStreamPlaybackRandomizer *> playbacks; Vector<PoolEntry> audio_stream_pool; float random_pitch_scale = 1.1f; float random_volume_offset_db = 5.0f; diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp index cc317031d4..b7c373479a 100644 --- a/servers/audio/effects/audio_effect_eq.cpp +++ b/servers/audio/effects/audio_effect_eq.cpp @@ -90,9 +90,9 @@ int AudioEffectEQ::get_band_count() const { } bool AudioEffectEQ::_set(const StringName &p_name, const Variant &p_value) { - const Map<StringName, int>::Element *E = prop_band_map.find(p_name); + HashMap<StringName, int>::ConstIterator E = prop_band_map.find(p_name); if (E) { - set_band_gain_db(E->get(), p_value); + set_band_gain_db(E->value, p_value); return true; } @@ -100,9 +100,9 @@ bool AudioEffectEQ::_set(const StringName &p_name, const Variant &p_value) { } bool AudioEffectEQ::_get(const StringName &p_name, Variant &r_ret) const { - const Map<StringName, int>::Element *E = prop_band_map.find(p_name); + HashMap<StringName, int>::ConstIterator E = prop_band_map.find(p_name); if (E) { - r_ret = get_band_gain_db(E->get()); + r_ret = get_band_gain_db(E->value); return true; } diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h index 252f931e6c..9b0560223f 100644 --- a/servers/audio/effects/audio_effect_eq.h +++ b/servers/audio/effects/audio_effect_eq.h @@ -55,7 +55,7 @@ class AudioEffectEQ : public AudioEffect { EQ eq; Vector<float> gain; - Map<StringName, int> prop_band_map; + HashMap<StringName, int> prop_band_map; Vector<String> band_names; protected: diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index c8f48207e4..8ec3e469d3 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1106,13 +1106,13 @@ float AudioServer::get_playback_speed_scale() const { void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time, float p_pitch_scale) { ERR_FAIL_COND(p_playback.is_null()); - Map<StringName, Vector<AudioFrame>> map; + HashMap<StringName, Vector<AudioFrame>> map; map[p_bus] = p_volume_db_vector; start_playback_stream(p_playback, map, p_start_time, p_pitch_scale); } -void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time, float p_pitch_scale, float p_highshelf_gain, float p_attenuation_cutoff_hz) { +void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time, float p_pitch_scale, float p_highshelf_gain, float p_attenuation_cutoff_hz) { ERR_FAIL_COND(p_playback.is_null()); AudioStreamPlaybackListNode *playback_node = new AudioStreamPlaybackListNode(); @@ -1173,13 +1173,13 @@ void AudioServer::stop_playback_stream(Ref<AudioStreamPlayback> p_playback) { void AudioServer::set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volumes) { ERR_FAIL_COND(p_volumes.size() != MAX_CHANNELS_PER_BUS); - Map<StringName, Vector<AudioFrame>> map; + HashMap<StringName, Vector<AudioFrame>> map; map[p_bus] = p_volumes; set_playback_bus_volumes_linear(p_playback, map); } -void AudioServer::set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes) { +void AudioServer::set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes) { ERR_FAIL_COND(p_bus_volumes.size() > MAX_BUSES_PER_PLAYBACK); AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback); @@ -1215,7 +1215,7 @@ void AudioServer::set_playback_all_bus_volumes_linear(Ref<AudioStreamPlayback> p ERR_FAIL_COND(p_playback.is_null()); ERR_FAIL_COND(p_volumes.size() != MAX_CHANNELS_PER_BUS); - Map<StringName, Vector<AudioFrame>> map; + HashMap<StringName, Vector<AudioFrame>> map; AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback); if (!playback_node) { diff --git a/servers/audio_server.h b/servers/audio_server.h index 3d8755071a..18e173ff0b 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -263,7 +263,7 @@ private: Vector<Vector<AudioFrame>> temp_buffer; //temp_buffer for each level Vector<AudioFrame> mix_buffer; Vector<Bus *> buses; - Map<StringName, Bus *> bus_map; + HashMap<StringName, Bus *> bus_map; void _update_bus_effects(int p_bus); @@ -365,11 +365,11 @@ public: // Convenience method. void start_playback_stream(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volume_db_vector, float p_start_time = 0, float p_pitch_scale = 1); // Expose all parameters. - void start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time = 0, float p_pitch_scale = 1, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0); + void start_playback_stream(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes, float p_start_time = 0, float p_pitch_scale = 1, float p_highshelf_gain = 0, float p_attenuation_cutoff_hz = 0); void stop_playback_stream(Ref<AudioStreamPlayback> p_playback); void set_playback_bus_exclusive(Ref<AudioStreamPlayback> p_playback, StringName p_bus, Vector<AudioFrame> p_volumes); - void set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Map<StringName, Vector<AudioFrame>> p_bus_volumes); + void set_playback_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, HashMap<StringName, Vector<AudioFrame>> p_bus_volumes); void set_playback_all_bus_volumes_linear(Ref<AudioStreamPlayback> p_playback, Vector<AudioFrame> p_volumes); void set_playback_pitch_scale(Ref<AudioStreamPlayback> p_playback, float p_pitch_scale); void set_playback_paused(Ref<AudioStreamPlayback> p_playback, bool p_paused); diff --git a/servers/debugger/servers_debugger.cpp b/servers/debugger/servers_debugger.cpp index 02703cacbf..222b475be8 100644 --- a/servers/debugger/servers_debugger.cpp +++ b/servers/debugger/servers_debugger.cpp @@ -199,7 +199,7 @@ class ServersDebugger::ScriptsProfiler : public EngineProfiler { }; Vector<ScriptLanguage::ProfilingInfo> info; Vector<ScriptLanguage::ProfilingInfo *> ptrs; - Map<StringName, int> sig_map; + HashMap<StringName, int> sig_map; int max_frame_functions = 16; public: @@ -277,7 +277,7 @@ class ServersDebugger::ServersProfiler : public EngineProfiler { typedef ServersDebugger::ServerInfo ServerInfo; typedef ServersDebugger::ServerFunctionInfo ServerFunctionInfo; - Map<StringName, ServerInfo> server_data; + HashMap<StringName, ServerInfo> server_data; ScriptsProfiler scripts_profiler; double frame_time = 0; @@ -292,13 +292,13 @@ class ServersDebugger::ServersProfiler : public EngineProfiler { frame.process_time = process_time; frame.physics_time = physics_time; frame.physics_frame_time = physics_frame_time; - Map<StringName, ServerInfo>::Element *E = server_data.front(); + HashMap<StringName, ServerInfo>::Iterator E = server_data.begin(); while (E) { if (!p_final) { - frame.servers.push_back(E->get()); + frame.servers.push_back(E->value); } - E->get().functions.clear(); - E = E->next(); + E->value.functions.clear(); + ++E; } uint64_t time = 0; scripts_profiler.write_frame_data(frame.script_functions, time, p_final); @@ -357,7 +357,7 @@ class ServersDebugger::VisualProfiler : public EngineProfiler { typedef ServersDebugger::ServerInfo ServerInfo; typedef ServersDebugger::ServerFunctionInfo ServerFunctionInfo; - Map<StringName, ServerInfo> server_data; + HashMap<StringName, ServerInfo> server_data; public: void toggle(bool p_enable, const Array &p_opts) { diff --git a/servers/extensions/physics_server_3d_extension.cpp b/servers/extensions/physics_server_3d_extension.cpp index b2a9273538..b073e837e2 100644 --- a/servers/extensions/physics_server_3d_extension.cpp +++ b/servers/extensions/physics_server_3d_extension.cpp @@ -34,7 +34,7 @@ bool PhysicsDirectSpaceState3DExtension::is_body_excluded_from_query(const RID & return exclude && exclude->has(p_body); } -thread_local const Set<RID> *PhysicsDirectSpaceState3DExtension::exclude = nullptr; +thread_local const RBSet<RID> *PhysicsDirectSpaceState3DExtension::exclude = nullptr; void PhysicsDirectSpaceState3DExtension::_bind_methods() { GDVIRTUAL_BIND(_intersect_ray, "from", "to", "collision_mask", "collide_with_bodies", "collide_with_areas", "hit_from_inside", "hit_back_faces", "result"); @@ -113,8 +113,8 @@ void PhysicsDirectBodyState3DExtension::_bind_methods() { PhysicsDirectBodyState3DExtension::PhysicsDirectBodyState3DExtension() { } -thread_local const Set<RID> *PhysicsServer3DExtension::exclude_bodies = nullptr; -thread_local const Set<ObjectID> *PhysicsServer3DExtension::exclude_objects = nullptr; +thread_local const RBSet<RID> *PhysicsServer3DExtension::exclude_bodies = nullptr; +thread_local const RBSet<ObjectID> *PhysicsServer3DExtension::exclude_objects = nullptr; bool PhysicsServer3DExtension::body_test_motion_is_excluding_body(RID p_body) const { return exclude_bodies && exclude_bodies->has(p_body); diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h index ce6bed41c9..8b49278306 100644 --- a/servers/extensions/physics_server_3d_extension.h +++ b/servers/extensions/physics_server_3d_extension.h @@ -122,7 +122,7 @@ GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionShapeRestInfo) class PhysicsDirectSpaceState3DExtension : public PhysicsDirectSpaceState3D { GDCLASS(PhysicsDirectSpaceState3DExtension, PhysicsDirectSpaceState3D); - thread_local static const Set<RID> *exclude; + thread_local static const RBSet<RID> *exclude; protected: static void _bind_methods(); @@ -388,8 +388,8 @@ public: GDVIRTUAL7RC(bool, _body_test_motion, RID, const Transform3D &, const Vector3 &, real_t, int, bool, GDNativePtr<PhysicsServer3DExtensionMotionResult>) - thread_local static const Set<RID> *exclude_bodies; - thread_local static const Set<ObjectID> *exclude_objects; + thread_local static const RBSet<RID> *exclude_bodies; + thread_local static const RBSet<ObjectID> *exclude_objects; bool body_test_motion_is_excluding_body(RID p_body) const; bool body_test_motion_is_excluding_object(ObjectID p_object) const; diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index a92fe8c79a..901d335017 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -170,8 +170,12 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer2D::map_get_closest_point); ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer2D::map_get_closest_point_owner); + ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer2D::map_get_regions); + ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer2D::map_get_agents); + ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer2D::region_create); ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer2D::region_set_map); + ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer2D::region_get_map); ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer2D::region_set_layers); ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer2D::region_get_layers); ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer2D::region_set_transform); @@ -182,6 +186,7 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create); ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map); + ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer2D::agent_get_map); ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer2D::agent_set_neighbor_dist); ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer2D::agent_set_max_neighbors); ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer2D::agent_set_time_horizon); @@ -208,6 +213,14 @@ NavigationServer2D::~NavigationServer2D() { singleton = nullptr; } +Array FORWARD_1_C(map_get_regions, RID, p_map, rid_to_rid); + +Array FORWARD_1_C(map_get_agents, RID, p_map, rid_to_rid); + +RID FORWARD_1_C(region_get_map, RID, p_region, rid_to_rid); + +RID FORWARD_1_C(agent_get_map, RID, p_agent, rid_to_rid); + RID FORWARD_0_C(map_create); void FORWARD_2_C(map_set_active, RID, p_map, bool, p_active, rid_to_rid, bool_to_bool); diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index 7350eeb5b1..dfdcf5fca8 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -80,11 +80,15 @@ public: virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const; virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const; + virtual Array map_get_regions(RID p_map) const; + virtual Array map_get_agents(RID p_map) const; + /// Creates a new region. virtual RID region_create() const; /// Set the map of this region. virtual void region_set_map(RID p_region, RID p_map) const; + virtual RID region_get_map(RID p_region) const; /// Set the region's layers virtual void region_set_layers(RID p_region, uint32_t p_layers) const; @@ -106,6 +110,7 @@ public: /// Put the agent in the map. virtual void agent_set_map(RID p_agent, RID p_map) const; + virtual RID agent_get_map(RID p_agent) const; /// The maximum distance (center point to /// center point) to other agents this agent diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 46192772f6..0ce869ad1a 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -48,8 +48,12 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal); ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer3D::map_get_closest_point_owner); + ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer3D::map_get_regions); + ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer3D::map_get_agents); + ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer3D::region_create); ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer3D::region_set_map); + ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer3D::region_get_map); ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer3D::region_set_layers); ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer3D::region_get_layers); ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer3D::region_set_transform); @@ -61,6 +65,7 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create); ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map); + ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer3D::agent_get_map); ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer3D::agent_set_neighbor_dist); ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer3D::agent_set_max_neighbors); ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer3D::agent_set_time_horizon); diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index 0a75b07931..c3d3a589a9 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -91,11 +91,15 @@ public: virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const = 0; virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const = 0; + virtual Array map_get_regions(RID p_map) const = 0; + virtual Array map_get_agents(RID p_map) const = 0; + /// Creates a new region. virtual RID region_create() const = 0; /// Set the map of this region. virtual void region_set_map(RID p_region, RID p_map) const = 0; + virtual RID region_get_map(RID p_region) const = 0; /// Set the region's layers virtual void region_set_layers(RID p_region, uint32_t p_layers) const = 0; @@ -120,6 +124,7 @@ public: /// Put the agent in the map. virtual void agent_set_map(RID p_agent, RID p_map) const = 0; + virtual RID agent_get_map(RID p_agent) const = 0; /// The maximum distance (center point to /// center point) to other agents this agent diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp index 9937178550..11208f2d5b 100644 --- a/servers/physics_2d/godot_area_2d.cpp +++ b/servers/physics_2d/godot_area_2d.cpp @@ -225,22 +225,24 @@ void GodotArea2D::call_queries() { resptr[i] = &res[i]; } - for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) { - if (E->get().state == 0) { // Nothing happened - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_bodies.erase(E); + for (HashMap<BodyKey, BodyState, BodyKey>::Iterator E = monitored_bodies.begin(); E;) { + if (E->value.state == 0) { // Nothing happened + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_bodies.remove(E); E = next; continue; } - res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED; - res[1] = E->key().rid; - res[2] = E->key().instance_id; - res[3] = E->key().body_shape; - res[4] = E->key().area_shape; + res[0] = E->value.state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED; + res[1] = E->key.rid; + res[2] = E->key.instance_id; + res[3] = E->key.body_shape; + res[4] = E->key.area_shape; - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_bodies.erase(E); + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_bodies.remove(E); E = next; Callable::CallError ce; @@ -261,22 +263,24 @@ void GodotArea2D::call_queries() { resptr[i] = &res[i]; } - for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) { - if (E->get().state == 0) { // Nothing happened - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_areas.erase(E); + for (HashMap<BodyKey, BodyState, BodyKey>::Iterator E = monitored_areas.begin(); E;) { + if (E->value.state == 0) { // Nothing happened + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_areas.remove(E); E = next; continue; } - res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED; - res[1] = E->key().rid; - res[2] = E->key().instance_id; - res[3] = E->key().body_shape; - res[4] = E->key().area_shape; + res[0] = E->value.state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED; + res[1] = E->key.rid; + res[2] = E->key.instance_id; + res[3] = E->key.body_shape; + res[4] = E->key.area_shape; - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_areas.erase(E); + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_areas.remove(E); E = next; Callable::CallError ce; diff --git a/servers/physics_2d/godot_area_2d.h b/servers/physics_2d/godot_area_2d.h index dadd9747b1..b825ea5cdb 100644 --- a/servers/physics_2d/godot_area_2d.h +++ b/servers/physics_2d/godot_area_2d.h @@ -68,16 +68,15 @@ class GodotArea2D : public GodotCollisionObject2D { uint32_t body_shape = 0; uint32_t area_shape = 0; - _FORCE_INLINE_ bool operator<(const BodyKey &p_key) const { - if (rid == p_key.rid) { - if (body_shape == p_key.body_shape) { - return area_shape < p_key.area_shape; - } else { - return body_shape < p_key.body_shape; - } - } else { - return rid < p_key.rid; - } + static uint32_t hash(const BodyKey &p_key) { + uint32_t h = hash_one_uint64(p_key.rid.get_id()); + h = hash_djb2_one_64(p_key.instance_id, h); + h = hash_djb2_one_32(p_key.area_shape, h); + return hash_djb2_one_32(p_key.body_shape, h); + } + + _FORCE_INLINE_ bool operator==(const BodyKey &p_key) const { + return rid == p_key.rid && instance_id == p_key.instance_id && body_shape == p_key.body_shape && area_shape == p_key.area_shape; } _FORCE_INLINE_ BodyKey() {} @@ -91,10 +90,10 @@ class GodotArea2D : public GodotCollisionObject2D { _FORCE_INLINE_ void dec() { state--; } }; - Map<BodyKey, BodyState> monitored_bodies; - Map<BodyKey, BodyState> monitored_areas; + HashMap<BodyKey, BodyState, BodyKey> monitored_bodies; + HashMap<BodyKey, BodyState, BodyKey> monitored_areas; - Set<GodotConstraint2D *> constraints; + RBSet<GodotConstraint2D *> constraints; virtual void _shapes_changed() override; void _queue_monitor_update(); @@ -143,7 +142,7 @@ public: _FORCE_INLINE_ void add_constraint(GodotConstraint2D *p_constraint) { constraints.insert(p_constraint); } _FORCE_INLINE_ void remove_constraint(GodotConstraint2D *p_constraint) { constraints.erase(p_constraint); } - _FORCE_INLINE_ const Set<GodotConstraint2D *> &get_constraints() const { return constraints; } + _FORCE_INLINE_ const RBSet<GodotConstraint2D *> &get_constraints() const { return constraints; } _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } void set_monitorable(bool p_monitorable); diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp index 650a95c914..f82f2533f3 100644 --- a/servers/physics_2d/godot_physics_server_2d.cpp +++ b/servers/physics_2d/godot_physics_server_2d.cpp @@ -1179,7 +1179,7 @@ void GodotPhysicsServer2D::free(RID p_rid) { GodotShape2D *shape = shape_owner.get_or_null(p_rid); while (shape->get_owners().size()) { - GodotShapeOwner2D *so = shape->get_owners().front()->key(); + GodotShapeOwner2D *so = shape->get_owners().begin()->key; so->remove_shape(shape); } @@ -1250,7 +1250,7 @@ void GodotPhysicsServer2D::step(real_t p_step) { island_count = 0; active_objects = 0; collision_pairs = 0; - for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { + for (RBSet<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { stepper->step(const_cast<GodotSpace2D *>(E->get()), p_step); island_count += E->get()->get_island_count(); active_objects += E->get()->get_active_objects(); @@ -1271,7 +1271,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()) { + for (RBSet<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { GodotSpace2D *space = const_cast<GodotSpace2D *>(E->get()); space->call_queries(); } @@ -1292,7 +1292,7 @@ void GodotPhysicsServer2D::flush_queries() { total_time[i] = 0; } - for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { + for (RBSet<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { for (int i = 0; i < GodotSpace2D::ELAPSED_TIME_MAX; i++) { total_time[i] += E->get()->get_elapsed_time(GodotSpace2D::ElapsedTime(i)); } diff --git a/servers/physics_2d/godot_physics_server_2d.h b/servers/physics_2d/godot_physics_server_2d.h index 0a84caadc5..55a7b39b9e 100644 --- a/servers/physics_2d/godot_physics_server_2d.h +++ b/servers/physics_2d/godot_physics_server_2d.h @@ -56,7 +56,7 @@ class GodotPhysicsServer2D : public PhysicsServer2D { bool flushing_queries = false; GodotStep2D *stepper = nullptr; - Set<const GodotSpace2D *> active_spaces; + RBSet<const GodotSpace2D *> active_spaces; mutable RID_PtrOwner<GodotShape2D, true> shape_owner; mutable RID_PtrOwner<GodotSpace2D, true> space_owner; diff --git a/servers/physics_2d/godot_shape_2d.cpp b/servers/physics_2d/godot_shape_2d.cpp index 6c020f9e72..72ade3757b 100644 --- a/servers/physics_2d/godot_shape_2d.cpp +++ b/servers/physics_2d/godot_shape_2d.cpp @@ -50,20 +50,20 @@ Vector2 GodotShape2D::get_support(const Vector2 &p_normal) const { } void GodotShape2D::add_owner(GodotShapeOwner2D *p_owner) { - Map<GodotShapeOwner2D *, int>::Element *E = owners.find(p_owner); + HashMap<GodotShapeOwner2D *, int>::Iterator E = owners.find(p_owner); if (E) { - E->get()++; + E->value++; } else { owners[p_owner] = 1; } } void GodotShape2D::remove_owner(GodotShapeOwner2D *p_owner) { - Map<GodotShapeOwner2D *, int>::Element *E = owners.find(p_owner); + HashMap<GodotShapeOwner2D *, int>::Iterator E = owners.find(p_owner); ERR_FAIL_COND(!E); - E->get()--; - if (E->get() == 0) { - owners.erase(E); + E->value--; + if (E->value == 0) { + owners.remove(E); } } @@ -71,7 +71,7 @@ bool GodotShape2D::is_owner(GodotShapeOwner2D *p_owner) const { return owners.has(p_owner); } -const Map<GodotShapeOwner2D *, int> &GodotShape2D::get_owners() const { +const HashMap<GodotShapeOwner2D *, int> &GodotShape2D::get_owners() const { return owners; } @@ -841,7 +841,7 @@ void GodotConcavePolygonShape2D::set_data(const Variant &p_data) { const Vector2 *arr = p2arr.ptr(); - Map<Point2, int> pointmap; + HashMap<Point2, int> pointmap; for (int i = 0; i < len; i += 2) { Point2 p1 = arr[i]; Point2 p2 = arr[i + 1]; @@ -868,7 +868,7 @@ void GodotConcavePolygonShape2D::set_data(const Variant &p_data) { } points.resize(pointmap.size()); - aabb.position = pointmap.front()->key(); + aabb.position = pointmap.begin()->key; for (const KeyValue<Point2, int> &E : pointmap) { aabb.expand_to(E.key); points.write[E.value] = E.key; diff --git a/servers/physics_2d/godot_shape_2d.h b/servers/physics_2d/godot_shape_2d.h index 9b3477cea8..cede01e18d 100644 --- a/servers/physics_2d/godot_shape_2d.h +++ b/servers/physics_2d/godot_shape_2d.h @@ -50,7 +50,7 @@ class GodotShape2D { bool configured = false; real_t custom_bias = 0.0; - Map<GodotShapeOwner2D *, int> owners; + HashMap<GodotShapeOwner2D *, int> owners; protected: void configure(const Rect2 &p_aabb); @@ -86,7 +86,7 @@ public: void add_owner(GodotShapeOwner2D *p_owner); void remove_owner(GodotShapeOwner2D *p_owner); bool is_owner(GodotShapeOwner2D *p_owner) const; - const Map<GodotShapeOwner2D *, int> &get_owners() const; + const HashMap<GodotShapeOwner2D *, int> &get_owners() const; _FORCE_INLINE_ void get_supports_transformed_cast(const Vector2 &p_cast, const Vector2 &p_normal, const Transform2D &p_xform, Vector2 *r_supports, int &r_amount) const { get_supports(p_xform.basis_xform_inv(p_normal).normalized(), r_supports, r_amount); diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 3ff7ab86bb..731eab2dfe 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -1073,7 +1073,7 @@ void GodotSpace2D::remove_object(GodotCollisionObject2D *p_object) { objects.erase(p_object); } -const Set<GodotCollisionObject2D *> &GodotSpace2D::get_objects() const { +const RBSet<GodotCollisionObject2D *> &GodotSpace2D::get_objects() const { return objects; } diff --git a/servers/physics_2d/godot_space_2d.h b/servers/physics_2d/godot_space_2d.h index 5d97721176..e8b05fa4f9 100644 --- a/servers/physics_2d/godot_space_2d.h +++ b/servers/physics_2d/godot_space_2d.h @@ -92,7 +92,7 @@ private: static void *_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_self); static void _broadphase_unpair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_data, void *p_self); - Set<GodotCollisionObject2D *> objects; + RBSet<GodotCollisionObject2D *> objects; GodotArea2D *area = nullptr; @@ -156,7 +156,7 @@ public: void add_object(GodotCollisionObject2D *p_object); void remove_object(GodotCollisionObject2D *p_object); - const Set<GodotCollisionObject2D *> &get_objects() const; + const RBSet<GodotCollisionObject2D *> &get_objects() const; _FORCE_INLINE_ int get_solver_iterations() const { return solver_iterations; } _FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; } diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp index fd72038be3..0df5c1aabc 100644 --- a/servers/physics_2d/godot_step_2d.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -168,7 +168,7 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) { const SelfList<GodotArea2D>::List &aml = p_space->get_moved_area_list(); while (aml.first()) { - for (const Set<GodotConstraint2D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { + for (const RBSet<GodotConstraint2D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { GodotConstraint2D *constraint = E->get(); if (constraint->get_island_step() == _step) { continue; diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp index e7df23d0d8..e2ad765d62 100644 --- a/servers/physics_3d/godot_area_3d.cpp +++ b/servers/physics_3d/godot_area_3d.cpp @@ -254,22 +254,24 @@ void GodotArea3D::call_queries() { resptr[i] = &res[i]; } - for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) { - if (E->get().state == 0) { // Nothing happened - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_bodies.erase(E); + for (HashMap<BodyKey, BodyState, BodyKey>::Iterator E = monitored_bodies.begin(); E;) { + if (E->value.state == 0) { // Nothing happened + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_bodies.remove(E); E = next; continue; } - res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED; - res[1] = E->key().rid; - res[2] = E->key().instance_id; - res[3] = E->key().body_shape; - res[4] = E->key().area_shape; + res[0] = E->value.state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED; + res[1] = E->key.rid; + res[2] = E->key.instance_id; + res[3] = E->key.body_shape; + res[4] = E->key.area_shape; - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_bodies.erase(E); + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_bodies.remove(E); E = next; Callable::CallError ce; @@ -290,22 +292,24 @@ void GodotArea3D::call_queries() { resptr[i] = &res[i]; } - for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) { - if (E->get().state == 0) { // Nothing happened - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_areas.erase(E); + for (HashMap<BodyKey, BodyState, BodyKey>::Iterator E = monitored_areas.begin(); E;) { + if (E->value.state == 0) { // Nothing happened + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_areas.remove(E); E = next; continue; } - res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED; - res[1] = E->key().rid; - res[2] = E->key().instance_id; - res[3] = E->key().body_shape; - res[4] = E->key().area_shape; + res[0] = E->value.state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED; + res[1] = E->key.rid; + res[2] = E->key.instance_id; + res[3] = E->key.body_shape; + res[4] = E->key.area_shape; - Map<BodyKey, BodyState>::Element *next = E->next(); - monitored_areas.erase(E); + HashMap<BodyKey, BodyState, BodyKey>::Iterator next = E; + ++next; + monitored_areas.remove(E); E = next; Callable::CallError ce; diff --git a/servers/physics_3d/godot_area_3d.h b/servers/physics_3d/godot_area_3d.h index d15f8ec0a6..2a5e5a537a 100644 --- a/servers/physics_3d/godot_area_3d.h +++ b/servers/physics_3d/godot_area_3d.h @@ -72,16 +72,15 @@ class GodotArea3D : public GodotCollisionObject3D { uint32_t body_shape = 0; uint32_t area_shape = 0; - _FORCE_INLINE_ bool operator<(const BodyKey &p_key) const { - if (rid == p_key.rid) { - if (body_shape == p_key.body_shape) { - return area_shape < p_key.area_shape; - } else { - return body_shape < p_key.body_shape; - } - } else { - return rid < p_key.rid; - } + static uint32_t hash(const BodyKey &p_key) { + uint32_t h = hash_one_uint64(p_key.rid.get_id()); + h = hash_djb2_one_64(p_key.instance_id, h); + h = hash_djb2_one_32(p_key.area_shape, h); + return hash_djb2_one_32(p_key.body_shape, h); + } + + _FORCE_INLINE_ bool operator==(const BodyKey &p_key) const { + return rid == p_key.rid && instance_id == p_key.instance_id && body_shape == p_key.body_shape && area_shape == p_key.area_shape; } _FORCE_INLINE_ BodyKey() {} @@ -96,11 +95,11 @@ class GodotArea3D : public GodotCollisionObject3D { _FORCE_INLINE_ void dec() { state--; } }; - Map<BodyKey, BodyState> monitored_soft_bodies; - Map<BodyKey, BodyState> monitored_bodies; - Map<BodyKey, BodyState> monitored_areas; + HashMap<BodyKey, BodyState, BodyKey> monitored_soft_bodies; + HashMap<BodyKey, BodyState, BodyKey> monitored_bodies; + HashMap<BodyKey, BodyState, BodyKey> monitored_areas; - Set<GodotConstraint3D *> constraints; + RBSet<GodotConstraint3D *> constraints; virtual void _shapes_changed() override; void _queue_monitor_update(); @@ -164,7 +163,7 @@ public: _FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint) { constraints.insert(p_constraint); } _FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraints.erase(p_constraint); } - _FORCE_INLINE_ const Set<GodotConstraint3D *> &get_constraints() const { return constraints; } + _FORCE_INLINE_ const RBSet<GodotConstraint3D *> &get_constraints() const { return constraints; } _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } void set_monitorable(bool p_monitorable); diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h index c0c847d920..93bd5a0071 100644 --- a/servers/physics_3d/godot_body_3d.h +++ b/servers/physics_3d/godot_body_3d.h @@ -112,7 +112,7 @@ class GodotBody3D : public GodotCollisionObject3D { virtual void _shapes_changed() override; Transform3D new_transform; - Map<GodotConstraint3D *, int> constraint_map; + HashMap<GodotConstraint3D *, int> constraint_map; Vector<AreaCMP> areas; @@ -196,7 +196,7 @@ public: _FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; } _FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraint_map.erase(p_constraint); } - const Map<GodotConstraint3D *, int> &get_constraint_map() const { return constraint_map; } + const HashMap<GodotConstraint3D *, int> &get_constraint_map() const { return constraint_map; } _FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); } _FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; } diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp index e5107be74b..cb4988757c 100644 --- a/servers/physics_3d/godot_physics_server_3d.cpp +++ b/servers/physics_3d/godot_physics_server_3d.cpp @@ -1531,7 +1531,7 @@ void GodotPhysicsServer3D::free(RID p_rid) { GodotShape3D *shape = shape_owner.get_or_null(p_rid); while (shape->get_owners().size()) { - GodotShapeOwner3D *so = shape->get_owners().front()->key(); + GodotShapeOwner3D *so = shape->get_owners().begin()->key; so->remove_shape(shape); } @@ -1611,7 +1611,7 @@ void GodotPhysicsServer3D::step(real_t p_step) { island_count = 0; active_objects = 0; collision_pairs = 0; - for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { + for (RBSet<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { stepper->step(const_cast<GodotSpace3D *>(E->get()), p_step); island_count += E->get()->get_island_count(); active_objects += E->get()->get_active_objects(); @@ -1635,7 +1635,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()) { + for (RBSet<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { GodotSpace3D *space = const_cast<GodotSpace3D *>(E->get()); space->call_queries(); } @@ -1656,7 +1656,7 @@ void GodotPhysicsServer3D::flush_queries() { total_time[i] = 0; } - for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { + for (RBSet<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { for (int i = 0; i < GodotSpace3D::ELAPSED_TIME_MAX; i++) { total_time[i] += E->get()->get_elapsed_time(GodotSpace3D::ElapsedTime(i)); } diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h index d2078a912c..65c53084ac 100644 --- a/servers/physics_3d/godot_physics_server_3d.h +++ b/servers/physics_3d/godot_physics_server_3d.h @@ -54,7 +54,7 @@ class GodotPhysicsServer3D : public PhysicsServer3D { bool flushing_queries = false; GodotStep3D *stepper = nullptr; - Set<const GodotSpace3D *> active_spaces; + RBSet<const GodotSpace3D *> active_spaces; mutable RID_PtrOwner<GodotShape3D, true> shape_owner; mutable RID_PtrOwner<GodotSpace3D, true> space_owner; diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp index 2efc11a4c0..5e310670a5 100644 --- a/servers/physics_3d/godot_shape_3d.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -76,20 +76,20 @@ Vector3 GodotShape3D::get_support(const Vector3 &p_normal) const { } void GodotShape3D::add_owner(GodotShapeOwner3D *p_owner) { - Map<GodotShapeOwner3D *, int>::Element *E = owners.find(p_owner); + HashMap<GodotShapeOwner3D *, int>::Iterator E = owners.find(p_owner); if (E) { - E->get()++; + E->value++; } else { owners[p_owner] = 1; } } void GodotShape3D::remove_owner(GodotShapeOwner3D *p_owner) { - Map<GodotShapeOwner3D *, int>::Element *E = owners.find(p_owner); + HashMap<GodotShapeOwner3D *, int>::Iterator E = owners.find(p_owner); ERR_FAIL_COND(!E); - E->get()--; - if (E->get() == 0) { - owners.erase(E); + E->value--; + if (E->value == 0) { + owners.remove(E); } } @@ -97,7 +97,7 @@ bool GodotShape3D::is_owner(GodotShapeOwner3D *p_owner) const { return owners.has(p_owner); } -const Map<GodotShapeOwner3D *, int> &GodotShape3D::get_owners() const { +const HashMap<GodotShapeOwner3D *, int> &GodotShape3D::get_owners() const { return owners; } diff --git a/servers/physics_3d/godot_shape_3d.h b/servers/physics_3d/godot_shape_3d.h index 9d171c3928..1fc8f7c711 100644 --- a/servers/physics_3d/godot_shape_3d.h +++ b/servers/physics_3d/godot_shape_3d.h @@ -51,7 +51,7 @@ class GodotShape3D { bool configured = false; real_t custom_bias = 0.0; - Map<GodotShapeOwner3D *, int> owners; + HashMap<GodotShapeOwner3D *, int> owners; protected: void configure(const AABB &p_aabb); @@ -93,7 +93,7 @@ public: void add_owner(GodotShapeOwner3D *p_owner); void remove_owner(GodotShapeOwner3D *p_owner); bool is_owner(GodotShapeOwner3D *p_owner) const; - const Map<GodotShapeOwner3D *, int> &get_owners() const; + const HashMap<GodotShapeOwner3D *, int> &get_owners() const; GodotShape3D() {} virtual ~GodotShape3D(); diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp index be4b41292d..9cc7912a5a 100644 --- a/servers/physics_3d/godot_soft_body_3d.cpp +++ b/servers/physics_3d/godot_soft_body_3d.cpp @@ -33,7 +33,7 @@ #include "godot_space_3d.h" #include "core/math/geometry_3d.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "servers/rendering_server.h" // Based on Bullet soft body. @@ -494,7 +494,7 @@ bool GodotSoftBody3D::create_from_trimesh(const Vector<int> &p_indices, const Ve // Process vertices. { uint32_t vertex_count = 0; - Map<Vector3, uint32_t> unique_vertices; + HashMap<Vector3, uint32_t> unique_vertices; vertices.resize(visual_vertex_count); map_visual_to_physics.resize(visual_vertex_count); @@ -502,11 +502,11 @@ bool GodotSoftBody3D::create_from_trimesh(const Vector<int> &p_indices, const Ve for (int visual_vertex_index = 0; visual_vertex_index < visual_vertex_count; ++visual_vertex_index) { const Vector3 &vertex = p_vertices[visual_vertex_index]; - Map<Vector3, uint32_t>::Element *e = unique_vertices.find(vertex); + HashMap<Vector3, uint32_t>::Iterator e = unique_vertices.find(vertex); uint32_t vertex_id; if (e) { // Already existing. - vertex_id = e->value(); + vertex_id = e->value; } else { // Create new one. vertex_id = vertex_count++; diff --git a/servers/physics_3d/godot_soft_body_3d.h b/servers/physics_3d/godot_soft_body_3d.h index 96f63e5819..094ab39c47 100644 --- a/servers/physics_3d/godot_soft_body_3d.h +++ b/servers/physics_3d/godot_soft_body_3d.h @@ -38,7 +38,7 @@ #include "core/math/dynamic_bvh.h" #include "core/math/vector3.h" #include "core/templates/local_vector.h" -#include "core/templates/set.h" +#include "core/templates/rb_set.h" #include "core/templates/vset.h" class GodotConstraint3D; @@ -103,7 +103,7 @@ class GodotSoftBody3D : public GodotCollisionObject3D { SelfList<GodotSoftBody3D> active_list; - Set<GodotConstraint3D *> constraints; + RBSet<GodotConstraint3D *> constraints; Vector<AreaCMP> areas; @@ -123,7 +123,7 @@ public: _FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint) { constraints.insert(p_constraint); } _FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraints.erase(p_constraint); } - _FORCE_INLINE_ const Set<GodotConstraint3D *> &get_constraints() const { return constraints; } + _FORCE_INLINE_ const RBSet<GodotConstraint3D *> &get_constraints() const { return constraints; } _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } _FORCE_INLINE_ void add_exception(const RID &p_exception) { exceptions.insert(p_exception); } diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index 0b84520c39..9c051b23f6 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -1096,7 +1096,7 @@ void GodotSpace3D::remove_object(GodotCollisionObject3D *p_object) { objects.erase(p_object); } -const Set<GodotCollisionObject3D *> &GodotSpace3D::get_objects() const { +const RBSet<GodotCollisionObject3D *> &GodotSpace3D::get_objects() const { return objects; } diff --git a/servers/physics_3d/godot_space_3d.h b/servers/physics_3d/godot_space_3d.h index 6308ede9a9..67dde30fb5 100644 --- a/servers/physics_3d/godot_space_3d.h +++ b/servers/physics_3d/godot_space_3d.h @@ -89,7 +89,7 @@ private: static void *_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_self); static void _broadphase_unpair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_data, void *p_self); - Set<GodotCollisionObject3D *> objects; + RBSet<GodotCollisionObject3D *> objects; GodotArea3D *area = nullptr; @@ -158,7 +158,7 @@ public: void add_object(GodotCollisionObject3D *p_object); void remove_object(GodotCollisionObject3D *p_object); - const Set<GodotCollisionObject3D *> &get_objects() const; + const RBSet<GodotCollisionObject3D *> &get_objects() const; _FORCE_INLINE_ int get_solver_iterations() const { return solver_iterations; } _FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; } diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp index 204adae450..b46436ba39 100644 --- a/servers/physics_3d/godot_step_3d.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -87,7 +87,7 @@ void GodotStep3D::_populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D void GodotStep3D::_populate_island_soft_body(GodotSoftBody3D *p_soft_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island) { p_soft_body->set_island_step(_step); - for (Set<GodotConstraint3D *>::Element *E = p_soft_body->get_constraints().front(); E; E = E->next()) { + for (RBSet<GodotConstraint3D *>::Element *E = p_soft_body->get_constraints().front(); E; E = E->next()) { GodotConstraint3D *constraint = const_cast<GodotConstraint3D *>(E->get()); if (constraint->get_island_step() == _step) { continue; // Already processed. @@ -236,7 +236,7 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) { const SelfList<GodotArea3D>::List &aml = p_space->get_moved_area_list(); while (aml.first()) { - for (const Set<GodotConstraint3D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { + for (const RBSet<GodotConstraint3D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { GodotConstraint3D *constraint = E->get(); if (constraint->get_island_step() == _step) { continue; diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index d6d23f8310..4aeaa7497f 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -158,7 +158,7 @@ Vector<RID> PhysicsRayQueryParameters2D::get_exclude() const { Vector<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; @@ -208,7 +208,7 @@ Vector<RID> PhysicsPointQueryParameters2D::get_exclude() const { Vector<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; @@ -267,7 +267,7 @@ Vector<RID> PhysicsShapeQueryParameters2D::get_exclude() const { Vector<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 2f70b88e30..bd53764932 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -127,7 +127,7 @@ public: struct RayParameters { Vector2 from; Vector2 to; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = UINT32_MAX; bool collide_with_bodies = true; @@ -157,7 +157,7 @@ public: struct PointParameters { Vector2 position; ObjectID canvas_instance_id; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = UINT32_MAX; bool collide_with_bodies = true; @@ -173,7 +173,7 @@ public: Transform2D transform; Vector2 motion; real_t margin = 0.0; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = UINT32_MAX; bool collide_with_bodies = true; @@ -483,8 +483,8 @@ public: Vector2 motion; real_t margin = 0.08; bool collide_separation_ray = false; - Set<RID> exclude_bodies; - Set<ObjectID> exclude_objects; + RBSet<RID> exclude_bodies; + RBSet<ObjectID> exclude_objects; MotionParameters() {} diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index bfe93f0dfb..d05f5128b2 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -177,7 +177,7 @@ Vector<RID> PhysicsRayQueryParameters3D::get_exclude() const { Vector<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; @@ -231,7 +231,7 @@ Vector<RID> PhysicsPointQueryParameters3D::get_exclude() const { Vector<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; @@ -286,7 +286,7 @@ Vector<RID> PhysicsShapeQueryParameters3D::get_exclude() const { Vector<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 47f3fc2027..c707f621b4 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -133,7 +133,7 @@ public: struct RayParameters { Vector3 from; Vector3 to; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = UINT32_MAX; bool collide_with_bodies = true; @@ -165,7 +165,7 @@ public: struct PointParameters { Vector3 position; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = UINT32_MAX; bool collide_with_bodies = true; @@ -179,7 +179,7 @@ public: Transform3D transform; Vector3 motion; real_t margin = 0.0; - Set<RID> exclude; + RBSet<RID> exclude; uint32_t collision_mask = UINT32_MAX; bool collide_with_bodies = true; @@ -520,8 +520,8 @@ public: real_t margin = 0.001; int max_collisions = 1; bool collide_separation_ray = false; - Set<RID> exclude_bodies; - Set<ObjectID> exclude_objects; + RBSet<RID> exclude_bodies; + RBSet<ObjectID> exclude_objects; MotionParameters() {} diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h index 6cad45ea6d..5c6fcc8386 100644 --- a/servers/rendering/dummy/rasterizer_dummy.h +++ b/servers/rendering/dummy/rasterizer_dummy.h @@ -95,9 +95,9 @@ public: static void make_current() { _create_func = _create_current; + low_end = true; } - bool is_low_end() const override { return true; } uint64_t get_frame_number() const override { return frame; } double get_frame_delta_time() const override { return delta; } diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 84ab19880c..46bc22ad54 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -1831,7 +1831,7 @@ void RendererCanvasCull::canvas_occluder_polygon_set_shape(RID p_occluder_polygo RSG::canvas_render->occluder_polygon_set_shape(occluder_poly->occluder, p_shape, p_closed); - for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { + for (RBSet<RendererCanvasRender::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { E->get()->aabb_cache = occluder_poly->aabb; } } @@ -1841,7 +1841,7 @@ void RendererCanvasCull::canvas_occluder_polygon_set_cull_mode(RID p_occluder_po ERR_FAIL_COND(!occluder_poly); occluder_poly->cull_mode = p_mode; RSG::canvas_render->occluder_polygon_set_cull_mode(occluder_poly->occluder, p_mode); - for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { + for (RBSet<RendererCanvasRender::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { E->get()->cull_cache = p_mode; } } @@ -1931,7 +1931,7 @@ bool RendererCanvasCull::free(RID p_rid) { RendererViewport::Viewport *vp = RSG::viewport->viewport_owner.get_or_null(canvas->viewports.front()->get()); ERR_FAIL_COND_V(!vp, true); - Map<RID, RendererViewport::Viewport::CanvasData>::Element *E = vp->canvas_map.find(p_rid); + HashMap<RID, RendererViewport::Viewport::CanvasData>::Iterator E = vp->canvas_map.find(p_rid); ERR_FAIL_COND_V(!E, true); vp->canvas_map.erase(p_rid); @@ -1942,11 +1942,11 @@ bool RendererCanvasCull::free(RID p_rid) { canvas->child_items[i].item->parent = RID(); } - for (Set<RendererCanvasRender::Light *>::Element *E = canvas->lights.front(); E; E = E->next()) { + for (RBSet<RendererCanvasRender::Light *>::Element *E = canvas->lights.front(); E; E = E->next()) { E->get()->canvas = RID(); } - for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *E = canvas->occluders.front(); E; E = E->next()) { + for (RBSet<RendererCanvasRender::LightOccluderInstance *>::Element *E = canvas->occluders.front(); E; E = E->next()) { E->get()->canvas = RID(); } diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 637245502d..6f3cd1d2c6 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -108,7 +108,7 @@ public: Rect2 aabb; RS::CanvasOccluderPolygonCullMode cull_mode; RID occluder; - Set<RendererCanvasRender::LightOccluderInstance *> owners; + RBSet<RendererCanvasRender::LightOccluderInstance *> owners; LightOccluderPolygon() { active = false; @@ -121,7 +121,7 @@ public: RID_Owner<RendererCanvasRender::LightOccluderInstance, true> canvas_light_occluder_owner; struct Canvas : public RendererViewport::CanvasBase { - Set<RID> viewports; + RBSet<RID> viewports; struct ChildItem { Point2 mirror; Item *item = nullptr; @@ -130,10 +130,10 @@ public: } }; - Set<RendererCanvasRender::Light *> lights; - Set<RendererCanvasRender::Light *> directional_lights; + RBSet<RendererCanvasRender::Light *> lights; + RBSet<RendererCanvasRender::Light *> directional_lights; - Set<RendererCanvasRender::LightOccluderInstance *> occluders; + RBSet<RendererCanvasRender::LightOccluderInstance *> occluders; bool children_order_dirty; Vector<ChildItem> child_items; diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp index fa4d9c8b31..b331ec2c1d 100644 --- a/servers/rendering/renderer_compositor.cpp +++ b/servers/rendering/renderer_compositor.cpp @@ -35,6 +35,7 @@ #include "core/string/print_string.h" RendererCompositor *(*RendererCompositor::_create_func)() = nullptr; +bool RendererCompositor::low_end = false; RendererCompositor *RendererCompositor::create() { return _create_func(); diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index 9466148a31..df3df1077a 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -71,6 +71,7 @@ private: protected: static RendererCompositor *(*_create_func)(); bool back_end = false; + static bool low_end; public: static RendererCompositor *create(); @@ -97,7 +98,7 @@ public: virtual uint64_t get_frame_number() const = 0; virtual double get_frame_delta_time() const = 0; - _FORCE_INLINE_ virtual bool is_low_end() const { return back_end; }; + static bool is_low_end() { return low_end; }; virtual bool is_xr_enabled() const; RendererCompositor(); diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp new file mode 100644 index 0000000000..cc7441776d --- /dev/null +++ b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp @@ -0,0 +1,475 @@ +/*************************************************************************/ +/* bokeh_dof.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 "bokeh_dof.h" +#include "copy_effects.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/uniform_set_cache_rd.h" + +using namespace RendererRD; + +BokehDOF::BokehDOF(bool p_prefer_raster_effects) { + prefer_raster_effects = p_prefer_raster_effects; + + // Initialize bokeh + Vector<String> bokeh_modes; + bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n#define OUTPUT_WEIGHT\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n#define OUTPUT_WEIGHT\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n#define OUTPUT_WEIGHT\n"); + bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n"); + if (prefer_raster_effects) { + bokeh.raster_shader.initialize(bokeh_modes); + + bokeh.shader_version = bokeh.raster_shader.version_create(); + + const int att_count[BOKEH_MAX] = { 1, 2, 1, 2, 1, 2, 1 }; + for (int i = 0; i < BOKEH_MAX; i++) { + RD::PipelineColorBlendState blend_state = (i == BOKEH_COMPOSITE) ? RD::PipelineColorBlendState::create_blend(att_count[i]) : RD::PipelineColorBlendState::create_disabled(att_count[i]); + bokeh.raster_pipelines[i].setup(bokeh.raster_shader.version_get_shader(bokeh.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } + } else { + bokeh.compute_shader.initialize(bokeh_modes); + bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_BOX_NOWEIGHT, false); + bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, false); + bokeh.shader_version = bokeh.compute_shader.version_create(); + + for (int i = 0; i < BOKEH_MAX; i++) { + if (bokeh.compute_shader.is_variant_enabled(i)) { + bokeh.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.compute_shader.version_get_shader(bokeh.shader_version, i)); + } + } + + for (int i = 0; i < BOKEH_MAX; i++) { + bokeh.raster_pipelines[i].clear(); + } + } +} + +BokehDOF::~BokehDOF() { + if (prefer_raster_effects) { + bokeh.raster_shader.version_free(bokeh.shader_version); + } else { + bokeh.compute_shader.version_free(bokeh.shader_version); + } +} + +void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of bokeh depth of field with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + // setup our push constant + memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant)); + bokeh.push_constant.blur_far_active = p_dof_far; + bokeh.push_constant.blur_far_begin = p_dof_far_begin; + bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size; + + bokeh.push_constant.blur_near_active = p_dof_near; + bokeh.push_constant.blur_near_begin = p_dof_near_begin; + bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size); + bokeh.push_constant.use_jitter = p_use_jitter; + bokeh.push_constant.jitter_seed = Math::randf() * 1000.0; + + bokeh.push_constant.z_near = p_cam_znear; + bokeh.push_constant.z_far = p_cam_zfar; + bokeh.push_constant.orthogonal = p_cam_orthogonal; + bokeh.push_constant.blur_size = p_bokeh_size; + + bokeh.push_constant.second_pass = false; + bokeh.push_constant.half_size = false; + + bokeh.push_constant.blur_scale = 0.5; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_base_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.base_texture })); + RD::Uniform u_depth_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.depth_texture })); + RD::Uniform u_secondary_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.secondary_texture })); + RD::Uniform u_half_texture0(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[0] })); + RD::Uniform u_half_texture1(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[1] })); + + RD::Uniform u_base_image(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.base_texture); + RD::Uniform u_secondary_image(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.secondary_texture); + RD::Uniform u_half_image0(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.half_texture[0]); + RD::Uniform u_half_image1(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.half_texture[1]); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + /* FIRST PASS */ + // The alpha channel of the source color texture is filled with the expected circle size + // If used for DOF far, the size is positive, if used for near, its negative. + + RID shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BLUR_SIZE); + ERR_FAIL_COND(shader.is_null()); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BLUR_SIZE]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_texture), 1); + + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) { + //second pass + BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL; + shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[mode]); + + static const int quality_samples[4] = { 6, 12, 12, 24 }; + + bokeh.push_constant.steps = quality_samples[p_quality]; + + if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { + //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes) + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_base_texture), 1); + + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; + bokeh.push_constant.half_size = true; + bokeh.push_constant.blur_size *= 0.5; + + } else { + //medium and high quality use full size + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_secondary_image), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_base_texture), 1); + } + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //third pass + bokeh.push_constant.second_pass = true; + + if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image1), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1); + } else { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_secondary_texture), 1); + } + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { + //forth pass, upscale for low quality + + shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE); + ERR_FAIL_COND(shader.is_null()); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture1), 1); + + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y; + bokeh.push_constant.half_size = false; + bokeh.push_constant.second_pass = false; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1); + } + } else { + //circle + + shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BOKEH_CIRCULAR); + ERR_FAIL_COND(shader.is_null()); + + //second pass + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BOKEH_CIRCULAR]); + + static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 }; + + bokeh.push_constant.steps = 0; + bokeh.push_constant.blur_scale = quality_scale[p_quality]; + + //circle always runs in half size, otherwise too expensive + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_base_texture), 1); + + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; + bokeh.push_constant.half_size = true; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //circle is just one pass, then upscale + + // upscale + + shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE); + ERR_FAIL_COND(shader.is_null()); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1); + + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y; + bokeh.push_constant.half_size = false; + bokeh.push_constant.second_pass = false; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1); + } + + RD::get_singleton()->compute_list_end(); +} + +void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't blur-based depth of field with the clustered renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + // setup our base push constant + memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant)); + + bokeh.push_constant.orthogonal = p_cam_orthogonal; + bokeh.push_constant.size[0] = p_buffers.base_texture_size.width; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.height; + bokeh.push_constant.z_far = p_cam_zfar; + bokeh.push_constant.z_near = p_cam_znear; + + bokeh.push_constant.second_pass = false; + bokeh.push_constant.half_size = false; + bokeh.push_constant.blur_size = p_dof_blur_amount; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_base_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.base_texture })); + RD::Uniform u_depth_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.depth_texture })); + RD::Uniform u_secondary_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.secondary_texture })); + RD::Uniform u_half_texture0(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[0] })); + RD::Uniform u_half_texture1(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[1] })); + RD::Uniform u_weight_texture0(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[0] })); + RD::Uniform u_weight_texture1(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[1] })); + RD::Uniform u_weight_texture2(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[2] })); + RD::Uniform u_weight_texture3(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[3] })); + + if (p_dof_far || p_dof_near) { + if (p_dof_far) { + bokeh.push_constant.blur_far_active = true; + bokeh.push_constant.blur_far_begin = p_dof_far_begin; + bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size; + } + + if (p_dof_near) { + bokeh.push_constant.blur_near_active = true; + bokeh.push_constant.blur_near_begin = p_dof_near_begin; + bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size; + } + + { + // generate our depth data + RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BLUR_SIZE); + ERR_FAIL_COND(shader.is_null()); + + RID framebuffer = p_buffers.base_weight_fb; + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_depth_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + } + + if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) { + // double pass approach + BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL; + + RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { + //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes) + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; + bokeh.push_constant.half_size = true; + bokeh.push_constant.blur_size *= 0.5; + } + + static const int quality_samples[4] = { 6, 12, 12, 24 }; + bokeh.push_constant.blur_scale = 0.5; + bokeh.push_constant.steps = quality_samples[p_quality]; + + RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb; + + // Pass 1 + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + // Pass 2 + if (!bokeh.push_constant.half_size) { + // do not output weight, we're writing back into our base buffer + mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT; + + shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + } + bokeh.push_constant.second_pass = true; + + framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[1] : p_buffers.base_fb; + RD::Uniform texture = bokeh.push_constant.half_size ? u_half_texture0 : u_secondary_texture; + RD::Uniform weight = bokeh.push_constant.half_size ? u_weight_texture2 : u_weight_texture1; + + draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, texture), 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, weight), 1); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + if (bokeh.push_constant.half_size) { + // Compose pass + mode = BOKEH_COMPOSITE; + shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + framebuffer = p_buffers.base_fb; + + draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture1), 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture3), 1); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_weight_texture0), 2); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + } + + } else { + // circular is a single pass approach + BokehMode mode = BOKEH_GEN_BOKEH_CIRCULAR; + + RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + { + // circle always runs in half size, otherwise too expensive (though the code below does support making this optional) + bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; + bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; + bokeh.push_constant.half_size = true; + // bokeh.push_constant.blur_size *= 0.5; + } + + static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 }; + bokeh.push_constant.blur_scale = quality_scale[p_quality]; + bokeh.push_constant.steps = 0.0; + + RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb; + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + if (bokeh.push_constant.half_size) { + // Compose + mode = BOKEH_COMPOSITE; + shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + framebuffer = p_buffers.base_fb; + + draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture0), 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture2), 1); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_weight_texture0), 2); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + } else { + CopyEffects::get_singleton()->copy_raster(p_buffers.secondary_texture, p_buffers.base_fb); + } + } + } +} diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.h b/servers/rendering/renderer_rd/effects/bokeh_dof.h new file mode 100644 index 0000000000..d7b736119c --- /dev/null +++ b/servers/rendering/renderer_rd/effects/bokeh_dof.h @@ -0,0 +1,120 @@ +/*************************************************************************/ +/* bokeh_dof.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 BOKEH_DOF_RD_H +#define BOKEH_DOF_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl.gen.h" +#include "servers/rendering/renderer_scene_render.h" + +#include "servers/rendering_server.h" + +namespace RendererRD { + +class BokehDOF { +private: + bool prefer_raster_effects; + + struct BokehPushConstant { + uint32_t size[2]; + float z_far; + float z_near; + + uint32_t orthogonal; + float blur_size; + float blur_scale; + uint32_t steps; + + uint32_t blur_near_active; + float blur_near_begin; + float blur_near_end; + uint32_t blur_far_active; + + float blur_far_begin; + float blur_far_end; + uint32_t second_pass; + uint32_t half_size; + + uint32_t use_jitter; + float jitter_seed; + uint32_t pad[2]; + }; + + enum BokehMode { + BOKEH_GEN_BLUR_SIZE, + BOKEH_GEN_BOKEH_BOX, + BOKEH_GEN_BOKEH_BOX_NOWEIGHT, + BOKEH_GEN_BOKEH_HEXAGONAL, + BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, + BOKEH_GEN_BOKEH_CIRCULAR, + BOKEH_COMPOSITE, + BOKEH_MAX + }; + + struct Bokeh { + BokehPushConstant push_constant; + BokehDofShaderRD compute_shader; + BokehDofRasterShaderRD raster_shader; + RID shader_version; + RID compute_pipelines[BOKEH_MAX]; + PipelineCacheRD raster_pipelines[BOKEH_MAX]; + } bokeh; + +public: + struct BokehBuffers { + // bokeh buffers + + // textures + Size2i base_texture_size; + RID base_texture; + RID depth_texture; + RID secondary_texture; + RID half_texture[2]; + + // raster only + RID base_fb; + RID secondary_fb; // with weights + RID half_fb[2]; // with weights + RID base_weight_fb; + RID weight_texture[4]; + }; + + BokehDOF(bool p_prefer_raster_effects); + ~BokehDOF(); + + void bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal); + void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal); +}; + +} // namespace RendererRD + +#endif // !BOKEH_DOF_RD_H diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp new file mode 100644 index 0000000000..6b786fdf16 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -0,0 +1,683 @@ +/*************************************************************************/ +/* copy_effects.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 "copy_effects.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/uniform_set_cache_rd.h" + +using namespace RendererRD; + +CopyEffects *CopyEffects::singleton = nullptr; + +CopyEffects *CopyEffects::get_singleton() { + return singleton; +} + +CopyEffects::CopyEffects(bool p_prefer_raster_effects) { + singleton = this; + prefer_raster_effects = p_prefer_raster_effects; + + if (prefer_raster_effects) { + // init blur shader (on compute use copy shader) + + Vector<String> blur_modes; + blur_modes.push_back("\n#define MODE_MIPMAP\n"); // BLUR_MIPMAP + blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); // BLUR_MODE_GAUSSIAN_BLUR + blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW + blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE + blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY + + blur_raster.shader.initialize(blur_modes); + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); + blur_raster.shader_version = blur_raster.shader.version_create(); + + for (int i = 0; i < BLUR_MODE_MAX; i++) { + blur_raster.pipelines[i].setup(blur_raster.shader.version_get_shader(blur_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } + + } else { + // not used in clustered + for (int i = 0; i < BLUR_MODE_MAX; i++) { + blur_raster.pipelines[i].clear(); + } + + Vector<String> copy_modes; + copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); + copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define DST_IMAGE_8BIT\n"); + copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n"); + copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); + copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n"); + copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n"); + copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n"); + copy_modes.push_back("\n#define MODE_SET_COLOR\n"); + copy_modes.push_back("\n#define MODE_SET_COLOR\n#define DST_IMAGE_8BIT\n"); + copy_modes.push_back("\n#define MODE_MIPMAP\n"); + copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n"); + copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n"); + copy_modes.push_back("\n#define MODE_CUBEMAP_ARRAY_TO_PANORAMA\n"); + + copy.shader.initialize(copy_modes); + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + + copy.shader_version = copy.shader.version_create(); + + for (int i = 0; i < COPY_MODE_MAX; i++) { + if (copy.shader.is_variant_enabled(i)) { + copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i)); + } + } + } + + { + Vector<String> copy_modes; + copy_modes.push_back("\n"); + copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); + copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); + copy_modes.push_back("\n#define MULTIVIEW\n"); + copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); + + copy_to_fb.shader.initialize(copy_modes); + + if (!RendererCompositorRD::singleton->is_xr_enabled()) { + copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW, false); + copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW_WITH_DEPTH, false); + } + + copy_to_fb.shader_version = copy_to_fb.shader.version_create(); + + //use additive + + for (int i = 0; i < COPY_TO_FB_MAX; i++) { + if (copy_to_fb.shader.is_variant_enabled(i)) { + copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } else { + copy_to_fb.pipelines[i].clear(); + } + } + } +} + +CopyEffects::~CopyEffects() { + if (prefer_raster_effects) { + blur_raster.shader.version_free(blur_raster.shader_version); + } else { + copy.shader.version_free(copy.shader_version); + } + + copy_to_fb.shader.version_free(copy_to_fb.shader_version); + + singleton = nullptr; +} + +void CopyEffects::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst, bool p_alpha_to_one) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_to_rect shader with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + if (p_flip_y) { + copy.push_constant.flags |= COPY_FLAG_FLIP_Y; + } + + if (p_force_luminance) { + copy.push_constant.flags |= COPY_FLAG_FORCE_LUMINANCE; + } + + if (p_all_source) { + copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE; + } + + if (p_alpha_to_one) { + copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE; + } + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_rect.size.width; + copy.push_constant.section[3] = p_rect.size.height; + copy.push_constant.target[0] = p_rect.position.x; + copy.push_constant.target[1] = p_rect.position.y; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture); + + CopyMode mode = p_8_bit_dst ? COPY_MODE_SIMPLY_COPY_8BIT : COPY_MODE_SIMPLY_COPY; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_cubemap_to_panorama shader with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_panorama_size.width; + copy.push_constant.section[3] = p_panorama_size.height; + copy.push_constant.target[0] = 0; + copy.push_constant.target[1] = 0; + copy.push_constant.camera_z_far = p_lod; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_cube(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_cube })); + RD::Uniform u_dest_panorama(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_panorama); + + CopyMode mode = p_is_array ? COPY_MODE_CUBE_ARRAY_TO_PANORAMA : COPY_MODE_CUBE_TO_PANORAMA; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cube), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_panorama), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_panorama_size.width, p_panorama_size.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_depth_to_rect shader with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + if (p_flip_y) { + copy.push_constant.flags |= COPY_FLAG_FLIP_Y; + } + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_rect.size.width; + copy.push_constant.section[3] = p_rect.size.height; + copy.push_constant.target[0] = p_rect.position.x; + copy.push_constant.target[1] = p_rect.position.y; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture); + + CopyMode mode = COPY_MODE_SIMPLY_COPY_DEPTH; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_depth_to_rect_and_linearize shader with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + if (p_flip_y) { + copy.push_constant.flags |= COPY_FLAG_FLIP_Y; + } + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_rect.size.width; + copy.push_constant.section[3] = p_rect.size.height; + copy.push_constant.target[0] = p_rect.position.x; + copy.push_constant.target[1] = p_rect.position.y; + copy.push_constant.camera_z_far = p_z_far; + copy.push_constant.camera_z_near = p_z_near; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture); + + CopyMode mode = COPY_MODE_LINEARIZE_DEPTH; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); + + copy_to_fb.push_constant.use_section = true; + copy_to_fb.push_constant.section[0] = p_uv_rect.position.x; + copy_to_fb.push_constant.section[1] = p_uv_rect.position.y; + copy_to_fb.push_constant.section[2] = p_uv_rect.size.x; + copy_to_fb.push_constant.section[3] = p_uv_rect.size.y; + + if (p_flip_y) { + copy_to_fb.push_constant.flip_y = true; + } + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + CopyToFBMode mode = p_panorama ? COPY_TO_FB_COPY_PANORAMA_TO_DP : COPY_TO_FB_COPY; + RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = p_draw_list; + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); +} + +void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); + + if (p_flip_y) { + copy_to_fb.push_constant.flip_y = true; + } + if (p_force_luminance) { + copy_to_fb.push_constant.force_luminance = true; + } + if (p_alpha_to_zero) { + copy_to_fb.push_constant.alpha_to_zero = true; + } + if (p_srgb) { + copy_to_fb.push_constant.srgb = true; + } + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + CopyToFBMode mode; + if (p_multiview) { + mode = p_secondary.is_valid() ? COPY_TO_FB_MULTIVIEW_WITH_DEPTH : COPY_TO_FB_MULTIVIEW; + } else { + mode = p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY; + } + + RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + if (p_secondary.is_valid()) { + // TODO may need to do this differently when reading from depth buffer for multiview + RD::Uniform u_secondary(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_secondary })); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_secondary), 1); + } + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the copy with the clustered renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_texture })); + + RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, BLUR_MODE_COPY); + ERR_FAIL_COND(shader.is_null()); + + // Just copy it back (we use our blur raster shader here).. + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + + copy.push_constant.section[0] = p_region.position.x; + copy.push_constant.section[1] = p_region.position.y; + copy.push_constant.section[2] = p_region.size.width; + copy.push_constant.section[3] = p_region.size.height; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_texture); + + CopyMode mode = p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + //HORIZONTAL + RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_texture), 3); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1); + + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + + CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW; + uint32_t base_flags = 0; + + copy.push_constant.section[2] = p_size.x; + copy.push_constant.section[3] = p_size.y; + + copy.push_constant.glow_strength = p_strength; + copy.push_constant.glow_bloom = p_bloom; + copy.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold; + copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale; + copy.push_constant.glow_exposure = p_exposure; + copy.push_constant.glow_white = 0; //actually unused + copy.push_constant.glow_luminance_cap = p_luminance_cap; + + copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_back_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_back_texture); + + RID shader = copy.shader.version_get_shader(copy.shader_version, copy_mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_back_texture), 3); + if (p_auto_exposure.is_valid() && p_first_pass) { + RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1); + } + + copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); + + BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW; + uint32_t base_flags = 0; + + blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x); + blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y); + + blur_raster.push_constant.glow_strength = p_strength; + blur_raster.push_constant.glow_bloom = p_bloom; + blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold; + blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale; + blur_raster.push_constant.glow_exposure = p_exposure; + blur_raster.push_constant.glow_white = 0; //actually unused + blur_raster.push_constant.glow_luminance_cap = p_luminance_cap; + + blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also + + blur_raster.push_constant.luminance_multiplier = p_luminance_multiplier; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_rd_texture_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_rd_texture_half })); + + RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode); + ERR_FAIL_COND(shader.is_null()); + + //HORIZONTAL + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + if (p_auto_exposure.is_valid() && p_first_pass) { + RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure })); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1); + } + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + blur_mode = BLUR_MODE_GAUSSIAN_GLOW; + + shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode); + ERR_FAIL_COND(shader.is_null()); + + //VERTICAL + draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_rd_texture_half), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + blur_raster.push_constant.flags = base_flags; + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void CopyEffects::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the make_mipmap shader with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_size.width; + copy.push_constant.section[3] = p_size.height; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture); + + CopyMode mode = COPY_MODE_MIPMAP; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); + + BlurRasterMode mode = BLUR_MIPMAP; + + blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x); + blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y); + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the set_color shader with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + + memset(©.push_constant, 0, sizeof(CopyPushConstant)); + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_region.size.width; + copy.push_constant.section[3] = p_region.size.height; + copy.push_constant.target[0] = p_region.position.x; + copy.push_constant.target[1] = p_region.position.y; + copy.push_constant.set_color[0] = p_color.r; + copy.push_constant.set_color[1] = p_color.g; + copy.push_constant.set_color[2] = p_color.b; + copy.push_constant.set_color[3] = p_color.a; + + // setup our uniforms + RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture); + + CopyMode mode = p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR; + RID shader = copy.shader.version_get_shader(copy.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1); + RD::get_singleton()->compute_list_end(); +} diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h new file mode 100644 index 0000000000..e522408d20 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/copy_effects.h @@ -0,0 +1,220 @@ +/*************************************************************************/ +/* copy_effects.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 COPY_RD_H +#define COPY_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/copy.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl.gen.h" +#include "servers/rendering/renderer_scene_render.h" + +#include "servers/rendering_server.h" + +namespace RendererRD { + +class CopyEffects { +private: + bool prefer_raster_effects; + + // Blur raster shader + + enum BlurRasterMode { + BLUR_MIPMAP, + + BLUR_MODE_GAUSSIAN_BLUR, + BLUR_MODE_GAUSSIAN_GLOW, + BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, + BLUR_MODE_COPY, + + BLUR_MODE_MAX + }; + + enum { + BLUR_FLAG_HORIZONTAL = (1 << 0), + BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 1), + BLUR_FLAG_GLOW_FIRST_PASS = (1 << 2), + }; + + struct BlurRasterPushConstant { + float pixel_size[2]; + uint32_t flags; + uint32_t pad; + + //glow + float glow_strength; + float glow_bloom; + float glow_hdr_threshold; + float glow_hdr_scale; + + float glow_exposure; + float glow_white; + float glow_luminance_cap; + float glow_auto_exposure_grey; + + float luminance_multiplier; + float res1; + float res2; + float res3; + }; + + struct BlurRaster { + BlurRasterPushConstant push_constant; + BlurRasterShaderRD shader; + RID shader_version; + PipelineCacheRD pipelines[BLUR_MODE_MAX]; + } blur_raster; + + // Copy shader + + enum CopyMode { + COPY_MODE_GAUSSIAN_COPY, + COPY_MODE_GAUSSIAN_COPY_8BIT, + COPY_MODE_GAUSSIAN_GLOW, + COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, + COPY_MODE_SIMPLY_COPY, + COPY_MODE_SIMPLY_COPY_8BIT, + COPY_MODE_SIMPLY_COPY_DEPTH, + COPY_MODE_SET_COLOR, + COPY_MODE_SET_COLOR_8BIT, + COPY_MODE_MIPMAP, + COPY_MODE_LINEARIZE_DEPTH, + COPY_MODE_CUBE_TO_PANORAMA, + COPY_MODE_CUBE_ARRAY_TO_PANORAMA, + COPY_MODE_MAX, + + }; + + enum { + COPY_FLAG_HORIZONTAL = (1 << 0), + COPY_FLAG_USE_COPY_SECTION = (1 << 1), + COPY_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2), + COPY_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3), + COPY_FLAG_GLOW_FIRST_PASS = (1 << 4), + COPY_FLAG_FLIP_Y = (1 << 5), + COPY_FLAG_FORCE_LUMINANCE = (1 << 6), + COPY_FLAG_ALL_SOURCE = (1 << 7), + COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8), + COPY_FLAG_ALPHA_TO_ONE = (1 << 9), + }; + + struct CopyPushConstant { + int32_t section[4]; + int32_t target[2]; + uint32_t flags; + uint32_t pad; + // Glow. + float glow_strength; + float glow_bloom; + float glow_hdr_threshold; + float glow_hdr_scale; + + float glow_exposure; + float glow_white; + float glow_luminance_cap; + float glow_auto_exposure_grey; + // DOF. + float camera_z_far; + float camera_z_near; + uint32_t pad2[2]; + //SET color + float set_color[4]; + }; + + struct Copy { + CopyPushConstant push_constant; + CopyShaderRD shader; + RID shader_version; + RID pipelines[COPY_MODE_MAX]; + + } copy; + + // Copy to FB shader + + enum CopyToFBMode { + COPY_TO_FB_COPY, + COPY_TO_FB_COPY_PANORAMA_TO_DP, + COPY_TO_FB_COPY2, + + COPY_TO_FB_MULTIVIEW, + COPY_TO_FB_MULTIVIEW_WITH_DEPTH, + COPY_TO_FB_MAX, + }; + + struct CopyToFbPushConstant { + float section[4]; + float pixel_size[2]; + uint32_t flip_y; + uint32_t use_section; + + uint32_t force_luminance; + uint32_t alpha_to_zero; + uint32_t srgb; + uint32_t pad; + }; + + struct CopyToFb { + CopyToFbPushConstant push_constant; + CopyToFbShaderRD shader; + RID shader_version; + PipelineCacheRD pipelines[COPY_TO_FB_MAX]; + + } copy_to_fb; + + static CopyEffects *singleton; + +public: + static CopyEffects *get_singleton(); + + CopyEffects(bool p_prefer_raster_effects); + ~CopyEffects(); + + void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false); + void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array); + void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false); + void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far); + void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false); + void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false); + void copy_raster(RID p_source_texture, RID p_dest_framebuffer); + + void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false); + void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); + void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); + + void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size); + void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size); + + void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false); +}; + +} // namespace RendererRD + +#endif // !COPY_RD_H diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.cpp b/servers/rendering/renderer_rd/effects/tone_mapper.cpp index e5642116bb..38a4a37b8a 100644 --- a/servers/rendering/renderer_rd/effects/tone_mapper.cpp +++ b/servers/rendering/renderer_rd/effects/tone_mapper.cpp @@ -75,28 +75,9 @@ ToneMapper::ToneMapper() { } } } - - // TODO maybe centralise this in mesh_storage? - { //create index array for copy shaders - Vector<uint8_t> pv; - pv.resize(6 * 4); - { - uint8_t *w = pv.ptrw(); - int *p32 = (int *)w; - p32[0] = 0; - p32[1] = 1; - p32[2] = 2; - p32[3] = 0; - p32[4] = 2; - p32[5] = 3; - } - index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv); - index_array = RD::get_singleton()->index_array_create(index_buffer, 0, 6); - } } ToneMapper::~ToneMapper() { - RD::get_singleton()->free(index_buffer); //array gets freed as dependency tonemap.shader.version_free(tonemap.shader_version); } @@ -154,11 +135,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - RD::Uniform u_source_color; - u_source_color.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u_source_color.binding = 0; - u_source_color.append_id(default_sampler); - u_source_color.append_id(p_source_color); + RD::Uniform u_source_color(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_color })); RD::Uniform u_exposure_texture; u_exposure_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; @@ -193,7 +170,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_glow_texture, u_glow_map), 2); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 3, u_color_correction_texture), 3); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); RD::get_singleton()->draw_list_set_push_constant(draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant)); RD::get_singleton()->draw_list_draw(draw_list, true); @@ -273,7 +250,7 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1); // should be set to a default texture, it's ignored RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 2, u_glow_texture, u_glow_map), 2); // should be set to a default texture, it's ignored RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 3, u_color_correction_texture), 3); - RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, index_array); + RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, material_storage->get_quad_index_array()); RD::get_singleton()->draw_list_set_push_constant(p_subpass_draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant)); RD::get_singleton()->draw_list_draw(p_subpass_draw_list, true); diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.h b/servers/rendering/renderer_rd/effects/tone_mapper.h index 357e814845..a90849dbeb 100644 --- a/servers/rendering/renderer_rd/effects/tone_mapper.h +++ b/servers/rendering/renderer_rd/effects/tone_mapper.h @@ -96,9 +96,6 @@ private: PipelineCacheRD pipelines[TONEMAP_MODE_MAX]; } tonemap; - RID index_buffer; - RID index_array; - public: ToneMapper(); ~ToneMapper(); diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index f05027d569..774745abdc 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -86,7 +86,7 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) u.append_id(p_texture); uniforms.push_back(u); // anything with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, 0), 0); + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0), 0); texture_to_uniform_set_cache[p_texture] = uniform_set; @@ -252,295 +252,6 @@ void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RI RD::get_singleton()->compute_list_end(compute_list); } -void EffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) { - memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); - - copy_to_fb.push_constant.use_section = true; - copy_to_fb.push_constant.section[0] = p_uv_rect.position.x; - copy_to_fb.push_constant.section[1] = p_uv_rect.position.y; - copy_to_fb.push_constant.section[2] = p_uv_rect.size.x; - copy_to_fb.push_constant.section[3] = p_uv_rect.size.y; - - if (p_flip_y) { - copy_to_fb.push_constant.flip_y = true; - } - - RD::DrawListID draw_list = p_draw_list; - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[p_panorama ? COPY_TO_FB_COPY_PANORAMA_TO_DP : COPY_TO_FB_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); -} - -void EffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview) { - memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); - - if (p_flip_y) { - copy_to_fb.push_constant.flip_y = true; - } - if (p_force_luminance) { - copy_to_fb.push_constant.force_luminance = true; - } - if (p_alpha_to_zero) { - copy_to_fb.push_constant.alpha_to_zero = true; - } - if (p_srgb) { - copy_to_fb.push_constant.srgb = true; - } - - CopyToFBMode mode; - if (p_multiview) { - mode = p_secondary.is_valid() ? COPY_TO_FB_MULTIVIEW_WITH_DEPTH : COPY_TO_FB_MULTIVIEW; - } else { - mode = p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY; - } - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - if (p_secondary.is_valid()) { - // TODO may need to do this differently when reading from depth buffer for multiview - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_secondary), 1); - } - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - -void EffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst, bool p_alpha_to_one) { - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - if (p_flip_y) { - copy.push_constant.flags |= COPY_FLAG_FLIP_Y; - } - - if (p_force_luminance) { - copy.push_constant.flags |= COPY_FLAG_FORCE_LUMINANCE; - } - - if (p_all_source) { - copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE; - } - - if (p_alpha_to_one) { - copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE; - } - - copy.push_constant.section[0] = 0; - copy.push_constant.section[1] = 0; - copy.push_constant.section[2] = p_rect.size.width; - copy.push_constant.section[3] = p_rect.size.height; - copy.push_constant.target[0] = p_rect.position.x; - copy.push_constant.target[1] = p_rect.position.y; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8_bit_dst ? COPY_MODE_SIMPLY_COPY_8BIT : COPY_MODE_SIMPLY_COPY]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array) { - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - - copy.push_constant.section[0] = 0; - copy.push_constant.section[1] = 0; - copy.push_constant.section[2] = p_panorama_size.width; - copy.push_constant.section[3] = p_panorama_size.height; - copy.push_constant.target[0] = 0; - copy.push_constant.target[1] = 0; - copy.push_constant.camera_z_far = p_lod; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_is_array ? COPY_MODE_CUBE_ARRAY_TO_PANORAMA : COPY_MODE_CUBE_TO_PANORAMA]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cube), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_panorama), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_panorama_size.width, p_panorama_size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far) { - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - if (p_flip_y) { - copy.push_constant.flags |= COPY_FLAG_FLIP_Y; - } - - copy.push_constant.section[0] = 0; - copy.push_constant.section[1] = 0; - copy.push_constant.section[2] = p_rect.size.width; - copy.push_constant.section[3] = p_rect.size.height; - copy.push_constant.target[0] = p_rect.position.x; - copy.push_constant.target[1] = p_rect.position.y; - copy.push_constant.camera_z_far = p_z_far; - copy.push_constant.camera_z_near = p_z_near; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_LINEARIZE_DEPTH]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) { - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - if (p_flip_y) { - copy.push_constant.flags |= COPY_FLAG_FLIP_Y; - } - - copy.push_constant.section[0] = 0; - copy.push_constant.section[1] = 0; - copy.push_constant.section[2] = p_rect.size.width; - copy.push_constant.section[3] = p_rect.size.height; - copy.push_constant.target[0] = p_rect.position.x; - copy.push_constant.target[1] = p_rect.position.y; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_SIMPLY_COPY_DEPTH]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) { - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - - copy.push_constant.section[0] = 0; - copy.push_constant.section[1] = 0; - copy.push_constant.section[2] = p_region.size.width; - copy.push_constant.section[3] = p_region.size.height; - copy.push_constant.target[0] = p_region.position.x; - copy.push_constant.target[1] = p_region.position.y; - copy.push_constant.set_color[0] = p_color.r; - copy.push_constant.set_color[1] = p_color.g; - copy.push_constant.set_color[2] = p_color.b; - copy.push_constant.set_color[3] = p_color.a; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst) { - ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer."); - - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - - copy.push_constant.section[0] = p_region.position.x; - copy.push_constant.section[1] = p_region.position.y; - copy.push_constant.section[2] = p_region.size.width; - copy.push_constant.section[3] = p_region.size.height; - - //HORIZONTAL - RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 3); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1); - - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { - ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer."); - - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - - CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW; - uint32_t base_flags = 0; - - copy.push_constant.section[2] = p_size.x; - copy.push_constant.section[3] = p_size.y; - - copy.push_constant.glow_strength = p_strength; - copy.push_constant.glow_bloom = p_bloom; - copy.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold; - copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale; - copy.push_constant.glow_exposure = p_exposure; - copy.push_constant.glow_white = 0; //actually unused - copy.push_constant.glow_luminance_cap = p_luminance_cap; - - copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 3); - if (p_auto_exposure.is_valid() && p_first_pass) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_auto_exposure), 1); - } - - copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { - ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer."); - - memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); - - BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW; - uint32_t base_flags = 0; - - blur_raster.push_constant.pixel_size[0] = p_pixel_size.x; - blur_raster.push_constant.pixel_size[1] = p_pixel_size.y; - - blur_raster.push_constant.glow_strength = p_strength; - blur_raster.push_constant.glow_bloom = p_bloom; - blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold; - blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale; - blur_raster.push_constant.glow_exposure = p_exposure; - blur_raster.push_constant.glow_white = 0; //actually unused - blur_raster.push_constant.glow_luminance_cap = p_luminance_cap; - - blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also - - //HORIZONTAL - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - if (p_auto_exposure.is_valid() && p_first_pass) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_auto_exposure), 1); - } - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - - blur_mode = BLUR_MODE_GAUSSIAN_GLOW; - - //VERTICAL - draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - blur_raster.push_constant.flags = base_flags; - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) { RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -733,43 +444,6 @@ void EffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_bas RD::get_singleton()->draw_list_end(); } -void EffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) { - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - - copy.push_constant.section[0] = 0; - copy.push_constant.section[1] = 0; - copy.push_constant.section[2] = p_size.width; - copy.push_constant.section[3] = p_size.height; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_MIPMAP]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) { - ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer."); - - memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); - - BlurRasterMode mode = BLUR_MIPMAP; - - blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x); - blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y); - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) { CopyToDPPushConstant push_constant; push_constant.screen_rect[0] = p_rect.position.x; @@ -865,332 +539,6 @@ void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_ } } -void EffectsRD::bokeh_dof(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) { - ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of BOKEH DOF with the mobile renderer."); - - bokeh.push_constant.blur_far_active = p_dof_far; - bokeh.push_constant.blur_far_begin = p_dof_far_begin; - bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size; - - bokeh.push_constant.blur_near_active = p_dof_near; - bokeh.push_constant.blur_near_begin = p_dof_near_begin; - bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size); - bokeh.push_constant.use_jitter = p_use_jitter; - bokeh.push_constant.jitter_seed = Math::randf() * 1000.0; - - bokeh.push_constant.z_near = p_cam_znear; - bokeh.push_constant.z_far = p_cam_zfar; - bokeh.push_constant.orthogonal = p_cam_orthogonal; - bokeh.push_constant.blur_size = p_bokeh_size; - - bokeh.push_constant.second_pass = false; - bokeh.push_constant.half_size = false; - - bokeh.push_constant.blur_scale = 0.5; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - /* FIRST PASS */ - // The alpha channel of the source color texture is filled with the expected circle size - // If used for DOF far, the size is positive, if used for near, its negative. - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BLUR_SIZE]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.depth_texture), 1); - - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) { - //second pass - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL]); - - static const int quality_samples[4] = { 6, 12, 12, 24 }; - - bokeh.push_constant.steps = quality_samples[p_quality]; - - if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { - //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes) - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[0]), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1); - - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; - bokeh.push_constant.half_size = true; - bokeh.push_constant.blur_size *= 0.5; - - } else { - //medium and high quality use full size - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.secondary_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1); - } - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - //third pass - bokeh.push_constant.second_pass = true; - - if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[1]), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[0]), 1); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.secondary_texture), 1); - } - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { - //forth pass, upscale for low quality - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[1]), 1); - - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y; - bokeh.push_constant.half_size = false; - bokeh.push_constant.second_pass = false; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1); - } - } else { - //circle - - //second pass - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BOKEH_CIRCULAR]); - - static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 }; - - bokeh.push_constant.steps = 0; - bokeh.push_constant.blur_scale = quality_scale[p_quality]; - - //circle always runs in half size, otherwise too expensive - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[0]), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1); - - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; - bokeh.push_constant.half_size = true; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - //circle is just one pass, then upscale - - // upscale - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[0]), 1); - - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y; - bokeh.push_constant.half_size = false; - bokeh.push_constant.second_pass = false; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1); - } - - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) { - ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use blur DOF with the clustered renderer."); - - memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant)); - - bokeh.push_constant.orthogonal = p_cam_orthogonal; - bokeh.push_constant.size[0] = p_buffers.base_texture_size.width; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.height; - bokeh.push_constant.z_far = p_cam_zfar; - bokeh.push_constant.z_near = p_cam_znear; - - bokeh.push_constant.second_pass = false; - bokeh.push_constant.half_size = false; - bokeh.push_constant.blur_size = p_dof_blur_amount; - - if (p_dof_far || p_dof_near) { - if (p_dof_far) { - bokeh.push_constant.blur_far_active = true; - bokeh.push_constant.blur_far_begin = p_dof_far_begin; - bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size; - } - - if (p_dof_near) { - bokeh.push_constant.blur_near_active = true; - bokeh.push_constant.blur_near_begin = p_dof_near_begin; - bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size; - } - - { - // generate our depth data - RID framebuffer = p_buffers.base_weight_fb; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.depth_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - } - - if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) { - // double pass approach - BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL; - - if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { - //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes) - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; - bokeh.push_constant.half_size = true; - bokeh.push_constant.blur_size *= 0.5; - } - - static const int quality_samples[4] = { 6, 12, 12, 24 }; - bokeh.push_constant.blur_scale = 0.5; - bokeh.push_constant.steps = quality_samples[p_quality]; - - RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb; - - // Pass 1 - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.base_texture), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 1); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - - // Pass 2 - if (!bokeh.push_constant.half_size) { - // do not output weight, we're writing back into our base buffer - mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT; - } - bokeh.push_constant.second_pass = true; - - framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[1] : p_buffers.base_fb; - RID texture = bokeh.push_constant.half_size ? p_buffers.half_texture[0] : p_buffers.secondary_texture; - RID weight = bokeh.push_constant.half_size ? p_buffers.weight_texture[2] : p_buffers.weight_texture[1]; - - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(texture), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(weight), 1); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - - if (bokeh.push_constant.half_size) { - // Compose pass - mode = BOKEH_COMPOSITE; - framebuffer = p_buffers.base_fb; - - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.half_texture[1]), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[3]), 1); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 2); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - } - - } else { - // circular is a single pass approach - BokehMode mode = BOKEH_GEN_BOKEH_CIRCULAR; - - { - // circle always runs in half size, otherwise too expensive (though the code below does support making this optional) - bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1; - bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1; - bokeh.push_constant.half_size = true; - // bokeh.push_constant.blur_size *= 0.5; - } - - static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 }; - bokeh.push_constant.blur_scale = quality_scale[p_quality]; - bokeh.push_constant.steps = 0.0; - - RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb; - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.base_texture), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 1); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - - if (bokeh.push_constant.half_size) { - // Compose - mode = BOKEH_COMPOSITE; - framebuffer = p_buffers.base_fb; - - draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.half_texture[0]), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[2]), 1); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 2); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - } else { - // Just copy it back (we use our blur raster shader here).. - draw_list = RD::get_singleton()->draw_list_begin(p_buffers.base_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_buffers.base_fb))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.secondary_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - } - } - } -} - void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection) { // Downsample and deinterleave the depth buffer for SSAO and SSIL RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -2152,94 +1500,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { prefer_raster_effects = p_prefer_raster_effects; - if (prefer_raster_effects) { - // init blur shader (on compute use copy shader) - - Vector<String> blur_modes; - blur_modes.push_back("\n#define MODE_MIPMAP\n"); // BLUR_MIPMAP - blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); // BLUR_MODE_GAUSSIAN_BLUR - blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW - blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE - blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY - - blur_raster.shader.initialize(blur_modes); - memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); - blur_raster.shader_version = blur_raster.shader.version_create(); - - for (int i = 0; i < BLUR_MODE_MAX; i++) { - blur_raster.pipelines[i].setup(blur_raster.shader.version_get_shader(blur_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); - } - - } else { - // not used in clustered - for (int i = 0; i < BLUR_MODE_MAX; i++) { - blur_raster.pipelines[i].clear(); - } - } - - if (!prefer_raster_effects) { // Initialize copy - Vector<String> copy_modes; - copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); - copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define DST_IMAGE_8BIT\n"); - copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n"); - copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); - copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n"); - copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n"); - copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n"); - copy_modes.push_back("\n#define MODE_SET_COLOR\n"); - copy_modes.push_back("\n#define MODE_SET_COLOR\n#define DST_IMAGE_8BIT\n"); - copy_modes.push_back("\n#define MODE_MIPMAP\n"); - copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n"); - copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n"); - copy_modes.push_back("\n#define MODE_CUBEMAP_ARRAY_TO_PANORAMA\n"); - - copy.shader.initialize(copy_modes); - memset(©.push_constant, 0, sizeof(CopyPushConstant)); - - if (prefer_raster_effects) { - // disable shaders we can't use - copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_COPY, false); - copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_COPY_8BIT, false); - copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_GLOW, false); - copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, false); - } - - copy.shader_version = copy.shader.version_create(); - - for (int i = 0; i < COPY_MODE_MAX; i++) { - if (copy.shader.is_variant_enabled(i)) { - copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i)); - } - } - } - { - Vector<String> copy_modes; - copy_modes.push_back("\n"); - copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); - copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); - copy_modes.push_back("\n#define MULTIVIEW\n"); - copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); - - copy_to_fb.shader.initialize(copy_modes); - - if (!RendererCompositorRD::singleton->is_xr_enabled()) { - copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW, false); - copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW_WITH_DEPTH, false); - } - - copy_to_fb.shader_version = copy_to_fb.shader.version_create(); - - //use additive - - for (int i = 0; i < COPY_TO_FB_MAX; i++) { - if (copy_to_fb.shader.is_variant_enabled(i)) { - copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); - } else { - copy_to_fb.pipelines[i].clear(); - } - } - } - { // Initialize roughness Vector<String> cubemap_roughness_modes; @@ -2311,42 +1571,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0); } - // Initialize bokeh - Vector<String> bokeh_modes; - bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n#define OUTPUT_WEIGHT\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n#define OUTPUT_WEIGHT\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n#define OUTPUT_WEIGHT\n"); - bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n"); - if (prefer_raster_effects) { - bokeh.raster_shader.initialize(bokeh_modes); - - bokeh.shader_version = bokeh.raster_shader.version_create(); - - const int att_count[BOKEH_MAX] = { 1, 2, 1, 2, 1, 2, 1 }; - for (int i = 0; i < BOKEH_MAX; i++) { - RD::PipelineColorBlendState blend_state = (i == BOKEH_COMPOSITE) ? RD::PipelineColorBlendState::create_blend(att_count[i]) : RD::PipelineColorBlendState::create_disabled(att_count[i]); - bokeh.raster_pipelines[i].setup(bokeh.raster_shader.version_get_shader(bokeh.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); - } - } else { - bokeh.compute_shader.initialize(bokeh_modes); - bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_BOX_NOWEIGHT, false); - bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, false); - bokeh.shader_version = bokeh.compute_shader.version_create(); - - for (int i = 0; i < BOKEH_MAX; i++) { - if (bokeh.compute_shader.is_variant_enabled(i)) { - bokeh.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.compute_shader.version_get_shader(bokeh.shader_version, i)); - } - } - - for (int i = 0; i < BOKEH_MAX; i++) { - bokeh.raster_pipelines[i].clear(); - } - } - if (!prefer_raster_effects) { { // Initialize depth buffer for screen space effects @@ -2837,21 +2061,17 @@ EffectsRD::~EffectsRD() { FSR_upscale.shader.version_free(FSR_upscale.shader_version); if (prefer_raster_effects) { - blur_raster.shader.version_free(blur_raster.shader_version); - bokeh.raster_shader.version_free(blur_raster.shader_version); luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version); roughness.raster_shader.version_free(roughness.shader_version); cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version); filter.raster_shader.version_free(filter.shader_version); } else { - bokeh.compute_shader.version_free(bokeh.shader_version); luminance_reduce.shader.version_free(luminance_reduce.shader_version); roughness.compute_shader.version_free(roughness.shader_version); cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version); filter.compute_shader.version_free(filter.shader_version); } if (!prefer_raster_effects) { - copy.shader.version_free(copy.shader_version); resolve.shader.version_free(resolve.shader_version); specular_merge.shader.version_free(specular_merge.shader_version); ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version); @@ -2875,7 +2095,6 @@ EffectsRD::~EffectsRD() { RD::get_singleton()->free(ssil.importance_map_load_counter); RD::get_singleton()->free(ssil.projection_uniform_buffer); } - copy_to_fb.shader.version_free(copy_to_fb.shader_version); cube_to_dp.shader.version_free(cube_to_dp.shader_version); sort.shader.version_free(sort.shader_version); } diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index 8174e30238..1963935236 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -33,11 +33,6 @@ #include "core/math/camera_matrix.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" -#include "servers/rendering/renderer_rd/shaders/blur_raster.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/bokeh_dof.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/copy.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/copy_to_fb.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/cube_to_dp.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl.gen.h" @@ -95,140 +90,6 @@ private: RID pipeline; } FSR_upscale; - enum BlurRasterMode { - BLUR_MIPMAP, - - BLUR_MODE_GAUSSIAN_BLUR, - BLUR_MODE_GAUSSIAN_GLOW, - BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, - BLUR_MODE_COPY, - - BLUR_MODE_MAX - }; - - enum { - BLUR_FLAG_HORIZONTAL = (1 << 0), - BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 1), - BLUR_FLAG_GLOW_FIRST_PASS = (1 << 2), - }; - - struct BlurRasterPushConstant { - float pixel_size[2]; - uint32_t flags; - uint32_t pad; - - //glow - float glow_strength; - float glow_bloom; - float glow_hdr_threshold; - float glow_hdr_scale; - - float glow_exposure; - float glow_white; - float glow_luminance_cap; - float glow_auto_exposure_grey; - }; - - struct BlurRaster { - BlurRasterPushConstant push_constant; - BlurRasterShaderRD shader; - RID shader_version; - PipelineCacheRD pipelines[BLUR_MODE_MAX]; - } blur_raster; - - enum CopyMode { - COPY_MODE_GAUSSIAN_COPY, - COPY_MODE_GAUSSIAN_COPY_8BIT, - COPY_MODE_GAUSSIAN_GLOW, - COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, - COPY_MODE_SIMPLY_COPY, - COPY_MODE_SIMPLY_COPY_8BIT, - COPY_MODE_SIMPLY_COPY_DEPTH, - COPY_MODE_SET_COLOR, - COPY_MODE_SET_COLOR_8BIT, - COPY_MODE_MIPMAP, - COPY_MODE_LINEARIZE_DEPTH, - COPY_MODE_CUBE_TO_PANORAMA, - COPY_MODE_CUBE_ARRAY_TO_PANORAMA, - COPY_MODE_MAX, - - }; - - enum { - COPY_FLAG_HORIZONTAL = (1 << 0), - COPY_FLAG_USE_COPY_SECTION = (1 << 1), - COPY_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2), - COPY_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3), - COPY_FLAG_GLOW_FIRST_PASS = (1 << 4), - COPY_FLAG_FLIP_Y = (1 << 5), - COPY_FLAG_FORCE_LUMINANCE = (1 << 6), - COPY_FLAG_ALL_SOURCE = (1 << 7), - COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8), - COPY_FLAG_ALPHA_TO_ONE = (1 << 9), - }; - - struct CopyPushConstant { - int32_t section[4]; - int32_t target[2]; - uint32_t flags; - uint32_t pad; - // Glow. - float glow_strength; - float glow_bloom; - float glow_hdr_threshold; - float glow_hdr_scale; - - float glow_exposure; - float glow_white; - float glow_luminance_cap; - float glow_auto_exposure_grey; - // DOF. - float camera_z_far; - float camera_z_near; - uint32_t pad2[2]; - //SET color - float set_color[4]; - }; - - struct Copy { - CopyPushConstant push_constant; - CopyShaderRD shader; - RID shader_version; - RID pipelines[COPY_MODE_MAX]; - - } copy; - - enum CopyToFBMode { - COPY_TO_FB_COPY, - COPY_TO_FB_COPY_PANORAMA_TO_DP, - COPY_TO_FB_COPY2, - - COPY_TO_FB_MULTIVIEW, - COPY_TO_FB_MULTIVIEW_WITH_DEPTH, - COPY_TO_FB_MAX, - - }; - - struct CopyToFbPushConstant { - float section[4]; - float pixel_size[2]; - uint32_t flip_y; - uint32_t use_section; - - uint32_t force_luminance; - uint32_t alpha_to_zero; - uint32_t srgb; - uint32_t pad; - }; - - struct CopyToFb { - CopyToFbPushConstant push_constant; - CopyToFbShaderRD shader; - RID shader_version; - PipelineCacheRD pipelines[COPY_TO_FB_MAX]; - - } copy_to_fb; - struct CubemapRoughnessPushConstant { uint32_t face_id; uint32_t sample_count; @@ -305,51 +166,6 @@ private: PipelineCacheRD pipeline; } cube_to_dp; - struct BokehPushConstant { - uint32_t size[2]; - float z_far; - float z_near; - - uint32_t orthogonal; - float blur_size; - float blur_scale; - uint32_t steps; - - uint32_t blur_near_active; - float blur_near_begin; - float blur_near_end; - uint32_t blur_far_active; - - float blur_far_begin; - float blur_far_end; - uint32_t second_pass; - uint32_t half_size; - - uint32_t use_jitter; - float jitter_seed; - uint32_t pad[2]; - }; - - enum BokehMode { - BOKEH_GEN_BLUR_SIZE, - BOKEH_GEN_BOKEH_BOX, - BOKEH_GEN_BOKEH_BOX_NOWEIGHT, - BOKEH_GEN_BOKEH_HEXAGONAL, - BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, - BOKEH_GEN_BOKEH_CIRCULAR, - BOKEH_COMPOSITE, - BOKEH_MAX - }; - - struct Bokeh { - BokehPushConstant push_constant; - BokehDofShaderRD compute_shader; - BokehDofRasterShaderRD raster_shader; - RID shader_version; - RID compute_pipelines[BOKEH_MAX]; - PipelineCacheRD raster_pipelines[BOKEH_MAX]; - } bokeh; - struct SSEffectsDownsamplePushConstant { float pixel_size[2]; float z_far; @@ -792,10 +608,10 @@ private: RID index_buffer; RID index_array; - Map<RID, RID> texture_to_uniform_set_cache; - Map<RID, RID> input_to_uniform_set_cache; + HashMap<RID, RID> texture_to_uniform_set_cache; + HashMap<RID, RID> input_to_uniform_set_cache; - Map<RID, RID> image_to_uniform_set_cache; + HashMap<RID, RID> image_to_uniform_set_cache; struct TexturePair { RID texture1; @@ -821,11 +637,11 @@ private: } }; - Map<TexturePair, RID> texture_pair_to_uniform_set_cache; - Map<RID, RID> texture_to_compute_uniform_set_cache; - Map<TexturePair, RID> texture_pair_to_compute_uniform_set_cache; - Map<TexturePair, RID> image_pair_to_compute_uniform_set_cache; - Map<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache; + RBMap<TexturePair, RID> texture_pair_to_uniform_set_cache; + RBMap<RID, RID> texture_to_compute_uniform_set_cache; + RBMap<TexturePair, RID> texture_pair_to_compute_uniform_set_cache; + RBMap<TexturePair, RID> image_pair_to_compute_uniform_set_cache; + RBMap<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache; RID _get_uniform_set_from_image(RID p_texture); RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); @@ -838,46 +654,13 @@ public: bool get_prefer_raster_effects(); void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness); - void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false); - void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false); - void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array); - void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false); - void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far); - void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false); - void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false); - void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false); - void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); - void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); - void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size); - void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size); void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip); void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); - struct BokehBuffers { - // bokeh buffers - - // textures - Size2i base_texture_size; - RID base_texture; - RID depth_texture; - RID secondary_texture; - RID half_texture[2]; - - // raster only - RID base_fb; - RID secondary_fb; // with weights - RID half_fb[2]; // with weights - RID base_weight_fb; - RID weight_texture[4]; - }; - - void bokeh_dof(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal); - void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal); - struct SSAOSettings { float radius = 1.0; float intensity = 2.0; 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 4bfaad9fe6..0eb981d51b 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -2006,14 +2006,14 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture); - Map<Size2i, RID>::Element *E = sdfgi_framebuffer_size_cache.find(fb_size); + HashMap<Size2i, RID>::Iterator E = sdfgi_framebuffer_size_cache.find(fb_size); if (!E) { RID fb = RD::get_singleton()->framebuffer_create_empty(fb_size); 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, 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); + _render_list_with_threads(&render_list_params, E->value, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs); } RD::get_singleton()->draw_command_end_label(); @@ -3276,8 +3276,8 @@ RenderForwardClustered::~RenderForwardClustered() { memdelete_arr(scene_state.lightmap_captures); } - while (sdfgi_framebuffer_size_cache.front()) { - RD::get_singleton()->free(sdfgi_framebuffer_size_cache.front()->get()); - sdfgi_framebuffer_size_cache.erase(sdfgi_framebuffer_size_cache.front()); + while (sdfgi_framebuffer_size_cache.begin()) { + RD::get_singleton()->free(sdfgi_framebuffer_size_cache.begin()->value); + sdfgi_framebuffer_size_cache.remove(sdfgi_framebuffer_size_cache.begin()); } } 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 0e588aecb4..bec10f7f0e 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -106,7 +106,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID color_only_fb; RID specular_only_fb; int width, height; - Map<uint32_t, RID> color_framebuffers; + HashMap<uint32_t, RID> color_framebuffers; uint32_t view_count; RID render_sdfgi_uniform_set; @@ -396,7 +396,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { void _fill_instance_data(RenderListType p_render_list, int *p_render_info = nullptr, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true); void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, bool p_append = false); - Map<Size2i, RID> sdfgi_framebuffer_size_cache; + HashMap<Size2i, RID> sdfgi_framebuffer_size_cache; struct GeometryInstanceData; struct GeometryInstanceForwardClustered; 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 036ad0f18a..bd39dd9c70 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 @@ -154,7 +154,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { print_line(gen_code.defines[i]); } - Map<String, String>::Element *el = gen_code.code.front(); + RBMap<String, String>::Element *el = gen_code.code.front(); while (el) { print_line("\n**code " + el->key() + ":\n" + el->value()); @@ -376,14 +376,14 @@ void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const St } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { @@ -477,7 +477,7 @@ void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) { next_pass = p_pass; } -bool SceneShaderForwardClustered::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool SceneShaderForwardClustered::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::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, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER); 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 0b2df983ff..c22b2f243d 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 @@ -138,14 +138,14 @@ public: String path; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; DepthDraw depth_draw; DepthTest depth_test; @@ -208,7 +208,7 @@ public: uint8_t priority; 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 bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~MaterialData(); }; @@ -239,7 +239,7 @@ public: ShaderData *overdraw_material_shader_ptr = nullptr; Vector<RD::PipelineSpecializationConstant> default_specialization_constants; - Set<uint32_t> valid_color_pass_pipelines; + RBSet<uint32_t> valid_color_pass_pipelines; SceneShaderForwardClustered(); ~SceneShaderForwardClustered(); 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 cdddc35579..a3cabb0693 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 @@ -154,7 +154,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { print_line(gen_code.defines[i]); } - Map<String, String>::Element * el = gen_code.code.front(); + RBMap<String, String>::Element * el = gen_code.code.front(); while (el) { print_line("\n**code " + el->key() + ":\n" + el->value()); @@ -339,14 +339,14 @@ void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const Strin } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { @@ -440,7 +440,7 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) { next_pass = p_pass; } -bool SceneShaderForwardMobile::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool SceneShaderForwardMobile::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::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, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER); 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 50b5fb26ec..f325d5c0a5 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 @@ -104,14 +104,14 @@ public: String path; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; DepthDraw depth_draw; DepthTest depth_test; @@ -171,7 +171,7 @@ public: uint8_t priority; 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 bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~MaterialData(); }; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 386bc18fcd..3c2f3f8a42 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -2160,14 +2160,14 @@ void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const S } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { @@ -2246,7 +2246,7 @@ RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() { return shader_data; } -bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const HashMap<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); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 06970acca6..04881ce7e6 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -166,14 +166,14 @@ class RendererCanvasRenderRD : public RendererCanvasRender { PipelineVariants pipeline_variants; String path; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_screen_texture = false; bool uses_sdf = false; @@ -205,7 +205,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { 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 bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~CanvasMaterialData(); }; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 26bd28286b..aefc189f68 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -90,7 +90,7 @@ protected: RID sampler; } blit; - Map<RID, RID> render_target_descriptors; + HashMap<RID, RID> render_target_descriptors; double time = 0.0; double delta = 0.0; @@ -131,6 +131,7 @@ public: static void make_current() { _create_func = _create_current; + low_end = false; } static RendererCompositorRD *singleton; diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index 5cbacb0ef3..7aede6bb48 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -1115,6 +1115,7 @@ void RendererSceneGIRD::SDFGI::update_cascades() { void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) { Vector<RD::Uniform> uniforms; @@ -1251,7 +1252,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons RD::get_singleton()->compute_list_end(); Size2 rtsize = texture_storage->render_target_get_size(p_render_target); - storage->get_effects()->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true); + copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true); } void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index bf65dca56a..e3bf2e3dda 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -1556,8 +1556,6 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH); - // TODO make sure texture_create_shared_from_slice works for multiview - RD::TextureFormat tf; tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT; tf.width = rb->internal_width; @@ -1583,55 +1581,63 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { tf.mipmaps--; rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - int base_width = rb->internal_width; - int base_height = rb->internal_height; + for (uint32_t l = 0; l < rb->view_count; l++) { + RenderBuffers::Blur::Layer ll[2]; + int base_width = rb->internal_width; + int base_height = rb->internal_height; - for (uint32_t i = 0; i < mipmaps_required; i++) { - RenderBuffers::Blur::Mipmap mm; - mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, 0, i); + for (uint32_t i = 0; i < mipmaps_required; i++) { + RenderBuffers::Blur::Mipmap mm; + mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, l, i); - mm.width = base_width; - mm.height = base_height; + mm.width = base_width; + mm.height = base_height; - if (!_render_buffers_can_be_storage()) { - Vector<RID> fb; - fb.push_back(mm.texture); - - mm.fb = RD::get_singleton()->framebuffer_create(fb); - } + if (!_render_buffers_can_be_storage()) { + Vector<RID> fb; + fb.push_back(mm.texture); - if (!_render_buffers_can_be_storage()) { - // and half texture, this is an intermediate result so just allocate a texture, is this good enough? - tf.width = MAX(1, base_width >> 1); - tf.height = base_height; - tf.mipmaps = 1; // 1 or 0? + mm.fb = RD::get_singleton()->framebuffer_create(fb); + } - mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + if (!_render_buffers_can_be_storage()) { + // and half texture, this is an intermediate result so just allocate a texture, is this good enough? + tf.width = MAX(1, base_width >> 1); + tf.height = base_height; + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + tf.mipmaps = 1; + + mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + Vector<RID> half_fb; + half_fb.push_back(mm.half_texture); + mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb); + } - Vector<RID> half_fb; - half_fb.push_back(mm.half_texture); - mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb); - } + ll[0].mipmaps.push_back(mm); - rb->blur[0].mipmaps.push_back(mm); + if (i > 0) { + mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, l, i - 1); - if (i > 0) { - mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1); + if (!_render_buffers_can_be_storage()) { + Vector<RID> fb; + fb.push_back(mm.texture); - if (!_render_buffers_can_be_storage()) { - Vector<RID> fb; - fb.push_back(mm.texture); + mm.fb = RD::get_singleton()->framebuffer_create(fb); - mm.fb = RD::get_singleton()->framebuffer_create(fb); + // We can re-use the half texture here as it is an intermediate result + } - // We can re-use the half texture here as it is an intermediate result + ll[1].mipmaps.push_back(mm); } - rb->blur[1].mipmaps.push_back(mm); + base_width = MAX(1, base_width >> 1); + base_height = MAX(1, base_height >> 1); } - base_width = MAX(1, base_width >> 1); - base_height = MAX(1, base_height >> 1); + rb->blur[0].layers.push_back(ll[0]); + rb->blur[1].layers.push_back(ll[1]); } if (!_render_buffers_can_be_storage()) { @@ -1640,21 +1646,19 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP tf.width = rb->internal_width; tf.height = rb->internal_height; - tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D; - tf.array_layers = rb->view_count; + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; // Our DOF effect handles one eye per turn tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; tf.mipmaps = 1; for (uint32_t i = 0; i < 4; i++) { // associated blur texture RID texture; - if (i == 0) { - texture = rb->texture; - } else if (i == 1) { - texture = rb->blur[0].mipmaps[0].texture; + if (i == 1) { + texture = rb->blur[0].layers[0].mipmaps[0].texture; } else if (i == 2) { - texture = rb->blur[1].mipmaps[0].texture; + texture = rb->blur[1].layers[0].mipmaps[0].texture; } else if (i == 3) { - texture = rb->blur[0].mipmaps[1].texture; + texture = rb->blur[0].layers[0].mipmaps[1].texture; } // create weight texture @@ -1662,7 +1666,9 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { // create frame buffer Vector<RID> fb; - fb.push_back(texture); + if (i != 0) { + fb.push_back(texture); + } fb.push_back(rb->weight_buffers[i].weight); rb->weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb); @@ -1672,13 +1678,6 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { tf.height = MAX(1u, tf.height >> 1); } } - - { - // and finally an FB for just our base weights - Vector<RID> fb; - fb.push_back(rb->weight_buffers[0].weight); - rb->base_weight_fb = RD::get_singleton()->framebuffer_create(fb); - } } } @@ -1765,6 +1764,21 @@ void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) { } void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { + if (rb->views.size() > 1) { // if 1 these are copies ofs rb->internal_texture, rb->depth_texture and rb->texture_fb + for (int i = 0; i < rb->views.size(); i++) { + if (rb->views[i].view_fb.is_valid()) { + RD::get_singleton()->free(rb->views[i].view_fb); + } + if (rb->views[i].view_texture.is_valid()) { + RD::get_singleton()->free(rb->views[i].view_texture); + } + if (rb->views[i].view_depth.is_valid()) { + RD::get_singleton()->free(rb->views[i].view_depth); + } + } + } + rb->views.clear(); + if (rb->texture_fb.is_valid()) { RD::get_singleton()->free(rb->texture_fb); rb->texture_fb = RID(); @@ -1813,24 +1827,26 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { } for (int i = 0; i < 2; i++) { - for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) { - // do we free the texture slice here? or is it enough to free the main texture? + for (int l = 0; l < rb->blur[i].layers.size(); l++) { + for (int m = 0; m < rb->blur[i].layers[l].mipmaps.size(); m++) { + // do we free the texture slice here? or is it enough to free the main texture? - // do free the mobile extra stuff - if (rb->blur[i].mipmaps[m].fb.is_valid()) { - RD::get_singleton()->free(rb->blur[i].mipmaps[m].fb); - } - // texture and framebuffer in both blur mipmaps are shared, so only free from the first one - if (i == 0) { - if (rb->blur[i].mipmaps[m].half_fb.is_valid()) { - RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_fb); + // do free the mobile extra stuff + if (rb->blur[i].layers[l].mipmaps[m].fb.is_valid()) { + RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].fb); } - if (rb->blur[i].mipmaps[m].half_texture.is_valid()) { - RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_texture); + // texture and framebuffer in both blur mipmaps are shared, so only free from the first one + if (i == 0) { + if (rb->blur[i].layers[l].mipmaps[m].half_fb.is_valid()) { + RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].half_fb); + } + if (rb->blur[i].layers[l].mipmaps[m].half_texture.is_valid()) { + RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].half_texture); + } } } } - rb->blur[i].mipmaps.clear(); + rb->blur[i].layers.clear(); if (rb->blur[i].texture.is_valid()) { RD::get_singleton()->free(rb->blur[i].texture); @@ -1998,8 +2014,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb _allocate_blur_textures(rb); } - storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection); - storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].mipmaps[1].texture); + storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].layers[0].mipmaps[1].texture, rb->blur[1].layers[0].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection); + storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].layers[0].mipmaps[1].texture); } void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) { @@ -2295,14 +2311,14 @@ void RendererSceneRenderRD::_copy_framebuffer_to_ssil(RID p_render_buffers) { ERR_FAIL_COND(!rb); if (rb->ss_effects.last_frame.is_valid()) { - storage->get_effects()->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height)); + copy_effects->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height)); int width = rb->width; int height = rb->height; for (int i = 0; i < rb->ss_effects.last_frame_slices.size() - 1; i++) { width = MAX(1, width >> 1); height = MAX(1, height >> 1); - storage->get_effects()->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height)); + copy_effects->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height)); } } } @@ -2317,19 +2333,19 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData _allocate_blur_textures(rb); } - // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye - bool can_use_storage = _render_buffers_can_be_storage(); - if (can_use_storage) { - storage->get_effects()->copy_to_rect(rb->texture, rb->blur[0].mipmaps[0].texture, Rect2i(0, 0, rb->width, rb->height)); - for (int i = 1; i < rb->blur[0].mipmaps.size(); i++) { - storage->get_effects()->make_mipmap(rb->blur[0].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i].texture, Size2i(rb->blur[0].mipmaps[i].width, rb->blur[0].mipmaps[i].height)); - } - } else { - storage->get_effects()->copy_to_fb_rect(rb->texture, rb->blur[0].mipmaps[0].fb, Rect2i(0, 0, rb->width, rb->height)); - for (int i = 1; i < rb->blur[0].mipmaps.size(); i++) { - storage->get_effects()->make_mipmap_raster(rb->blur[0].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i].fb, Size2i(rb->blur[0].mipmaps[i].width, rb->blur[0].mipmaps[i].height)); + for (uint32_t v = 0; v < rb->view_count; v++) { + if (can_use_storage) { + copy_effects->copy_to_rect(rb->views[v].view_texture, rb->blur[0].layers[v].mipmaps[0].texture, Rect2i(0, 0, rb->width, rb->height)); + for (int i = 1; i < rb->blur[0].layers[v].mipmaps.size(); i++) { + copy_effects->make_mipmap(rb->blur[0].layers[v].mipmaps[i - 1].texture, rb->blur[0].layers[v].mipmaps[i].texture, Size2i(rb->blur[0].layers[v].mipmaps[i].width, rb->blur[0].layers[v].mipmaps[i].height)); + } + } else { + copy_effects->copy_to_fb_rect(rb->views[v].view_texture, rb->blur[0].layers[v].mipmaps[0].fb, Rect2i(0, 0, rb->width, rb->height)); + for (int i = 1; i < rb->blur[0].layers[v].mipmaps.size(); i++) { + copy_effects->make_mipmap_raster(rb->blur[0].layers[v].mipmaps[i - 1].texture, rb->blur[0].layers[v].mipmaps[i].fb, Size2i(rb->blur[0].layers[v].mipmaps[i].width, rb->blur[0].layers[v].mipmaps[i].height)); + } } } @@ -2351,9 +2367,9 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR bool can_use_storage = _render_buffers_can_be_storage(); if (can_use_storage) { - storage->get_effects()->copy_to_rect(rb->depth_texture, rb->depth_back_texture, Rect2i(0, 0, rb->width, rb->height)); + copy_effects->copy_to_rect(rb->depth_texture, rb->depth_back_texture, Rect2i(0, 0, rb->width, rb->height)); } else { - storage->get_effects()->copy_to_fb_rect(rb->depth_texture, rb->depth_back_fb, Rect2i(0, 0, rb->width, rb->height)); + copy_effects->copy_to_fb_rect(rb->depth_texture, rb->depth_back_fb, Rect2i(0, 0, rb->width, rb->height)); } RD::get_singleton()->draw_command_end_label(); @@ -2371,30 +2387,33 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende bool can_use_effects = rb->width >= 8 && rb->height >= 8; bool can_use_storage = _render_buffers_can_be_storage(); - // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye - if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) { RD::get_singleton()->draw_command_begin_label("DOF"); if (rb->blur[0].texture.is_null()) { _allocate_blur_textures(rb); } - EffectsRD::BokehBuffers buffers; + RendererRD::BokehDOF::BokehBuffers buffers; // Textures we use buffers.base_texture_size = Size2i(rb->internal_width, rb->internal_height); - buffers.base_texture = rb->internal_texture; - buffers.depth_texture = rb->depth_texture; - buffers.secondary_texture = rb->blur[0].mipmaps[0].texture; - buffers.half_texture[0] = rb->blur[1].mipmaps[0].texture; - buffers.half_texture[1] = rb->blur[0].mipmaps[1].texture; + buffers.secondary_texture = rb->blur[0].layers[0].mipmaps[0].texture; + buffers.half_texture[0] = rb->blur[1].layers[0].mipmaps[0].texture; + buffers.half_texture[1] = rb->blur[0].layers[0].mipmaps[1].texture; float bokeh_size = camfx->dof_blur_amount * 64.0; if (can_use_storage) { - storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_orthogonal); + for (uint32_t i = 0; i < rb->view_count; i++) { + buffers.base_texture = rb->views[i].view_texture; + buffers.depth_texture = rb->views[i].view_depth; + + // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum + float z_near = p_render_data->view_projection[i].get_z_near(); + float z_far = p_render_data->view_projection[i].get_z_far(); + bokeh_dof->bokeh_dof_compute(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, z_near, z_far, p_render_data->cam_orthogonal); + }; } else { // Set framebuffers. - buffers.base_fb = rb->texture_fb; buffers.secondary_fb = rb->weight_buffers[1].fb; buffers.half_fb[0] = rb->weight_buffers[2].fb; buffers.half_fb[1] = rb->weight_buffers[3].fb; @@ -2404,9 +2423,18 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende buffers.weight_texture[3] = rb->weight_buffers[3].weight; // Set weight buffers. - buffers.base_weight_fb = rb->base_weight_fb; + buffers.base_weight_fb = rb->weight_buffers[0].fb; + + for (uint32_t i = 0; i < rb->view_count; i++) { + buffers.base_texture = rb->views[i].view_texture; + buffers.depth_texture = rb->views[i].view_depth; + buffers.base_fb = rb->views[i].view_fb; - storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_orthogonal); + // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum + float z_near = p_render_data->view_projection[i].get_z_near(); + float z_far = p_render_data->view_projection[i].get_z_far(); + bokeh_dof->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, z_near, z_far, p_render_data->cam_orthogonal); + } } RD::get_singleton()->draw_command_end_label(); } @@ -2449,33 +2477,36 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { if (env->glow_levels[i] > 0.0) { - if (i >= rb->blur[1].mipmaps.size()) { - max_glow_level = rb->blur[1].mipmaps.size() - 1; + if (i >= rb->blur[1].layers[0].mipmaps.size()) { + max_glow_level = rb->blur[1].layers[0].mipmaps.size() - 1; } else { max_glow_level = i; } } } - for (int i = 0; i < (max_glow_level + 1); i++) { - int vp_w = rb->blur[1].mipmaps[i].width; - int vp_h = rb->blur[1].mipmaps[i].height; + float luminance_multiplier = _render_buffers_get_luminance_multiplier(); + for (uint32_t l = 0; l < rb->view_count; l++) { + for (int i = 0; i < (max_glow_level + 1); i++) { + int vp_w = rb->blur[1].layers[l].mipmaps[i].width; + int vp_h = rb->blur[1].layers[l].mipmaps[i].height; - if (i == 0) { - RID luminance_texture; - if (env->auto_exposure && rb->luminance.current.is_valid()) { - luminance_texture = rb->luminance.current; - } - if (can_use_storage) { - storage->get_effects()->gaussian_glow(rb->internal_texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); - } else { - storage->get_effects()->gaussian_glow_raster(rb->internal_texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); - } - } else { - if (can_use_storage) { - storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); + if (i == 0) { + RID luminance_texture; + if (env->auto_exposure && rb->luminance.current.is_valid()) { + luminance_texture = rb->luminance.current; + } + if (can_use_storage) { + copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); + } else { + copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); + } } else { - storage->get_effects()->gaussian_glow_raster(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, glow_high_quality); + if (can_use_storage) { + copy_effects->gaussian_glow(rb->blur[1].layers[l].mipmaps[i - 1].texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); + } else { + copy_effects->gaussian_glow_raster(rb->blur[1].layers[l].mipmaps[i - 1].texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); + } } } } @@ -2503,8 +2534,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { tonemap.glow_levels[i] = env->glow_levels[i]; } - tonemap.glow_texture_size.x = rb->blur[1].mipmaps[0].width; - tonemap.glow_texture_size.y = rb->blur[1].mipmaps[0].height; + tonemap.glow_texture_size.x = rb->blur[1].layers[0].mipmaps[0].width; + tonemap.glow_texture_size.y = rb->blur[1].layers[0].mipmaps[0].height; tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale; tonemap.glow_texture = rb->blur[1].texture; if (env->glow_map.is_valid()) { @@ -2562,7 +2593,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } if (can_use_effects && can_use_storage && (rb->internal_width != rb->width || rb->internal_height != rb->height)) { - RD::get_singleton()->draw_command_begin_label("FSR Upscale"); + RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale"); storage->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness); @@ -2652,7 +2683,6 @@ 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); ERR_FAIL_COND(!rb); @@ -2666,7 +2696,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID } Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true); + copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true); } } @@ -2675,7 +2705,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID RID shadow_atlas_texture = directional_shadow_get_texture(); Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true); + copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true); } } @@ -2685,7 +2715,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID if (decal_atlas.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true); + copy_effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true); } } @@ -2693,36 +2723,36 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID if (rb->luminance.current.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(rb->luminance.current, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true); + copy_effects->copy_to_fb_rect(rb->luminance.current, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true); } } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ss_effects.ssao.ao_final.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); + copy_effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb->ss_effects.ssil.ssil_final.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); + copy_effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); + copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && rb->ambient_buffer.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); RID ambient_texture = rb->ambient_buffer; RID reflection_texture = rb->reflection_buffer; - effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture); + copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture); } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) { if (p_occlusion_buffer.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false); + copy_effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false); } } } @@ -3035,12 +3065,38 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); } - if (!_render_buffers_can_be_storage()) { - // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS! - Vector<RID> fb; - fb.push_back(rb->internal_texture); + { + if (!_render_buffers_can_be_storage()) { + // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS! + Vector<RID> fb; + fb.push_back(rb->internal_texture); + + rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count); + } - rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count); + rb->views.clear(); // JIC + if (rb->view_count == 1) { + // copy as a convenience + RenderBuffers::View view; + view.view_texture = rb->internal_texture; + view.view_depth = rb->depth_texture; + view.view_fb = rb->texture_fb; + rb->views.push_back(view); + } else { + for (uint32_t i = 0; i < rb->view_count; i++) { + RenderBuffers::View view; + view.view_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->internal_texture, i, 0); + view.view_depth = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->depth_texture, i, 0); + + if (!_render_buffers_can_be_storage()) { + Vector<RID> fb; + fb.push_back(view.view_texture); + view.view_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, 1); + } + + rb->views.push_back(view); + } + } } RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target); @@ -3903,45 +3959,45 @@ void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const Strin } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + RBMap<int, StringName> order; - for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { - if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - if (E->get().texture_order >= 0) { - order[E->get().texture_order + 100000] = E->key(); + if (E.value.texture_order >= 0) { + order[E.value.texture_order + 100000] = E.key; } else { - order[E->get().order] = E->key(); + order[E.value.order] = E.key; } } - for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) { - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]); - pi.name = E->get(); + for (const KeyValue<int, StringName> &E : order) { + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); + pi.name = E.value; p_param_list->push_back(pi); } } 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) { + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } 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; - p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().array_size, E->get().hint); + p.info = ShaderLanguage::uniform_to_property_info(E.value); + p.info.name = E.key; //supply name + p.index = E.value.instance_index; + p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); p_param_list->push_back(p); } } @@ -3989,7 +4045,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) { +bool RendererSceneRenderRD::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); uniform_set_updated = true; @@ -5408,7 +5464,7 @@ bool RendererSceneRenderRD::free(RID p_rid) { LightInstance *light_instance = light_instance_owner.get_or_null(p_rid); //remove from shadow atlases.. - for (Set<RID>::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) { + for (RBSet<RID>::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(E->get()); ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid)); uint32_t key = shadow_atlas->shadow_owners[p_rid]; @@ -5836,12 +5892,21 @@ void fog() { cull_argument.set_page_pool(&cull_argument_pool); + bool can_use_storage = _render_buffers_can_be_storage(); + bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage)); + copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage)); tone_mapper = memnew(RendererRD::ToneMapper); } RendererSceneRenderRD::~RendererSceneRenderRD() { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + if (bokeh_dof) { + memdelete(bokeh_dof); + } + if (copy_effects) { + memdelete(copy_effects); + } if (tone_mapper) { memdelete(tone_mapper); } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 6bf3a95dd0..4daee17525 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -35,6 +35,8 @@ #include "core/templates/rid_owner.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/cluster_builder_rd.h" +#include "servers/rendering/renderer_rd/effects/bokeh_dof.h" +#include "servers/rendering/renderer_rd/effects/copy_effects.h" #include "servers/rendering/renderer_rd/effects/tone_mapper.h" #include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_gi_rd.h" @@ -94,6 +96,8 @@ class RendererSceneRenderRD : public RendererSceneRender { protected: RendererStorageRD *storage = nullptr; + RendererRD::BokehDOF *bokeh_dof = nullptr; + RendererRD::CopyEffects *copy_effects = nullptr; RendererRD::ToneMapper *tone_mapper = nullptr; double time = 0.0; double time_step = 0.0; @@ -293,7 +297,7 @@ private: RID depth; RID fb; //for copying - Map<RID, uint32_t> shadow_owners; + HashMap<RID, uint32_t> shadow_owners; }; RID_Owner<ShadowAtlas> shadow_atlas_owner; @@ -341,7 +345,7 @@ private: RID side_fb[6]; }; - Map<int, ShadowCubemap> shadow_cubemaps; + HashMap<int, ShadowCubemap> shadow_cubemaps; ShadowCubemap *_get_shadow_cubemap(int p_size); void _create_shadow_cubemaps(); @@ -383,7 +387,7 @@ private: Rect2 directional_rect; - Set<RID> shadow_atlases; //shadow atlases where this light is registered + RBSet<RID> shadow_atlases; //shadow atlases where this light is registered ForwardID forward_id = -1; @@ -482,6 +486,14 @@ private: RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!! RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling) + // Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images) + struct View { + RID view_texture; // texture slice for this view/layer + RID view_depth; // depth slice for this view/layer + RID view_fb; // framebuffer for this view/layer, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!! + }; + Vector<View> views; + RendererSceneGIRD::SDFGI *sdfgi = nullptr; VolumetricFog *volumetric_fog = nullptr; RendererSceneGIRD::RenderBuffersGI gi; @@ -503,19 +515,22 @@ private: RID half_fb; }; - Vector<Mipmap> mipmaps; + struct Layer { + Vector<Mipmap> mipmaps; + }; + + Vector<Layer> layers; }; Blur blur[2]; //the second one starts from the first mipmap struct WeightBuffers { RID weight; - RID fb; // FB with both texture and weight + RID fb; // FB with both texture and weight writing into one level lower }; // 2 full size, 2 half size WeightBuffers weight_buffers[4]; // Only used in raster - RID base_weight_fb; // base buffer for weight RID depth_back_texture; RID depth_back_fb; // only used on mobile @@ -906,7 +921,7 @@ private: RID version; RID pipeline; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; @@ -914,7 +929,7 @@ private: String path; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_time = false; @@ -939,7 +954,7 @@ private: 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 bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~FogMaterialData(); }; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 51cf0e952b..14a5f02eee 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "core/math/math_defs.h" #include "renderer_scene_render_rd.h" +#include "servers/rendering/renderer_rd/effects/copy_effects.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" @@ -150,14 +151,14 @@ void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringNa } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { @@ -236,7 +237,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) { +bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); uniform_set_updated = true; @@ -730,8 +731,10 @@ bool RendererSceneSkyRD::Sky::set_material(RID p_material) { return true; } -Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage, float p_energy, int p_roughness_layers, const Size2i &p_size) { +Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) { if (radiance.is_valid()) { + RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); + RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; tf.width = p_size.width; @@ -739,7 +742,7 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage, tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; RID rad_tex = RD::get_singleton()->texture_create(tf, RD::TextureView()); - p_storage->get_effects()->copy_cubemap_to_panorama(radiance, rad_tex, p_size, p_roughness_layers, reflection.layers.size() > 1); + copy_effects->copy_cubemap_to_panorama(radiance, rad_tex, p_size, p_roughness_layers, reflection.layers.size() > 1); Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rad_tex, 0); RD::get_singleton()->free(rad_tex); @@ -1905,7 +1908,7 @@ Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool update_dirty_skys(); - return sky->bake_panorama(storage, p_energy, p_bake_irradiance ? roughness_layers : 0, p_size); + return sky->bake_panorama(p_energy, p_bake_irradiance ? roughness_layers : 0, p_size); } RID RendererSceneSkyRD::sky_get_radiance_texture_rd(RID p_sky) const { diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h index 497d27ec26..83a8fe6e77 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h @@ -110,7 +110,7 @@ private: RID version; PipelineCacheRD pipelines[SKY_VERSION_MAX]; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; @@ -118,7 +118,7 @@ private: String path; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_time = false; bool uses_position = false; @@ -235,7 +235,7 @@ public: 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 bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~SkyMaterialData(); }; @@ -273,7 +273,7 @@ public: bool set_radiance_size(int p_radiance_size); bool set_mode(RS::SkyMode p_mode); bool set_material(RID p_material); - Ref<Image> bake_panorama(RendererStorageRD *p_storage, float p_energy, int p_roughness_layers, const Size2i &p_size); + Ref<Image> bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size); }; uint32_t sky_ggx_samples_quality; diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index fdfecf2d2c..04e05380f1 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -522,7 +522,7 @@ void ShaderRD::_compile_version(Version *p_version) { p_version->valid = true; } -void ShaderRD::version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines) { +void ShaderRD::version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines) { ERR_FAIL_COND(is_compute); Version *version = version_owner.get_or_null(p_version); @@ -547,7 +547,7 @@ void ShaderRD::version_set_code(RID p_version, const Map<String, String> &p_code } } -void ShaderRD::version_set_compute_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines) { +void ShaderRD::version_set_compute_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines) { ERR_FAIL_COND(!is_compute); Version *version = version_owner.get_or_null(p_version); diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h index 8e57f0d9af..40b10808c2 100644 --- a/servers/rendering/renderer_rd/shader_rd.h +++ b/servers/rendering/renderer_rd/shader_rd.h @@ -35,7 +35,7 @@ #include "core/string/string_builder.h" #include "core/templates/hash_map.h" #include "core/templates/local_vector.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/templates/rid_owner.h" #include "core/variant/variant.h" #include "servers/rendering_server.h" @@ -51,7 +51,7 @@ class ShaderRD { CharString vertex_globals; CharString compute_globals; CharString fragment_globals; - Map<StringName, CharString> code_sections; + HashMap<StringName, CharString> code_sections; Vector<CharString> custom_defines; Vector<uint8_t> *variant_data = nullptr; @@ -129,8 +129,8 @@ protected: public: RID version_create(); - void version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines); - void version_set_compute_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines); + void version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines); + void version_set_compute_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines); _FORCE_INLINE_ RID version_get_shader(RID p_version, int p_variant) { ERR_FAIL_INDEX_V(p_variant, variant_defines.size(), RID()); diff --git a/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl deleted file mode 100644 index e7a2e18323..0000000000 --- a/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl +++ /dev/null @@ -1,21 +0,0 @@ -#define FLAG_HORIZONTAL (1 << 0) -#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 1) -#define FLAG_GLOW_FIRST_PASS (1 << 2) - -layout(push_constant, std430) uniform Blur { - vec2 pixel_size; - uint flags; - uint pad; - - // Glow. - float glow_strength; - float glow_bloom; - float glow_hdr_threshold; - float glow_hdr_scale; - - float glow_exposure; - float glow_white; - float glow_luminance_cap; - float glow_auto_exposure_grey; -} -blur; diff --git a/servers/rendering/renderer_rd/shaders/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl index f8b4e3f610..96f5c3e9f2 100644 --- a/servers/rendering/renderer_rd/shaders/blur_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl @@ -53,7 +53,9 @@ void main() { #ifdef MODE_GAUSSIAN_BLUR - //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect + // Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect + + // note, for blur blur.luminance_multiplier is irrelavant, we would be multiplying and then dividing by this amount. if (bool(blur.flags & FLAG_HORIZONTAL)) { vec2 pix_size = blur.pixel_size; @@ -94,6 +96,7 @@ void main() { if (bool(blur.flags & FLAG_HORIZONTAL)) { vec2 pix_size = blur.pixel_size; pix_size *= 0.5; //reading from larger buffer, so use more samples + vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938; GLOW_ADD(vec2(1.0, 0.0), 0.165569); GLOW_ADD(vec2(2.0, 0.0), 0.140367); @@ -101,7 +104,10 @@ void main() { GLOW_ADD(vec2(-1.0, 0.0), 0.165569); GLOW_ADD(vec2(-2.0, 0.0), 0.140367); GLOW_ADD(vec2(-3.0, 0.0), 0.106595); + + // only do this in the horizontal pass, if we also do this in the vertical pass we're doubling up. color *= blur.glow_strength; + frag_color = color; } else { vec2 pix_size = blur.pixel_size; @@ -110,13 +116,17 @@ void main() { GLOW_ADD(vec2(0.0, 2.0), 0.122581); GLOW_ADD(vec2(0.0, -1.0), 0.233062); GLOW_ADD(vec2(0.0, -2.0), 0.122581); - color *= blur.glow_strength; + frag_color = color; } #undef GLOW_ADD if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) { + // In the first pass bring back to correct color range else we're applying the wrong threshold + // in subsequent passes we can use it as is as we'd just be undoing it right after. + frag_color *= blur.luminance_multiplier; + #ifdef GLOW_USE_AUTO_EXPOSURE frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey; @@ -126,10 +136,10 @@ void main() { float luminance = max(frag_color.r, max(frag_color.g, frag_color.b)); float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom); - frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap)); + frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap)) / blur.luminance_multiplier; } -#endif +#endif // MODE_GAUSSIAN_GLOW #ifdef MODE_COPY vec4 color = textureLod(source_color, uv_interp, 0.0); diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl new file mode 100644 index 0000000000..730504571a --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl @@ -0,0 +1,26 @@ +#define FLAG_HORIZONTAL (1 << 0) +#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 1) +#define FLAG_GLOW_FIRST_PASS (1 << 2) + +layout(push_constant, std430) uniform Blur { + vec2 pixel_size; // 08 - 08 + uint flags; // 04 - 12 + uint pad; // 04 - 16 + + // Glow. + float glow_strength; // 04 - 20 + float glow_bloom; // 04 - 24 + float glow_hdr_threshold; // 04 - 28 + float glow_hdr_scale; // 04 - 32 + + float glow_exposure; // 04 - 36 + float glow_white; // 04 - 40 + float glow_luminance_cap; // 04 - 44 + float glow_auto_exposure_grey; // 04 - 48 + + float luminance_multiplier; // 04 - 52 + float res1; // 04 - 56 + float res2; // 04 - 60 + float res3; // 04 - 64 +} +blur; diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl index 0438671dd2..0438671dd2 100644 --- a/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl index b90a527554..b90a527554 100644 --- a/servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl index a3b3938ee9..a3b3938ee9 100644 --- a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl diff --git a/servers/rendering/renderer_rd/shaders/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl index 4563ac7af9..3a4ef86ef0 100644 --- a/servers/rendering/renderer_rd/shaders/copy.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl @@ -189,7 +189,7 @@ void main() { #endif color *= params.glow_exposure; - float luminance = dot(color.rgb, vec3(0.299, 0.587, 0.114)); + float luminance = max(color.r, max(color.g, color.b)); float feedback = max(smoothstep(params.glow_hdr_threshold, params.glow_hdr_threshold + params.glow_hdr_scale, luminance), params.glow_bloom); color = min(color * feedback, vec4(params.glow_luminance_cap)); diff --git a/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl index 9787c9879d..9787c9879d 100644 --- a/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl diff --git a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl index 19a9350137..5a238452c0 100644 --- a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl @@ -44,7 +44,11 @@ layout(set = 0, binding = 0) uniform sampler2D source_color; #endif layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; +#ifdef MULTIVIEW +layout(set = 2, binding = 0) uniform sampler2DArray source_glow; +#else layout(set = 2, binding = 0) uniform sampler2D source_glow; +#endif layout(set = 2, binding = 1) uniform sampler2D glow_map; #ifdef USE_1D_LUT @@ -118,6 +122,36 @@ float h1(float a) { return 1.0f + w3(a) / (w2(a) + w3(a)); } +#ifdef MULTIVIEW +vec4 texture2D_bicubic(sampler2DArray tex, vec2 uv, int p_lod) { + float lod = float(p_lod); + vec2 tex_size = vec2(params.glow_texture_size >> p_lod); + vec2 pixel_size = vec2(1.0f) / tex_size; + + uv = uv * tex_size + vec2(0.5f); + + vec2 iuv = floor(uv); + vec2 fuv = fract(uv); + + float g0x = g0(fuv.x); + float g1x = g1(fuv.x); + float h0x = h0(fuv.x); + float h1x = h1(fuv.x); + float h0y = h0(fuv.y); + float h1y = h1(fuv.y); + + vec3 p0 = vec3((vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5f)) * pixel_size, ViewIndex); + vec3 p1 = vec3((vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5f)) * pixel_size, ViewIndex); + vec3 p2 = vec3((vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5f)) * pixel_size, ViewIndex); + vec3 p3 = vec3((vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5f)) * pixel_size, ViewIndex); + + return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) + + (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod))); +} + +#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod) +#else // MULTIVIEW + vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) { float lod = float(p_lod); vec2 tex_size = vec2(params.glow_texture_size >> p_lod); @@ -145,12 +179,17 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) { } #define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod) +#endif // !MULTIVIEW -#else +#else // USE_GLOW_FILTER_BICUBIC +#ifdef MULTIVIEW +#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, vec3(m_uv, ViewIndex), float(m_lod)) +#else // MULTIVIEW #define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod)) +#endif // !MULTIVIEW -#endif +#endif // !USE_GLOW_FILTER_BICUBIC vec3 tonemap_filmic(vec3 color, float white) { // exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers @@ -231,7 +270,11 @@ vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always o } } +#ifdef MULTIVIEW +vec3 gather_glow(sampler2DArray tex, vec2 uv) { // sample all selected glow levels, view is added to uv later +#else vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels +#endif // defined(MULTIVIEW) vec3 glow = vec3(0.0f); if (params.glow_levels[0] > 0.0001) { diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 58b4ded9f4..4f49c186a6 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -679,7 +679,7 @@ void main() { float normal_map_depth = 1.0; - vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center + vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size; float sss_strength = 0.0; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index b6ba244665..b4e4ac9bc8 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -650,7 +650,7 @@ void main() { float normal_map_depth = 1.0; - vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center + vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size; float sss_strength = 0.0; diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 9ca2973fd4..27f0c5f273 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -896,7 +896,7 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, /////////////////////////////////////////////////////////////////////////// // 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) { +void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<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; @@ -943,11 +943,11 @@ void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::S 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); + HashMap<StringName, Variant>::ConstIterator 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); + _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->value, data, p_use_linear_color); } else if (E.value.default_value.size()) { //default value @@ -1001,7 +1001,7 @@ MaterialData::~MaterialData() { } } -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) { +void MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<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(); @@ -1029,12 +1029,12 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, 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); + HashMap<StringName, uint64_t>::Iterator 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; + E->value = global_textures_pass; } textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value); @@ -1044,10 +1044,10 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, 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); + HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(uniform_name); if (V) { - if (V->get().is_array()) { - Array array = (Array)V->get(); + if (V->value.is_array()) { + Array array = (Array)V->value; if (uniform_array_size > 0) { for (int j = 0; j < array.size(); j++) { textures.push_back(array[j]); @@ -1058,25 +1058,25 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, } } } else { - textures.push_back(V->get()); + textures.push_back(V->value); } } 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); + HashMap<StringName, HashMap<int, RID>>::ConstIterator 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]); + if (W && W->value.has(j)) { + textures.push_back(W->value[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]); + HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name); + if (W && W->value.has(0)) { + textures.push_back(W->value[0]); } } } @@ -1190,12 +1190,12 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, } { //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); + List<StringName> to_delete; + for (KeyValue<StringName, uint64_t> &E : used_global_textures) { + if (E.value != global_textures_pass) { + to_delete.push_back(E.key); - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E->key()); + GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key); if (v) { v->texture_materials.erase(self); } @@ -1225,7 +1225,7 @@ void MaterialData::free_parameters_uniform_set(RID 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) { +bool MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<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()) { @@ -1420,6 +1420,25 @@ MaterialStorage::MaterialStorage() { //custom sampler sampler_rd_configure_custom(0.0f); + // buffers + { //create index array for copy shaders + Vector<uint8_t> pv; + pv.resize(6 * 4); + { + uint8_t *w = pv.ptrw(); + int *p32 = (int *)w; + p32[0] = 0; + p32[1] = 1; + p32[2] = 2; + p32[3] = 0; + p32[4] = 2; + p32[5] = 3; + } + quad_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv); + quad_index_array = RD::get_singleton()->index_array_create(quad_index_buffer, 0, 6); + } + + // Shaders for (int i = 0; i < SHADER_TYPE_MAX; i++) { shader_data_request_func[i] = nullptr; } @@ -1441,6 +1460,10 @@ MaterialStorage::~MaterialStorage() { memdelete_arr(global_variables.buffer_dirty_regions); RD::get_singleton()->free(global_variables.buffer); + // buffers + + RD::get_singleton()->free(quad_index_buffer); //array gets freed as dependency + //def samplers for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { @@ -1936,10 +1959,9 @@ Vector<StringName> MaterialStorage::global_variable_get_list() const { 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); + for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) { + names.push_back(E.key); } names.sort_custom<StringName::AlphCompare>(); return names; @@ -1957,7 +1979,7 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); - for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { + for (RBSet<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); @@ -1989,7 +2011,7 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); - for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { + for (RBSet<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); @@ -2283,7 +2305,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { shader->data = nullptr; } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); material->shader_type = new_type; if (material->data) { @@ -2300,7 +2322,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { shader->type = SHADER_TYPE_MAX; //invalid } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + for (RBSet<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); @@ -2312,7 +2334,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { } if (shader->data) { - for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) { + for (const KeyValue<StringName, HashMap<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); } @@ -2324,7 +2346,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { shader->data->set_code(p_code); } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { + for (RBSet<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); @@ -2351,7 +2373,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin 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] = HashMap<int, RID>(); } shader->default_texture_parameter[p_name][p_index] = p_texture; } else { @@ -2366,7 +2388,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin 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()) { + for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); _material_queue_update(material, false, true); } diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index c8cc418c3a..7d4db49f78 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -76,23 +76,23 @@ struct Shader { ShaderData *data = nullptr; String code; ShaderType type; - Map<StringName, Map<int, RID>> default_texture_parameter; - Set<Material *> owners; + HashMap<StringName, HashMap<int, RID>> default_texture_parameter; + RBSet<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); + void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); + void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<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 bool update_parameters(const HashMap<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); + bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<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: @@ -101,7 +101,7 @@ private: 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; + HashMap<StringName, uint64_t> used_global_textures; //internally by update_parameters_uniform_set Vector<uint8_t> ubo_data; @@ -120,7 +120,7 @@ struct Material { uint32_t shader_id = 0; bool uniform_dirty = false; bool texture_dirty = false; - Map<StringName, Variant> params; + HashMap<StringName, Variant> params; int32_t priority = 0; RID next_pass; SelfList<Material> update_element; @@ -137,7 +137,7 @@ struct GlobalVariables { BUFFER_DIRTY_REGION_SIZE = 1024 }; struct Variable { - Set<RID> texture_materials; // materials using this + RBSet<RID> texture_materials; // materials using this RS::GlobalVariableType type; Variant value; @@ -200,6 +200,11 @@ private: 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]; + /* Buffers */ + + RID quad_index_buffer; + RID quad_index_array; + /* GLOBAL VARIABLE API */ GlobalVariables global_variables; @@ -240,6 +245,10 @@ public: // void sampler_rd_set_default(float p_mipmap_bias); + /* Buffers */ + + RID get_quad_index_array() { return quad_index_array; } + /* GLOBAL VARIABLE API */ void _update_global_variables(); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 9b7b0d2c25..fa051c92ed 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -215,7 +215,7 @@ void MeshStorage::mesh_free(RID p_rid) { 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()) { + for (RBSet<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); @@ -431,7 +431,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { + for (RBSet<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); @@ -742,7 +742,7 @@ void MeshStorage::mesh_clear(RID p_mesh) { 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()) { + for (RBSet<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); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 7d3f603afd..d90bb2f128 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -141,7 +141,7 @@ struct Mesh { List<MeshInstance *> instances; RID shadow_mesh; - Set<Mesh *> shadow_owners; + RBSet<Mesh *> shadow_owners; RendererStorage::Dependency dependency; }; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 094120f908..1701b56b0b 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -838,7 +838,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta } uint32_t collision_3d_textures_used = 0; - for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) { + for (const RBSet<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) { ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E->get()); if (!pci || !pci->active) { continue; @@ -1592,14 +1592,14 @@ void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const Stri } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { @@ -1676,7 +1676,7 @@ ShaderData *ParticlesStorage::_create_particles_shader_func() { return shader_data; } -bool ParticlesStorage::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool ParticlesStorage::ParticlesMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { 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, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3); } diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index c6480794c1..eb55db19fb 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -224,7 +224,7 @@ struct Particles { ParticleEmissionBuffer *emission_buffer = nullptr; RID emission_storage_buffer; - Set<RID> collisions; + RBSet<RID> collisions; RendererStorage::Dependency dependency; @@ -345,7 +345,7 @@ private: RID version; bool uses_collision = false; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; @@ -353,7 +353,7 @@ private: String path; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; RID pipeline; @@ -387,7 +387,7 @@ private: 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 bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~ParticlesMaterialData(); }; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 3b52a187f6..7d4808f936 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -29,8 +29,8 @@ /*************************************************************************/ #include "texture_storage.h" - -#include "../renderer_storage_rd.h" +#include "../effects/copy_effects.h" +#include "material_storage.h" using namespace RendererRD; @@ -1808,8 +1808,8 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const { } void TextureStorage::update_decal_atlas() { - EffectsRD *effects = RendererStorageRD::base_singleton->get_effects(); - ERR_FAIL_NULL(effects); + RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); + ERR_FAIL_NULL(copy_effects); if (!decal_atlas.dirty) { return; //nothing to do @@ -1831,13 +1831,13 @@ void TextureStorage::update_decal_atlas() { Vector<DecalAtlas::SortItem> itemsv; itemsv.resize(decal_atlas.textures.size()); int base_size = 8; - const RID *K = nullptr; int idx = 0; - while ((K = decal_atlas.textures.next(K))) { + + for (const KeyValue<RID, DecalAtlas::Texture> &E : decal_atlas.textures) { DecalAtlas::SortItem &si = itemsv.write[idx]; - Texture *src_tex = get_texture(*K); + Texture *src_tex = get_texture(E.key); si.size.width = (src_tex->width / border) + 1; si.size.height = (src_tex->height / border) + 1; @@ -1847,7 +1847,7 @@ void TextureStorage::update_decal_atlas() { base_size = nearest_power_of_2_templated(si.size.width); } - si.texture = *K; + si.texture = E.key; idx++; } @@ -1983,18 +1983,17 @@ void TextureStorage::update_decal_atlas() { RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc); - const RID *K = nullptr; - while ((K = decal_atlas.textures.next(K))) { - DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K); - Texture *src_tex = get_texture(*K); - effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0); + for (const KeyValue<RID, DecalAtlas::Texture> &E : decal_atlas.textures) { + DecalAtlas::Texture *t = decal_atlas.textures.getptr(E.key); + Texture *src_tex = get_texture(E.key); + copy_effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0); } RD::get_singleton()->draw_list_end(); prev_texture = mm.texture; } else { - effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size)); + copy_effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size)); prev_texture = mm.texture; } } else { @@ -2623,8 +2622,8 @@ void TextureStorage::render_target_sdf_process(RID p_render_target) { } void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) { - EffectsRD *effects = RendererStorageRD::base_singleton->get_effects(); - ERR_FAIL_NULL(effects); + CopyEffects *copy_effects = CopyEffects::get_singleton(); + ERR_FAIL_NULL(copy_effects); RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); @@ -2642,9 +2641,11 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons } } + // TODO figure out stereo support here + //single texture copy for backbuffer //RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true); - effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true); + copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true); if (!p_gen_mipmaps) { return; @@ -2660,7 +2661,7 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons region.size.y = MAX(1, region.size.y >> 1); RID mipmap = rt->backbuffer_mipmaps[i]; - effects->gaussian_blur(prev_texture, mipmap, region, true); + copy_effects->gaussian_blur(prev_texture, mipmap, region, true); prev_texture = mipmap; } RD::get_singleton()->draw_command_end_label(); @@ -2670,8 +2671,8 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); - EffectsRD *effects = RendererStorageRD::base_singleton->get_effects(); - ERR_FAIL_NULL(effects); + CopyEffects *copy_effects = CopyEffects::get_singleton(); + ERR_FAIL_NULL(copy_effects); if (!rt->backbuffer.is_valid()) { _create_render_target_backbuffer(rt); @@ -2688,15 +2689,15 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const } //single texture copy for backbuffer - effects->set_color(rt->backbuffer_mipmap0, p_color, region, true); + copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true); } void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); - EffectsRD *effects = RendererStorageRD::base_singleton->get_effects(); - ERR_FAIL_NULL(effects); + CopyEffects *copy_effects = CopyEffects::get_singleton(); + ERR_FAIL_NULL(copy_effects); if (!rt->backbuffer.is_valid()) { _create_render_target_backbuffer(rt); @@ -2722,7 +2723,7 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, region.size.y = MAX(1, region.size.y >> 1); RID mipmap = rt->backbuffer_mipmaps[i]; - effects->gaussian_blur(prev_texture, mipmap, region, true); + copy_effects->gaussian_blur(prev_texture, mipmap, region, true); prev_texture = mipmap; } RD::get_singleton()->draw_command_end_label(); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index a6f50803e4..029816cbda 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -124,7 +124,7 @@ public: RID proxy_to; Vector<RID> proxies; - Set<RID> lightmap_users; + RBSet<RID> lightmap_users; RS::TextureDetectCallback detect_3d_callback = nullptr; void *detect_3d_callback_ud = nullptr; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 6e1fa59a7a..37bbab86ff 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -609,13 +609,16 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { if (p_base.is_valid()) { instance->base_type = RSG::storage->get_base_type(p_base); + // fix up a specific malfunctioning case before the switch, so it can be handled if (instance->base_type == RS::INSTANCE_NONE && RendererSceneOcclusionCull::get_singleton()->is_occluder(p_base)) { instance->base_type = RS::INSTANCE_OCCLUDER; } - ERR_FAIL_COND(instance->base_type == RS::INSTANCE_NONE); - switch (instance->base_type) { + case RS::INSTANCE_NONE: { + ERR_PRINT_ONCE("unimplemented base type encountered in renderer scene cull"); + return; + } case RS::INSTANCE_LIGHT: { InstanceLightData *light = memnew(InstanceLightData); @@ -650,7 +653,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr()); } - for (Set<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) { Instance *dep_instance = E->get(); ERR_CONTINUE(dep_instance->array_index == -1); ERR_CONTINUE(dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index != -1); @@ -1289,14 +1292,14 @@ void RendererSceneCull::instance_set_visibility_parent(RID p_instance, RID p_par bool RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance) { bool cycle_detected = false; - Set<Instance *> traversed_nodes; + RBSet<Instance *> traversed_nodes; { Instance *instance = p_instance; while (instance) { if (!instance->visibility_dependencies.is_empty()) { uint32_t depth = 0; - for (Set<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) { depth = MAX(depth, E->get()->visibility_dependencies_depth); } instance->visibility_dependencies_depth = depth + 1; @@ -1426,7 +1429,7 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); - Map<StringName, Instance::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter); + HashMap<StringName, Instance::InstanceShaderParameter>::Iterator E = instance->instance_shader_parameters.find(p_parameter); if (!E) { Instance::InstanceShaderParameter isp; @@ -1435,10 +1438,10 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c isp.value = p_value; instance->instance_shader_parameters[p_parameter] = isp; } else { - E->get().value = p_value; - if (E->get().index >= 0 && instance->instance_allocated_shader_parameters) { + E->value.value = p_value; + if (E->value.index >= 0 && instance->instance_allocated_shader_parameters) { //update directly - RSG::material_storage->global_variables_instance_update(p_instance, E->get().index, p_value); + RSG::material_storage->global_variables_instance_update(p_instance, E->value.index, p_value); } } } @@ -1556,7 +1559,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(p_instance->base_data); //erase dependencies, since no longer a lightmap - for (Set<Instance *>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) { Instance *geom = E->get(); _instance_queue_update(geom, true, false); } @@ -1571,7 +1574,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { //make sure lights are updated if it casts shadow if (geom->can_cast_shadows) { - for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); light->shadow_dirty = true; } @@ -1629,7 +1632,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { idata.parent_array_index = p_instance->visibility_parent ? p_instance->visibility_parent->array_index : -1; idata.visibility_index = p_instance->visibility_index; - for (Set<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) { Instance *dep_instance = E->get(); if (dep_instance->array_index != -1) { dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = p_instance->array_index; @@ -1797,7 +1800,7 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) { swapped_instance->scenario->instance_visibility[swapped_instance->visibility_index].array_index = swapped_instance->array_index; } - for (Set<Instance *>::Element *E = swapped_instance->visibility_dependencies.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = swapped_instance->visibility_dependencies.front(); E; E = E->next()) { Instance *dep_instance = E->get(); if (dep_instance != p_instance && dep_instance->array_index != -1) { dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = swapped_instance->array_index; @@ -1821,7 +1824,7 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) { scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, nullptr, 0); } - for (Set<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) { Instance *dep_instance = E->get(); if (dep_instance->array_index != -1) { dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1; @@ -1920,7 +1923,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance) float accum_blend = 0.0; InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); - for (Set<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) { Instance *lightmap = E->get(); bool interior = RSG::light_storage->lightmap_is_interior(lightmap->base); @@ -2741,7 +2744,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); uint32_t idx = 0; - for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); instance_pair_buffer[idx++] = light->instance; if (idx == MAX_INSTANCE_PAIRS) { @@ -2764,7 +2767,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); uint32_t idx = 0; - for (Set<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data); instance_pair_buffer[idx++] = reflection_probe->instance; @@ -2781,7 +2784,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); uint32_t idx = 0; - for (Set<Instance *>::Element *E = geom->decals.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->decals.front(); E; E = E->next()) { InstanceDecalData *decal = static_cast<InstanceDecalData *>(E->get()->base_data); instance_pair_buffer[idx++] = decal->instance; @@ -2796,7 +2799,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul if (idata.flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); uint32_t idx = 0; - for (Set<Instance *>::Element *E = geom->voxel_gi_instances.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->voxel_gi_instances.front(); E; E = E->next()) { InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(E->get()->base_data); instance_pair_buffer[idx++] = voxel_gi->probe_instance; @@ -3417,7 +3420,7 @@ void RendererSceneCull::render_probes() { const RID *instance_caches = probe->light_instances.ptr(); int idx = 0; //must count visible lights - for (Set<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) { Instance *instance = E->get(); InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; if (!instance->visible) { @@ -3499,7 +3502,7 @@ void RendererSceneCull::render_probes() { RID *instance_caches = probe->light_instances.ptrw(); int idx = 0; //must count visible lights - for (Set<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) { Instance *instance = E->get(); InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; if (!instance->visible) { @@ -3554,7 +3557,7 @@ void RendererSceneCull::render_probes() { RID instance_pair_buffer[MAX_INSTANCE_PAIRS]; - for (Set<Instance *>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) { Instance *ins = E->get(); if (!ins->visible) { continue; @@ -3563,7 +3566,7 @@ void RendererSceneCull::render_probes() { if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY)) { uint32_t idx = 0; - for (Set<Instance *>::Element *F = geom->voxel_gi_instances.front(); F; F = F->next()) { + for (RBSet<Instance *>::Element *F = geom->voxel_gi_instances.front(); F; F = F->next()) { InstanceVoxelGIData *voxel_gi2 = static_cast<InstanceVoxelGIData *>(F->get()->base_data); instance_pair_buffer[idx++] = voxel_gi2->probe_instance; @@ -3626,7 +3629,7 @@ 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) { +void RendererSceneCull::_update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) { List<RendererMaterialStorage::InstanceShaderParam> plist; RSG::material_storage->material_get_instance_shader_parameters(p_material, &plist); for (const RendererMaterialStorage::InstanceShaderParam &E : plist) { @@ -3697,7 +3700,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { bool can_cast_shadows = true; bool is_animated = false; - Map<StringName, Instance::InstanceShaderParameter> isparams; + HashMap<StringName, Instance::InstanceShaderParameter> isparams; if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) { can_cast_shadows = false; @@ -3820,7 +3823,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { if (can_cast_shadows != geom->can_cast_shadows) { //ability to cast shadows change, let lights now - for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { + for (RBSet<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); light->shadow_dirty = true; } diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index b5e8cf702f..c5325ef30a 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -324,7 +324,7 @@ public: RID reflection_probe_shadow_atlas; RID reflection_atlas; uint64_t used_viewport_visibility_bits; - Map<RID, uint64_t> viewport_visibility_masks; + HashMap<RID, uint64_t> viewport_visibility_masks; SelfList<Instance>::List instances; @@ -426,7 +426,7 @@ public: PropertyInfo info; }; - Map<StringName, InstanceShaderParameter> instance_shader_parameters; + HashMap<StringName, InstanceShaderParameter> instance_shader_parameters; bool instance_allocated_shader_parameters = false; int32_t instance_allocated_shader_parameters_offset = -1; @@ -443,7 +443,7 @@ public: float visibility_range_end_margin = 0.0f; RS::VisibilityRangeFadeMode visibility_range_fade_mode = RS::VISIBILITY_RANGE_FADE_DISABLED; Instance *visibility_parent = nullptr; - Set<Instance *> visibility_dependencies; + RBSet<Instance *> visibility_dependencies; uint32_t visibility_dependencies_depth = 0; float transparency = 0.0f; Scenario *scenario = nullptr; @@ -579,16 +579,16 @@ public: struct InstanceGeometryData : public InstanceBaseData { RendererSceneRender::GeometryInstance *geometry_instance = nullptr; - Set<Instance *> lights; + RBSet<Instance *> lights; bool can_cast_shadows; bool material_is_animated; uint32_t projector_count = 0; uint32_t softshadow_count = 0; - Set<Instance *> decals; - Set<Instance *> reflection_probes; - Set<Instance *> voxel_gi_instances; - Set<Instance *> lightmap_captures; + RBSet<Instance *> decals; + RBSet<Instance *> reflection_probes; + RBSet<Instance *> voxel_gi_instances; + RBSet<Instance *> lightmap_captures; InstanceGeometryData() { can_cast_shadows = true; @@ -599,7 +599,7 @@ public: struct InstanceReflectionProbeData : public InstanceBaseData { Instance *owner = nullptr; - Set<Instance *> geometries; + RBSet<Instance *> geometries; RID instance; SelfList<InstanceReflectionProbeData> update_list; @@ -616,7 +616,7 @@ public: Instance *owner = nullptr; RID instance; - Set<Instance *> geometries; + RBSet<Instance *> geometries; InstanceDecalData() { } @@ -654,7 +654,7 @@ public: bool uses_projector = false; bool uses_softshadow = false; - Set<Instance *> geometries; + RBSet<Instance *> geometries; Instance *baked_light = nullptr; @@ -673,10 +673,10 @@ public: struct InstanceVoxelGIData : public InstanceBaseData { Instance *owner = nullptr; - Set<Instance *> geometries; - Set<Instance *> dynamic_geometries; + RBSet<Instance *> geometries; + RBSet<Instance *> dynamic_geometries; - Set<Instance *> lights; + RBSet<Instance *> lights; struct LightCache { RS::LightType type; @@ -713,8 +713,8 @@ public: struct InstanceLightmapData : public InstanceBaseData { RID instance; - Set<Instance *> geometries; - Set<Instance *> users; + RBSet<Instance *> geometries; + RBSet<Instance *> users; InstanceLightmapData() { } @@ -779,7 +779,7 @@ public: } }; - Set<Instance *> heightfield_particle_colliders_update_list; + RBSet<Instance *> heightfield_particle_colliders_update_list; PagedArrayPool<Instance *> instance_cull_page_pool; PagedArrayPool<RendererSceneRender::GeometryInstance *> geometry_instance_cull_page_pool; @@ -964,7 +964,7 @@ public: virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index); virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias); - void _update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material); + void _update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material); virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value); virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const; diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index 7cf4fd0aff..7f35d2ca99 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -62,7 +62,7 @@ public: private: friend struct DependencyTracker; - Map<DependencyTracker *, uint32_t> instances; + HashMap<DependencyTracker *, uint32_t> instances; }; struct DependencyTracker { @@ -83,15 +83,16 @@ public: } void update_end() { //call after updating dependencies - List<Pair<Dependency *, Map<DependencyTracker *, uint32_t>::Element *>> to_clean_up; - for (Set<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) { + List<Pair<Dependency *, DependencyTracker *>> to_clean_up; + + for (RBSet<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) { Dependency *dep = E->get(); - Map<DependencyTracker *, uint32_t>::Element *F = dep->instances.find(this); + HashMap<DependencyTracker *, uint32_t>::Iterator F = dep->instances.find(this); ERR_CONTINUE(!F); - if (F->get() != instance_version) { - Pair<Dependency *, Map<DependencyTracker *, uint32_t>::Element *> p; + if (F->value != instance_version) { + Pair<Dependency *, DependencyTracker *> p; p.first = dep; - p.second = F; + p.second = F->key; to_clean_up.push_back(p); } } @@ -104,7 +105,7 @@ public: } void clear() { // clear all dependencies - for (Set<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) { + for (RBSet<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) { Dependency *dep = E->get(); dep->instances.erase(this); } @@ -116,7 +117,7 @@ public: private: friend struct Dependency; uint32_t instance_version = 0; - Set<Dependency *> dependencies; + RBSet<Dependency *> dependencies; }; virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 3ea67ae115..d612fb4aa7 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -226,7 +226,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { } if (!p_viewport->disable_2d) { - Map<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map; + RBMap<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map; Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y); RendererCanvasRender::Light *lights = nullptr; @@ -247,7 +247,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas); Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size); - for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { + for (RBSet<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { if (!F->get()->enabled) { continue; } @@ -281,7 +281,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { // Find lights in canvas. - for (Set<RendererCanvasRender::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) { + for (RBSet<RendererCanvasRender::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) { RendererCanvasRender::Light *cl = F->get(); if (cl->enabled && cl->texture.is_valid()) { //not super efficient.. @@ -313,7 +313,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { } } - for (Set<RendererCanvasRender::Light *>::Element *F = canvas->directional_lights.front(); F; F = F->next()) { + for (RBSet<RendererCanvasRender::Light *>::Element *F = canvas->directional_lights.front(); F; F = F->next()) { RendererCanvasRender::Light *cl = F->get(); if (cl->enabled) { cl->filter_next_ptr = directional_lights; @@ -349,7 +349,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas); Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size); - for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { + for (RBSet<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { if (!F->get()->enabled) { continue; } @@ -429,7 +429,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas); Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size); - for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { + for (RBSet<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { if (!F->get()->enabled) { continue; } @@ -454,7 +454,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { RENDER_TIMESTAMP("< Render DirectionalLight2D Shadows"); } - if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) { + if (scenario_draw_canvas_bg && canvas_map.begin() && canvas_map.begin()->key.get_layer() > scenario_canvas_max_layer) { if (!can_draw_3d) { RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas); } else { @@ -547,7 +547,7 @@ void RendererViewport::draw_viewports() { //sort viewports active_viewports.sort_custom<ViewportSort>(); - Map<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list; + HashMap<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list; //draw viewports RENDER_TIMESTAMP("> Render Viewports"); @@ -1176,8 +1176,8 @@ bool RendererViewport::free(RID p_rid) { RSG::scene->free(viewport->render_buffers); } - while (viewport->canvas_map.front()) { - viewport_remove_canvas(p_rid, viewport->canvas_map.front()->key()); + while (viewport->canvas_map.begin()) { + viewport_remove_canvas(p_rid, viewport->canvas_map.begin()->key); } viewport_set_scenario(p_rid, RID()); diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index b6e44e8436..da8cf5396c 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -137,7 +137,7 @@ public: Transform2D global_transform; - Map<RID, CanvasData> canvas_map; + HashMap<RID, CanvasData> canvas_map; RendererScene::RenderInfo render_info; diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp index e50ac42027..d03c4e0427 100644 --- a/servers/rendering/rendering_device_binds.cpp +++ b/servers/rendering/rendering_device_binds.cpp @@ -45,7 +45,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String }; String stage_code[RD::SHADER_STAGE_MAX]; int stages_found = 0; - Map<StringName, String> version_texts; + HashMap<StringName, String> version_texts; versions.clear(); base_error = ""; diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h index ee5bf8b891..8bdd3deea1 100644 --- a/servers/rendering/rendering_device_binds.h +++ b/servers/rendering/rendering_device_binds.h @@ -329,7 +329,7 @@ protected: class RDShaderFile : public Resource { GDCLASS(RDShaderFile, Resource) - Map<StringName, Ref<RDShaderSPIRV>> versions; + HashMap<StringName, Ref<RDShaderSPIRV>> versions; String base_error; public: diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 000b253e8a..c4538e0776 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -179,10 +179,10 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { print_line("GPU PROFILE (total " + rtos(total_time) + "ms): "); float print_threshold = 0.01; - for (OrderedHashMap<String, float>::Element E = print_gpu_profile_task_time.front(); E; E = E.next()) { - double time = E.value() / double(print_frame_profile_frame_count); + for (const KeyValue<String, float> &E : print_gpu_profile_task_time) { + double time = E.value / double(print_frame_profile_frame_count); if (time > print_threshold) { - print_line("\t-" + E.key() + ": " + rtos(time) + "ms"); + print_line("\t-" + E.key + ": " + rtos(time) + "ms"); } } print_gpu_profile_task_time.clear(); @@ -321,11 +321,7 @@ void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) { } bool RenderingServerDefault::is_low_end() const { - // FIXME: Commented out when rebasing vulkan branch on master, - // causes a crash, it seems rasterizer is not initialized yet the - // first time it's called. - //return RSG::rasterizer->is_low_end(); - return false; + return RendererCompositor::is_low_end(); } void RenderingServerDefault::_thread_exit() { diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index de4f8d9194..9d4059b9df 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -33,7 +33,7 @@ #include "core/math/octree.h" #include "core/templates/command_queue_mt.h" -#include "core/templates/ordered_hash_map.h" +#include "core/templates/hash_map.h" #include "renderer_canvas_cull.h" #include "renderer_scene_cull.h" #include "renderer_viewport.h" @@ -69,7 +69,7 @@ class RenderingServerDefault : public RenderingServer { //for printing bool print_gpu_profile = false; - OrderedHashMap<String, float> print_gpu_profile_task_time; + HashMap<String, float> print_gpu_profile_task_time; uint64_t print_frame_profile_ticks_from = 0; uint32_t print_frame_profile_frame_count = 0; @@ -113,7 +113,9 @@ public: _changes_changed(); #else - _FORCE_INLINE_ static void redraw_request() { changes++; } + _FORCE_INLINE_ static void redraw_request() { + changes++; + } #endif #define WRITE_ACTION redraw_request(); diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 812d636a0b..c88d9e8222 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -48,8 +48,8 @@ static String _mktab(int p_level) { static String _typestr(SL::DataType p_type) { String type = ShaderLanguage::get_datatype_name(p_type); - if (ShaderLanguage::is_sampler_type(p_type)) { - type = type.replace("sampler", "texture"); //we use textures instead of samplers + if (!RS::get_singleton()->is_low_end() && ShaderLanguage::is_sampler_type(p_type)) { + type = type.replace("sampler", "texture"); //we use textures instead of samplers in Vulkan GLSL } return type; } @@ -289,7 +289,7 @@ String ShaderCompiler::_get_sampler_name(ShaderLanguage::TextureFilter p_filter, return actions.sampler_array_name + "[" + itos(p_filter + (p_repeat == ShaderLanguage::REPEAT_ENABLE ? ShaderLanguage::FILTER_DEFAULT : 0)) + "]"; } -void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added) { +void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const HashMap<StringName, String> &p_func_code, String &r_to_add, RBSet<StringName> &added) { int fidx = -1; for (int i = 0; i < p_node->functions.size(); i++) { @@ -303,7 +303,7 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str Vector<StringName> uses_functions; - for (Set<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) { + for (RBSet<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) { uses_functions.push_back(E->get()); } uses_functions.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced @@ -538,7 +538,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene continue; // Instances are indexed directly, don't need index uniforms. } if (SL::is_sampler_type(uniform.type)) { - ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") uniform "; + // Texture layouts are different for OpenGL GLSL and Vulkan GLSL + if (!RS::get_singleton()->is_low_end()) { + ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") "; + } + ucode += "uniform "; } bool is_buffer_global = !SL::is_sampler_type(uniform.type) && uniform.scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL; @@ -681,9 +685,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } vcode += ";\n"; - - r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode; - r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") " + interp_mode + "in " + vcode; + // GLSL ES 3.0 does not allow layout qualifiers for varyings + if (!RS::get_singleton()->is_low_end()) { + r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") "; + r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") "; + } + r_gen_code.stage_globals[STAGE_VERTEX] += interp_mode + "out " + vcode; + r_gen_code.stage_globals[STAGE_FRAGMENT] += interp_mode + "in " + vcode; index += inc; } @@ -727,7 +735,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } } - Map<StringName, String> function_code; + HashMap<StringName, String> function_code; //code for functions for (int i = 0; i < pnode->functions.size(); i++) { @@ -740,7 +748,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene //place functions in actual code - Set<StringName> added_funcs_per_stage[STAGE_MAX]; + RBSet<StringName> added_funcs_per_stage[STAGE_MAX]; for (int i = 0; i < pnode->functions.size(); i++) { SL::FunctionNode *fnode = pnode->functions[i].function; @@ -1125,8 +1133,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene code += ", "; } String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - if (is_texture_func && i == 1) { - //need to map from texture to sampler in order to sample + if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) { + //need to map from texture to sampler in order to sample when using Vulkan GLSL StringName texture_uniform; bool correct_texture_uniform = false; diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h index 347ecf2988..85b93c4063 100644 --- a/servers/rendering/shader_compiler.h +++ b/servers/rendering/shader_compiler.h @@ -45,14 +45,14 @@ public: }; struct IdentifierActions { - Map<StringName, Stage> entry_point_stages; + HashMap<StringName, Stage> entry_point_stages; - Map<StringName, Pair<int *, int>> render_mode_values; - Map<StringName, bool *> render_mode_flags; - Map<StringName, bool *> usage_flag_pointers; - Map<StringName, bool *> write_flag_pointers; + HashMap<StringName, Pair<int *, int>> render_mode_values; + HashMap<StringName, bool *> render_mode_flags; + HashMap<StringName, bool *> usage_flag_pointers; + HashMap<StringName, bool *> write_flag_pointers; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms; }; struct GeneratedCode { @@ -74,7 +74,7 @@ public: String uniforms; String stage_globals[STAGE_MAX]; - Map<String, String> code; + HashMap<String, String> code; bool uses_global_textures; bool uses_fragment_time; @@ -82,10 +82,10 @@ public: }; struct DefaultIdentifierActions { - Map<StringName, String> renames; - Map<StringName, String> render_mode_defines; - Map<StringName, String> usage_defines; - Map<StringName, String> custom_samplers; + HashMap<StringName, String> renames; + HashMap<StringName, String> render_mode_defines; + HashMap<StringName, String> usage_defines; + HashMap<StringName, String> custom_samplers; ShaderLanguage::TextureFilter default_filter; ShaderLanguage::TextureRepeat default_repeat; String sampler_array_name; @@ -103,20 +103,20 @@ private: String _get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat); - void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added); + void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const HashMap<StringName, String> &p_func_code, String &r_to_add, RBSet<StringName> &added); String _dump_node_code(const ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_scope = true); const ShaderLanguage::ShaderNode *shader = nullptr; const ShaderLanguage::FunctionNode *function = nullptr; StringName current_func_name; StringName time_name; - Set<StringName> texture_functions; + RBSet<StringName> texture_functions; - Set<StringName> used_name_defines; - Set<StringName> used_flag_pointers; - Set<StringName> used_rmode_defines; - Set<StringName> internal_functions; - Set<StringName> fragment_varyings; + RBSet<StringName> used_name_defines; + RBSet<StringName> used_flag_pointers; + RBSet<StringName> used_rmode_defines; + RBSet<StringName> internal_functions; + RBSet<StringName> fragment_varyings; DefaultIdentifierActions actions; diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 6f70a55948..8a3ab92714 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -4019,7 +4019,7 @@ uint32_t ShaderLanguage::get_datatype_size(ShaderLanguage::DataType p_type) { } void ShaderLanguage::get_keyword_list(List<String> *r_keywords) { - Set<String> kws; + RBSet<String> kws; int idx = 0; @@ -4036,7 +4036,7 @@ void ShaderLanguage::get_keyword_list(List<String> *r_keywords) { idx++; } - for (Set<String>::Element *E = kws.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = kws.front(); E; E = E->next()) { r_keywords->push_back(E->get()); } } @@ -4056,7 +4056,7 @@ bool ShaderLanguage::is_control_flow_keyword(String p_keyword) { } void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) { - Set<String> kws; + RBSet<String> kws; int idx = 0; @@ -4066,7 +4066,7 @@ void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) { idx++; } - for (Set<String>::Element *E = kws.front(); E; E = E->next()) { + for (RBSet<String>::Element *E = kws.front(); E; E = E->next()) { r_keywords->push_back(E->get()); } } @@ -4340,8 +4340,8 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringNam arg->tex_argument_check = true; arg->tex_argument_filter = p_filter; arg->tex_argument_repeat = p_repeat; - for (KeyValue<StringName, Set<int>> &E : arg->tex_argument_connect) { - for (Set<int>::Element *F = E.value.front(); F; F = F->next()) { + for (KeyValue<StringName, RBSet<int>> &E : arg->tex_argument_connect) { + for (RBSet<int>::Element *F = E.value.front(); F; F = F->next()) { if (!_propagate_function_call_sampler_uniform_settings(E.key, F->get(), p_filter, p_repeat)) { return false; } @@ -4374,8 +4374,8 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa arg->tex_builtin_check = true; arg->tex_builtin = p_builtin; - for (KeyValue<StringName, Set<int>> &E : arg->tex_argument_connect) { - for (Set<int>::Element *F = E.value.front(); F; F = F->next()) { + for (KeyValue<StringName, RBSet<int>> &E : arg->tex_argument_connect) { + for (RBSet<int>::Element *F = E.value.front(); F; F = F->next()) { if (!_propagate_function_call_sampler_builtin_reference(E.key, F->get(), p_builtin)) { return false; } @@ -5096,7 +5096,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons for (int j = 0; j < base_function->arguments.size(); j++) { if (base_function->arguments[j].name == varname) { if (!base_function->arguments[j].tex_argument_connect.has(call_function->name)) { - base_function->arguments.write[j].tex_argument_connect[call_function->name] = Set<int>(); + base_function->arguments.write[j].tex_argument_connect[call_function->name] = RBSet<int>(); } base_function->arguments.write[j].tex_argument_connect[call_function->name].insert(i); found = true; @@ -5419,9 +5419,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons StringName member_struct_name = ""; int array_size = 0; - Set<char> position_symbols; - Set<char> color_symbols; - Set<char> texture_symbols; + RBSet<char> position_symbols; + RBSet<char> color_symbols; + RBSet<char> texture_symbols; bool mix_error = false; @@ -6648,7 +6648,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun StringName func_name = parent_function->name; if (!used_local_vars.has(func_name)) { - used_local_vars.insert(func_name, Map<StringName, Usage>()); + used_local_vars.insert(func_name, HashMap<StringName, Usage>()); } used_local_vars[func_name].insert(name, Usage(tk_line)); @@ -7062,7 +7062,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun _set_tkpos(pos); continue; } else { - Set<int> constants; + RBSet<int> constants; for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates. ControlFlowNode *flow = static_cast<ControlFlowNode *>(switch_block->statements[i]); if (flow) { @@ -7565,10 +7565,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return OK; } -String ShaderLanguage::_get_shader_type_list(const Set<String> &p_shader_types) const { +String ShaderLanguage::_get_shader_type_list(const RBSet<String> &p_shader_types) const { // Return a list of shader types as an human-readable string String valid_types; - for (const Set<String>::Element *E = p_shader_types.front(); E; E = E->next()) { + for (const RBSet<String>::Element *E = p_shader_types.front(); E; E = E->next()) { if (!valid_types.is_empty()) { valid_types += ", "; } @@ -7639,7 +7639,7 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) { return OK; } -Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types) { +Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const RBSet<String> &p_shader_types) { Token tk = _get_token(); TkPos prev_pos; Token next; @@ -7699,7 +7699,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct stages = &p_functions; const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo(); - Map<String, String> defined_modes; + HashMap<String, String> defined_modes; while (tk.type != TK_EOF) { switch (tk.type) { @@ -7790,7 +7790,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct st.shader_struct = st_node; int member_count = 0; - Set<String> member_names; + RBSet<String> member_names; while (true) { // variables list #ifdef DEBUG_ENABLED @@ -9234,7 +9234,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return OK; } -bool ShaderLanguage::has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name) { +bool ShaderLanguage::has_builtin(const HashMap<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name) { for (const KeyValue<StringName, ShaderLanguage::FunctionInfo> &E : p_functions) { if (E.value.built_ins.has(p_name)) { return true; @@ -9376,19 +9376,19 @@ String ShaderLanguage::get_shader_type(const String &p_code) { #ifdef DEBUG_ENABLED void ShaderLanguage::_check_warning_accums() { - for (const KeyValue<ShaderWarning::Code, Map<StringName, Map<StringName, Usage>> *> &E : warnings_check_map2) { - for (Map<StringName, Map<StringName, Usage>>::Element *T = (*E.value).front(); T; T = T->next()) { - for (const KeyValue<StringName, Usage> &U : T->get()) { + for (const KeyValue<ShaderWarning::Code, HashMap<StringName, HashMap<StringName, Usage>> *> &E : warnings_check_map2) { + for (const KeyValue<StringName, HashMap<StringName, Usage>> &T : *E.value) { + for (const KeyValue<StringName, Usage> &U : T.value) { if (!U.value.used) { _add_warning(E.key, U.value.decl_line, U.key); } } } } - for (const KeyValue<ShaderWarning::Code, Map<StringName, Usage> *> &E : warnings_check_map) { - for (const Map<StringName, Usage>::Element *U = (*E.value).front(); U; U = U->next()) { - if (!U->get().used) { - _add_warning(E.key, U->get().decl_line, U->key()); + for (const KeyValue<ShaderWarning::Code, HashMap<StringName, Usage> *> &E : warnings_check_map) { + for (const KeyValue<StringName, Usage> &U : (*E.value)) { + if (!U.value.used) { + _add_warning(E.key, U.value.decl_line, U.key); } } } @@ -9546,7 +9546,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ case COMPLETION_IDENTIFIER: case COMPLETION_FUNCTION_CALL: { bool comp_ident = completion_type == COMPLETION_IDENTIFIER; - Map<String, ScriptLanguage::CodeCompletionKind> matches; + HashMap<String, ScriptLanguage::CodeCompletionKind> matches; StringName skip_function; BlockNode *block = completion_block; @@ -9793,7 +9793,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } int idx2 = 0; - Set<int> out_args; + RBSet<int> out_args; while (builtin_func_out_args[idx2].name != nullptr) { if (builtin_func_out_args[idx2].name == builtin_func_defs[idx].name) { for (int i = 0; i < BuiltinFuncOutArgs::MAX_ARGS; i++) { diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 80230ed54c..d4a2e0b549 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -35,7 +35,7 @@ #include "core/string/string_name.h" #include "core/string/ustring.h" #include "core/templates/list.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/typedefs.h" #include "core/variant/variant.h" @@ -525,7 +525,7 @@ public: ConstantNode::Value value; }; - Map<StringName, Variable> variables; + HashMap<StringName, Variable> variables; List<Node *> statements; bool single_statement = false; bool use_comma_between_statements = false; @@ -589,7 +589,7 @@ public: bool is_const; int array_size; - Map<StringName, Set<int>> tex_argument_connect; + HashMap<StringName, RBSet<int>> tex_argument_connect; }; StringName name; @@ -622,7 +622,7 @@ public: struct Function { StringName name; FunctionNode *function = nullptr; - Set<StringName> uses_function; + RBSet<StringName> uses_function; bool callable; }; @@ -697,10 +697,10 @@ public: } }; - Map<StringName, Constant> constants; - Map<StringName, Varying> varyings; - Map<StringName, Uniform> uniforms; - Map<StringName, Struct> structs; + HashMap<StringName, Constant> constants; + HashMap<StringName, Varying> varyings; + HashMap<StringName, Uniform> uniforms; + HashMap<StringName, Struct> structs; Vector<StringName> render_modes; Vector<Function> functions; @@ -857,13 +857,13 @@ public: }; struct FunctionInfo { - Map<StringName, BuiltInInfo> built_ins; - Map<StringName, StageFunctionInfo> stage_functions; + HashMap<StringName, BuiltInInfo> built_ins; + HashMap<StringName, StageFunctionInfo> stage_functions; bool can_discard = false; bool main_function = false; }; - static bool has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name); + static bool has_builtin(const HashMap<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name); typedef DataType (*GlobalVariableGetTypeFunc)(const StringName &p_name); @@ -893,15 +893,15 @@ private: } }; - Map<StringName, Usage> used_constants; - Map<StringName, Usage> used_varyings; - Map<StringName, Usage> used_uniforms; - Map<StringName, Usage> used_functions; - Map<StringName, Usage> used_structs; - Map<ShaderWarning::Code, Map<StringName, Usage> *> warnings_check_map; + HashMap<StringName, Usage> used_constants; + HashMap<StringName, Usage> used_varyings; + HashMap<StringName, Usage> used_uniforms; + HashMap<StringName, Usage> used_functions; + HashMap<StringName, Usage> used_structs; + HashMap<ShaderWarning::Code, HashMap<StringName, Usage> *> warnings_check_map; - Map<StringName, Map<StringName, Usage>> used_local_vars; - Map<ShaderWarning::Code, Map<StringName, Map<StringName, Usage>> *> warnings_check_map2; + HashMap<StringName, HashMap<StringName, Usage>> used_local_vars; + HashMap<ShaderWarning::Code, HashMap<StringName, HashMap<StringName, Usage>> *> warnings_check_map2; List<ShaderWarning> warnings; @@ -1039,7 +1039,7 @@ private: uint32_t keyword_completion_context; #endif // DEBUG_ENABLED - const Map<StringName, FunctionInfo> *stages = nullptr; + const HashMap<StringName, FunctionInfo> *stages = nullptr; bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier); static const BuiltinFuncDef builtin_func_defs[]; @@ -1068,10 +1068,10 @@ private: Node *_parse_and_reduce_expression(BlockNode *p_block, const FunctionInfo &p_function_info); Error _parse_block(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); - String _get_shader_type_list(const Set<String> &p_shader_types) const; + String _get_shader_type_list(const RBSet<String> &p_shader_types) const; String _get_qualifier_str(ArgumentQualifier p_qualifier) const; - Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types); + Error _parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const RBSet<String> &p_shader_types); Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op); Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op); @@ -1094,10 +1094,10 @@ public: static String get_shader_type(const String &p_code); struct ShaderCompileInfo { - Map<StringName, FunctionInfo> functions; + HashMap<StringName, FunctionInfo> functions; Vector<ModeInfo> render_modes; VaryingFunctionNames varying_function_names = VaryingFunctionNames(); - Set<String> shader_types; + RBSet<String> shader_types; GlobalVariableGetTypeFunc global_variable_type_func = nullptr; }; diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 27a69fbc2e..98c7f0d7aa 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -31,7 +31,7 @@ #include "shader_types.h" #include "core/math/math_defs.h" -const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(RS::ShaderMode p_mode) const { +const HashMap<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(RS::ShaderMode p_mode) const { return shader_modes[p_mode].functions; } @@ -39,7 +39,7 @@ const Vector<ShaderLanguage::ModeInfo> &ShaderTypes::get_modes(RS::ShaderMode p_ return shader_modes[p_mode].modes; } -const Set<String> &ShaderTypes::get_types() const { +const RBSet<String> &ShaderTypes::get_types() const { return shader_types; } diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h index 385083b670..e0fee0a822 100644 --- a/servers/rendering/shader_types.h +++ b/servers/rendering/shader_types.h @@ -31,29 +31,29 @@ #ifndef SHADERTYPES_H #define SHADERTYPES_H -#include "core/templates/ordered_hash_map.h" +#include "core/templates/rb_map.h" #include "servers/rendering_server.h" #include "shader_language.h" class ShaderTypes { struct Type { - Map<StringName, ShaderLanguage::FunctionInfo> functions; + HashMap<StringName, ShaderLanguage::FunctionInfo> functions; Vector<ShaderLanguage::ModeInfo> modes; }; - Map<RS::ShaderMode, Type> shader_modes; + HashMap<RS::ShaderMode, Type> shader_modes; static ShaderTypes *singleton; - Set<String> shader_types; + RBSet<String> shader_types; List<String> shader_types_list; public: static ShaderTypes *get_singleton() { return singleton; } - const Map<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode) const; + const HashMap<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode) const; const Vector<ShaderLanguage::ModeInfo> &get_modes(RS::ShaderMode p_mode) const; - const Set<String> &get_types() const; + const RBSet<String> &get_types() const; const List<String> &get_types_list() const; ShaderTypes(); diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp index 639b9bd165..855dc23d94 100644 --- a/servers/rendering/shader_warnings.cpp +++ b/servers/rendering/shader_warnings.cpp @@ -109,10 +109,10 @@ ShaderWarning::Code ShaderWarning::get_code_from_name(const String &p_name) { ERR_FAIL_V_MSG(WARNING_MAX, "Invalid shader warning name: " + p_name); } -static Map<int, uint32_t> *code_to_flags_map = nullptr; +static HashMap<int, uint32_t> *code_to_flags_map = nullptr; static void init_code_to_flags_map() { - code_to_flags_map = memnew((Map<int, uint32_t>)); + code_to_flags_map = memnew((HashMap<int, uint32_t>)); code_to_flags_map->insert(ShaderWarning::FLOAT_COMPARISON, ShaderWarning::FLOAT_COMPARISON_FLAG); code_to_flags_map->insert(ShaderWarning::UNUSED_CONSTANT, ShaderWarning::UNUSED_CONSTANT_FLAG); code_to_flags_map->insert(ShaderWarning::UNUSED_FUNCTION, ShaderWarning::UNUSED_FUNCTION_FLAG); @@ -124,7 +124,7 @@ static void init_code_to_flags_map() { code_to_flags_map->insert(ShaderWarning::DEVICE_LIMIT_EXCEEDED, ShaderWarning::DEVICE_LIMIT_EXCEEDED_FLAG); } -ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) { +ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const HashMap<Code, bool> &p_map) { uint32_t result = 0U; if (code_to_flags_map == nullptr) { diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h index e309907181..8edf85842f 100644 --- a/servers/rendering/shader_warnings.h +++ b/servers/rendering/shader_warnings.h @@ -34,8 +34,9 @@ #ifdef DEBUG_ENABLED #include "core/string/string_name.h" +#include "core/templates/hash_map.h" #include "core/templates/list.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/variant/variant.h" class ShaderWarning { @@ -82,7 +83,7 @@ public: static String get_name_from_code(Code p_code); static Code get_code_from_name(const String &p_name); - static CodeFlags get_flags_from_codemap(const Map<Code, bool> &p_map); + static CodeFlags get_flags_from_codemap(const HashMap<Code, bool> &p_map); ShaderWarning(Code p_code = WARNING_MAX, int p_line = -1, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()); }; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 136664e333..fc40f058aa 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2885,6 +2885,7 @@ RenderingServer::RenderingServer() { GLOBAL_DEF("rendering/shading/overrides/force_lambert_over_burley.mobile", true); GLOBAL_DEF("rendering/driver/depth_prepass/enable", true); + GLOBAL_DEF("rendering/driver/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple"); GLOBAL_DEF_RST("rendering/textures/default_filters/use_nearest_mipmap_filter", false); GLOBAL_DEF_RST("rendering/textures/default_filters/anisotropic_filtering_level", 2); @@ -2933,7 +2934,7 @@ RenderingServer::RenderingServer() { ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/mode", PropertyInfo(Variant::INT, "rendering/scaling_3d/mode", - PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR (Fast)")); + PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR 1.0 (Fast)")); ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/scale", PropertyInfo(Variant::FLOAT, @@ -3002,44 +3003,15 @@ RenderingServer::RenderingServer() { GLOBAL_DEF("rendering/limits/cluster_builder/max_clustered_elements", 512); ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/cluster_builder/max_clustered_elements", PropertyInfo(Variant::FLOAT, "rendering/limits/cluster_builder/max_clustered_elements", PROPERTY_HINT_RANGE, "32,8192,1")); - GLOBAL_DEF_RST_BASIC("xr/shaders/enabled", false); + // OpenGL limits + GLOBAL_DEF_RST("rendering/limits/opengl/max_renderable_elements", 65536); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_renderable_elements", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_elements", PROPERTY_HINT_RANGE, "1024,65536,1")); + GLOBAL_DEF_RST("rendering/limits/opengl/max_renderable_lights", 256); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_renderable_lights", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_lights", PROPERTY_HINT_RANGE, "16,4096,1")); + GLOBAL_DEF_RST("rendering/limits/opengl/max_lights_per_object", 8); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_lights_per_object", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_lights_per_object", PROPERTY_HINT_RANGE, "2,1024,1")); - GLOBAL_DEF_RST("rendering/2d/options/use_software_skinning", true); - GLOBAL_DEF_RST("rendering/2d/options/ninepatch_mode", 1); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/options/ninepatch_mode", PropertyInfo(Variant::INT, "rendering/2d/options/ninepatch_mode", PROPERTY_HINT_ENUM, "Fixed,Scaling")); - - GLOBAL_DEF_RST("rendering/2d/opengl/batching_send_null", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/batching_send_null", PropertyInfo(Variant::INT, "rendering/2d/opengl/batching_send_null", PROPERTY_HINT_ENUM, "Default (On),Off,On")); - GLOBAL_DEF_RST("rendering/2d/opengl/batching_stream", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/batching_stream", PropertyInfo(Variant::INT, "rendering/2d/opengl/batching_stream", PROPERTY_HINT_ENUM, "Default (Off),Off,On")); - GLOBAL_DEF_RST("rendering/2d/opengl/legacy_orphan_buffers", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/legacy_orphan_buffers", PropertyInfo(Variant::INT, "rendering/2d/opengl/legacy_orphan_buffers", PROPERTY_HINT_ENUM, "Default (On),Off,On")); - GLOBAL_DEF_RST("rendering/2d/opengl/legacy_stream", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/legacy_stream", PropertyInfo(Variant::INT, "rendering/2d/opengl/legacy_stream", PROPERTY_HINT_ENUM, "Default (On),Off,On")); - - GLOBAL_DEF("rendering/batching/options/use_batching", false); - GLOBAL_DEF_RST("rendering/batching/options/use_batching_in_editor", false); - GLOBAL_DEF("rendering/batching/options/single_rect_fallback", false); - GLOBAL_DEF("rendering/batching/parameters/max_join_item_commands", 16); - GLOBAL_DEF("rendering/batching/parameters/colored_vertex_format_threshold", 0.25f); - GLOBAL_DEF("rendering/batching/lights/scissor_area_threshold", 1.0f); - GLOBAL_DEF("rendering/batching/lights/max_join_items", 32); - GLOBAL_DEF("rendering/batching/parameters/batch_buffer_size", 16384); - GLOBAL_DEF("rendering/batching/parameters/item_reordering_lookahead", 4); - GLOBAL_DEF("rendering/batching/debug/flash_batching", false); - GLOBAL_DEF("rendering/batching/debug/diagnose_frame", false); - GLOBAL_DEF("rendering/gles2/compatibility/disable_half_float", false); - GLOBAL_DEF("rendering/gles2/compatibility/enable_high_float.Android", false); - GLOBAL_DEF("rendering/batching/precision/uv_contract", false); - GLOBAL_DEF("rendering/batching/precision/uv_contract_amount", 100); - - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/max_join_item_commands", PropertyInfo(Variant::INT, "rendering/batching/parameters/max_join_item_commands", PROPERTY_HINT_RANGE, "0,65535")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/colored_vertex_format_threshold", PropertyInfo(Variant::FLOAT, "rendering/batching/parameters/colored_vertex_format_threshold", PROPERTY_HINT_RANGE, "0.0,1.0,0.01")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/batch_buffer_size", PropertyInfo(Variant::INT, "rendering/batching/parameters/batch_buffer_size", PROPERTY_HINT_RANGE, "1024,65535,1024")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/lights/scissor_area_threshold", PropertyInfo(Variant::FLOAT, "rendering/batching/lights/scissor_area_threshold", PROPERTY_HINT_RANGE, "0.0,1.0")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/lights/max_join_items", PropertyInfo(Variant::INT, "rendering/batching/lights/max_join_items", PROPERTY_HINT_RANGE, "0,512")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/item_reordering_lookahead", PropertyInfo(Variant::INT, "rendering/batching/parameters/item_reordering_lookahead", PROPERTY_HINT_RANGE, "0,256")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/precision/uv_contract_amount", PropertyInfo(Variant::INT, "rendering/batching/precision/uv_contract_amount", PROPERTY_HINT_RANGE, "0,10000")); + GLOBAL_DEF_RST_BASIC("xr/shaders/enabled", false); } RenderingServer::~RenderingServer() { diff --git a/servers/text_server.h b/servers/text_server.h index b08aa26917..f96146a549 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -159,7 +159,7 @@ public: void _draw_hex_code_box_number(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const; protected: - Map<char32_t, char32_t> diacritics_map; + HashMap<char32_t, char32_t> diacritics_map; void _diacritics_map_add(const String &p_from, char32_t p_to); void _init_diacritics_map(); diff --git a/servers/xr/xr_positional_tracker.h b/servers/xr/xr_positional_tracker.h index cd06d4a087..8371dfcbb5 100644 --- a/servers/xr/xr_positional_tracker.h +++ b/servers/xr/xr_positional_tracker.h @@ -60,8 +60,8 @@ private: String profile; // this is interface dependent, for OpenXR this will be the interaction profile bound for to the tracker TrackerHand hand; // if known, the hand this tracker is held in - Map<StringName, Ref<XRPose>> poses; - Map<StringName, Variant> inputs; + HashMap<StringName, Ref<XRPose>> poses; + HashMap<StringName, Variant> inputs; protected: static void _bind_methods(); |