diff options
Diffstat (limited to 'servers')
56 files changed, 944 insertions, 908 deletions
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index ed140c2244..e6257d9260 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -52,7 +52,7 @@ Error AudioDriverDummy::init() { } return OK; -}; +} void AudioDriverDummy::thread_func(void *p_udata) { AudioDriverDummy *ad = static_cast<AudioDriverDummy *>(p_udata); @@ -68,31 +68,31 @@ void AudioDriverDummy::thread_func(void *p_udata) { ad->stop_counting_ticks(); ad->unlock(); - }; + } OS::get_singleton()->delay_usec(usdelay); - }; -}; + } +} void AudioDriverDummy::start() { active.set(); -}; +} int AudioDriverDummy::get_mix_rate() const { return mix_rate; -}; +} AudioDriver::SpeakerMode AudioDriverDummy::get_speaker_mode() const { return speaker_mode; -}; +} void AudioDriverDummy::lock() { mutex.lock(); -}; +} void AudioDriverDummy::unlock() { mutex.unlock(); -}; +} void AudioDriverDummy::set_use_threads(bool p_use_threads) { use_threads = p_use_threads; @@ -141,7 +141,7 @@ void AudioDriverDummy::finish() { if (samples_in) { memdelete_arr(samples_in); - }; + } } AudioDriverDummy::AudioDriverDummy() { diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h index 8c858a2483..823bad1d2e 100644 --- a/servers/audio/audio_driver_dummy.h +++ b/servers/audio/audio_driver_dummy.h @@ -59,17 +59,18 @@ class AudioDriverDummy : public AudioDriver { static AudioDriverDummy *singleton; public: - const char *get_name() const { + virtual const char *get_name() const override { return "Dummy"; }; - virtual Error init(); - virtual void start(); - virtual int get_mix_rate() const; - virtual SpeakerMode get_speaker_mode() const; - virtual void lock(); - virtual void unlock(); - virtual void finish(); + virtual Error init() override; + virtual void start() override; + virtual int get_mix_rate() const override; + virtual SpeakerMode get_speaker_mode() const override; + + virtual void lock() override; + virtual void unlock() override; + virtual void finish() override; void set_use_threads(bool p_use_threads); void set_speaker_mode(SpeakerMode p_mode); diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 90997ac16e..32ee650f8d 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -367,7 +367,7 @@ void AudioStreamPlaybackMicrophone::start(double p_from_pos) { input_ofs = 0; - if (AudioDriver::get_singleton()->capture_start() == OK) { + if (AudioDriver::get_singleton()->input_start() == OK) { active = true; begin_resample(); } @@ -375,7 +375,7 @@ void AudioStreamPlaybackMicrophone::start(double p_from_pos) { void AudioStreamPlaybackMicrophone::stop() { if (active) { - AudioDriver::get_singleton()->capture_stop(); + AudioDriver::get_singleton()->input_stop(); active = false; } } diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp index 2693b2a56a..11c1d44472 100644 --- a/servers/audio/effects/audio_effect_pitch_shift.cpp +++ b/servers/audio/effects/audio_effect_pitch_shift.cpp @@ -309,7 +309,7 @@ Ref<AudioEffectInstance> AudioEffectPitchShift::instantiate() { } void AudioEffectPitchShift::set_pitch_scale(float p_pitch_scale) { - ERR_FAIL_COND(p_pitch_scale <= 0.0); + ERR_FAIL_COND(!(p_pitch_scale > 0.0)); pitch_scale = p_pitch_scale; } diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 8c877e4eed..0344bf322d 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1640,8 +1640,8 @@ String AudioServer::get_output_device() { return AudioDriver::get_singleton()->get_output_device(); } -void AudioServer::set_output_device(String output_device) { - AudioDriver::get_singleton()->set_output_device(output_device); +void AudioServer::set_output_device(const String &p_name) { + AudioDriver::get_singleton()->set_output_device(p_name); } PackedStringArray AudioServer::get_input_device_list() { @@ -1711,9 +1711,10 @@ void AudioServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_speaker_mode"), &AudioServer::get_speaker_mode); ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioServer::get_mix_rate); + ClassDB::bind_method(D_METHOD("get_output_device_list"), &AudioServer::get_output_device_list); ClassDB::bind_method(D_METHOD("get_output_device"), &AudioServer::get_output_device); - ClassDB::bind_method(D_METHOD("set_output_device", "output_device"), &AudioServer::set_output_device); + ClassDB::bind_method(D_METHOD("set_output_device", "name"), &AudioServer::set_output_device); ClassDB::bind_method(D_METHOD("get_time_to_next_mix"), &AudioServer::get_time_to_next_mix); ClassDB::bind_method(D_METHOD("get_time_since_last_mix"), &AudioServer::get_time_since_last_mix); diff --git a/servers/audio_server.h b/servers/audio_server.h index d3d87a8400..155beb2000 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -88,26 +88,32 @@ public: static AudioDriver *get_singleton(); void set_singleton(); + // Virtual API to implement. + virtual const char *get_name() const = 0; virtual Error init() = 0; virtual void start() = 0; virtual int get_mix_rate() const = 0; virtual SpeakerMode get_speaker_mode() const = 0; - virtual PackedStringArray get_output_device_list(); - virtual String get_output_device(); - virtual void set_output_device(String output_device) {} + virtual float get_latency() { return 0; } + virtual void lock() = 0; virtual void unlock() = 0; virtual void finish() = 0; - virtual Error capture_start() { return FAILED; } - virtual Error capture_stop() { return FAILED; } - virtual void set_input_device(const String &p_name) {} - virtual String get_input_device() { return "Default"; } + virtual PackedStringArray get_output_device_list(); + virtual String get_output_device(); + virtual void set_output_device(const String &p_name) {} + + virtual Error input_start() { return FAILED; } + virtual Error input_stop() { return FAILED; } + virtual PackedStringArray get_input_device_list(); + virtual String get_input_device() { return "Default"; } + virtual void set_input_device(const String &p_name) {} - virtual float get_latency() { return 0; } + // SpeakerMode get_speaker_mode_by_total_channels(int p_channels) const; int get_total_channels_by_speaker_mode(SpeakerMode) const; @@ -421,7 +427,7 @@ public: PackedStringArray get_output_device_list(); String get_output_device(); - void set_output_device(String output_device); + void set_output_device(const String &p_name); PackedStringArray get_input_device_list(); String get_input_device(); diff --git a/servers/debugger/servers_debugger.cpp b/servers/debugger/servers_debugger.cpp index c44f9a3a1b..75452be49b 100644 --- a/servers/debugger/servers_debugger.cpp +++ b/servers/debugger/servers_debugger.cpp @@ -409,6 +409,7 @@ Error ServersDebugger::_capture(void *p_user, const String &p_cmd, const Array & if (RenderingServer::get_singleton()->has_changed()) { RenderingServer::get_singleton()->draw(true, delta); } + EngineDebugger::get_singleton()->send_message("servers:drawn", Array()); } else if (p_cmd == "foreground") { singleton->last_draw_time = 0.0; DisplayServer::get_singleton()->window_move_to_foreground(); diff --git a/servers/navigation/navigation_utilities.h b/servers/navigation/navigation_utilities.h index 7897efd423..04d0ab0d98 100644 --- a/servers/navigation/navigation_utilities.h +++ b/servers/navigation/navigation_utilities.h @@ -69,10 +69,10 @@ struct PathQueryParameters { }; struct PathQueryResult { - Vector<Vector3> path; - Vector<int32_t> path_types; + PackedVector3Array path; + PackedInt32Array path_types; TypedArray<RID> path_rids; - Vector<int64_t> path_owner_ids; + PackedInt64Array path_owner_ids; }; } //namespace NavigationUtilities diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index 85ba8ed431..273bb9ceda 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -152,14 +152,15 @@ void NavigationServer2D::_emit_map_changed(RID p_map) { emit_signal(SNAME("map_changed"), p_map); } -#ifdef DEBUG_ENABLED void NavigationServer2D::set_debug_enabled(bool p_enabled) { NavigationServer3D::get_singleton()->set_debug_enabled(p_enabled); } + bool NavigationServer2D::get_debug_enabled() const { return NavigationServer3D::get_singleton()->get_debug_enabled(); } +#ifdef DEBUG_ENABLED void NavigationServer2D::set_debug_navigation_edge_connection_color(const Color &p_color) { NavigationServer3D::get_singleton()->set_debug_navigation_edge_connection_color(p_color); } @@ -200,6 +201,22 @@ Color NavigationServer2D::get_debug_navigation_link_connection_disabled_color() return NavigationServer3D::get_singleton()->get_debug_navigation_link_connection_disabled_color(); } +void NavigationServer2D::set_debug_navigation_geometry_edge_color(const Color &p_color) { + NavigationServer3D::get_singleton()->set_debug_navigation_geometry_edge_color(p_color); +} + +Color NavigationServer2D::get_debug_navigation_geometry_edge_color() const { + return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_edge_color(); +} + +void NavigationServer2D::set_debug_navigation_geometry_edge_disabled_color(const Color &p_color) { + NavigationServer3D::get_singleton()->set_debug_navigation_geometry_edge_disabled_color(p_color); +} + +Color NavigationServer2D::get_debug_navigation_geometry_edge_disabled_color() const { + return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_edge_disabled_color(); +} + void NavigationServer2D::set_debug_navigation_enable_edge_connections(const bool p_value) { NavigationServer3D::get_singleton()->set_debug_navigation_enable_edge_connections(p_value); } @@ -208,6 +225,22 @@ bool NavigationServer2D::get_debug_navigation_enable_edge_connections() const { return NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_connections(); } +void NavigationServer2D::set_debug_navigation_enable_geometry_face_random_color(const bool p_value) { + NavigationServer3D::get_singleton()->set_debug_navigation_enable_geometry_face_random_color(p_value); +} + +bool NavigationServer2D::get_debug_navigation_enable_geometry_face_random_color() const { + return NavigationServer3D::get_singleton()->get_debug_navigation_enable_geometry_face_random_color(); +} + +void NavigationServer2D::set_debug_navigation_enable_edge_lines(const bool p_value) { + NavigationServer3D::get_singleton()->set_debug_navigation_enable_edge_lines(p_value); +} + +bool NavigationServer2D::get_debug_navigation_enable_edge_lines() const { + return NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_lines(); +} + void NavigationServer2D::set_debug_navigation_agent_path_color(const Color &p_color) { NavigationServer3D::get_singleton()->set_debug_navigation_agent_path_color(p_color); } @@ -309,6 +342,9 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free); + ClassDB::bind_method(D_METHOD("set_debug_enabled", "enabled"), &NavigationServer2D::set_debug_enabled); + ClassDB::bind_method(D_METHOD("get_debug_enabled"), &NavigationServer2D::get_debug_enabled); + ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map"))); ADD_SIGNAL(MethodInfo("navigation_debug_changed")); diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index 746389404b..ed2e39e53c 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -225,6 +225,7 @@ public: /// Callback called at the end of the RVO process virtual void agent_set_callback(RID p_agent, Callable p_callback); + /// Returns a customized navigation path using a query parameters object virtual void query_path(const Ref<NavigationPathQueryParameters2D> &p_query_parameters, Ref<NavigationPathQueryResult2D> p_query_result) const; /// Destroy the `RID` @@ -233,10 +234,10 @@ public: NavigationServer2D(); virtual ~NavigationServer2D(); -#ifdef DEBUG_ENABLED void set_debug_enabled(bool p_enabled); bool get_debug_enabled() const; +#ifdef DEBUG_ENABLED void set_debug_navigation_edge_connection_color(const Color &p_color); Color get_debug_navigation_edge_connection_color() const; @@ -246,6 +247,12 @@ public: void set_debug_navigation_geometry_face_disabled_color(const Color &p_color); Color get_debug_navigation_geometry_face_disabled_color() const; + void set_debug_navigation_geometry_edge_color(const Color &p_color); + Color get_debug_navigation_geometry_edge_color() const; + + void set_debug_navigation_geometry_edge_disabled_color(const Color &p_color); + Color get_debug_navigation_geometry_edge_disabled_color() const; + void set_debug_navigation_link_connection_color(const Color &p_color); Color get_debug_navigation_link_connection_color() const; @@ -255,6 +262,12 @@ public: void set_debug_navigation_enable_edge_connections(const bool p_value); bool get_debug_navigation_enable_edge_connections() const; + void set_debug_navigation_enable_geometry_face_random_color(const bool p_value); + bool get_debug_navigation_enable_geometry_face_random_color() const; + + void set_debug_navigation_enable_edge_lines(const bool p_value); + bool get_debug_navigation_enable_edge_lines() const; + void set_debug_navigation_agent_path_color(const Color &p_color); Color get_debug_navigation_agent_path_color() const; diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 70897ae75c..e5cc426708 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -29,7 +29,6 @@ /**************************************************************************/ #include "navigation_server_3d.h" - #include "core/config/project_settings.h" NavigationServer3D *NavigationServer3D::singleton = nullptr; @@ -116,7 +115,9 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer3D::free); ClassDB::bind_method(D_METHOD("set_active", "active"), &NavigationServer3D::set_active); - ClassDB::bind_method(D_METHOD("process", "delta_time"), &NavigationServer3D::process); + + ClassDB::bind_method(D_METHOD("set_debug_enabled", "enabled"), &NavigationServer3D::set_debug_enabled); + ClassDB::bind_method(D_METHOD("get_debug_enabled"), &NavigationServer3D::get_debug_enabled); ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map"))); @@ -186,15 +187,22 @@ NavigationServer3D::~NavigationServer3D() { singleton = nullptr; } -NavigationServer3DCallback NavigationServer3DManager::create_callback = nullptr; +void NavigationServer3D::set_debug_enabled(bool p_enabled) { +#ifdef DEBUG_ENABLED + if (debug_enabled != p_enabled) { + debug_dirty = true; + } -void NavigationServer3DManager::set_default_server(NavigationServer3DCallback p_callback) { - create_callback = p_callback; + debug_enabled = p_enabled; + + if (debug_dirty) { + call_deferred("_emit_navigation_debug_changed_signal"); + } +#endif // DEBUG_ENABLED } -NavigationServer3D *NavigationServer3DManager::new_default_server() { - ERR_FAIL_COND_V(create_callback == nullptr, nullptr); - return create_callback(); +bool NavigationServer3D::get_debug_enabled() const { + return debug_enabled; } #ifdef DEBUG_ENABLED @@ -546,22 +554,6 @@ bool NavigationServer3D::get_debug_navigation_enable_link_connections_xray() con return debug_navigation_enable_link_connections_xray; } -void NavigationServer3D::set_debug_enabled(bool p_enabled) { - if (debug_enabled != p_enabled) { - debug_dirty = true; - } - - debug_enabled = p_enabled; - - if (debug_dirty) { - call_deferred("_emit_navigation_debug_changed_signal"); - } -} - -bool NavigationServer3D::get_debug_enabled() const { - return debug_enabled; -} - void NavigationServer3D::set_debug_navigation_enable_agent_paths(const bool p_value) { if (debug_navigation_enable_agent_paths != p_value) { debug_dirty = true; @@ -594,8 +586,6 @@ bool NavigationServer3D::get_debug_navigation_enable_agent_paths_xray() const { #endif // DEBUG_ENABLED -/////////////////////////////////////////////////////// - void NavigationServer3D::query_path(const Ref<NavigationPathQueryParameters3D> &p_query_parameters, Ref<NavigationPathQueryResult3D> p_query_result) const { ERR_FAIL_COND(!p_query_parameters.is_valid()); ERR_FAIL_COND(!p_query_result.is_valid()); @@ -607,3 +597,19 @@ void NavigationServer3D::query_path(const Ref<NavigationPathQueryParameters3D> & p_query_result->set_path_rids(_query_result.path_rids); p_query_result->set_path_owner_ids(_query_result.path_owner_ids); } + +/////////////////////////////////////////////////////// + +NavigationServer3DCallback NavigationServer3DManager::create_callback = nullptr; + +void NavigationServer3DManager::set_default_server(NavigationServer3DCallback p_callback) { + create_callback = p_callback; +} + +NavigationServer3D *NavigationServer3DManager::new_default_server() { + if (create_callback == nullptr) { + return nullptr; + } + + return create_callback(); +} diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index bc4bdf2a30..05df5ca0fe 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -253,12 +253,12 @@ public: virtual void process(real_t delta_time) = 0; /// Returns a customized navigation path using a query parameters object - void query_path(const Ref<NavigationPathQueryParameters3D> &p_query_parameters, Ref<NavigationPathQueryResult3D> p_query_result) const; + virtual void query_path(const Ref<NavigationPathQueryParameters3D> &p_query_parameters, Ref<NavigationPathQueryResult3D> p_query_result) const; virtual NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const = 0; NavigationServer3D(); - virtual ~NavigationServer3D(); + ~NavigationServer3D() override; enum ProcessInfo { INFO_ACTIVE_MAPS, @@ -274,9 +274,13 @@ public: virtual int get_process_info(ProcessInfo p_info) const = 0; -#ifdef DEBUG_ENABLED + void set_debug_enabled(bool p_enabled); + bool get_debug_enabled() const; + private: bool debug_enabled = false; + +#ifdef DEBUG_ENABLED bool debug_dirty = true; void _emit_navigation_debug_changed_signal(); @@ -313,9 +317,6 @@ private: Ref<StandardMaterial3D> debug_navigation_agent_path_point_material; public: - void set_debug_enabled(bool p_enabled); - bool get_debug_enabled() const; - void set_debug_navigation_edge_connection_color(const Color &p_color); Color get_debug_navigation_edge_connection_color() const; diff --git a/servers/navigation_server_3d_dummy.h b/servers/navigation_server_3d_dummy.h new file mode 100644 index 0000000000..fd9226e59e --- /dev/null +++ b/servers/navigation_server_3d_dummy.h @@ -0,0 +1,119 @@ +/**************************************************************************/ +/* navigation_server_3d_dummy.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 NAVIGATION_SERVER_3D_DUMMY_H +#define NAVIGATION_SERVER_3D_DUMMY_H + +#include "servers/navigation_server_3d.h" + +class NavigationServer3DDummy : public NavigationServer3D { + GDCLASS(NavigationServer3DDummy, NavigationServer3D); + +public: + TypedArray<RID> get_maps() const override { return TypedArray<RID>(); } + RID map_create() override { return RID(); } + void map_set_active(RID p_map, bool p_active) override {} + bool map_is_active(RID p_map) const override { return false; } + void map_set_up(RID p_map, Vector3 p_up) override {} + Vector3 map_get_up(RID p_map) const override { return Vector3(); } + void map_set_cell_size(RID p_map, real_t p_cell_size) override {} + real_t map_get_cell_size(RID p_map) const override { return 0; } + void map_set_edge_connection_margin(RID p_map, real_t p_connection_margin) override {} + real_t map_get_edge_connection_margin(RID p_map) const override { return 0; } + void map_set_link_connection_radius(RID p_map, real_t p_connection_radius) override {} + real_t map_get_link_connection_radius(RID p_map) const override { return 0; } + Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers) const override { return Vector<Vector3>(); } + Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const override { return Vector3(); } + Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const override { return Vector3(); } + Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const override { return Vector3(); } + RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const override { return RID(); } + TypedArray<RID> map_get_links(RID p_map) const override { return TypedArray<RID>(); } + TypedArray<RID> map_get_regions(RID p_map) const override { return TypedArray<RID>(); } + TypedArray<RID> map_get_agents(RID p_map) const override { return TypedArray<RID>(); } + void map_force_update(RID p_map) override {} + RID region_create() override { return RID(); } + void region_set_enter_cost(RID p_region, real_t p_enter_cost) override {} + real_t region_get_enter_cost(RID p_region) const override { return 0; } + void region_set_travel_cost(RID p_region, real_t p_travel_cost) override {} + real_t region_get_travel_cost(RID p_region) const override { return 0; } + void region_set_owner_id(RID p_region, ObjectID p_owner_id) override {} + ObjectID region_get_owner_id(RID p_region) const override { return ObjectID(); } + bool region_owns_point(RID p_region, const Vector3 &p_point) const override { return false; } + void region_set_map(RID p_region, RID p_map) override {} + RID region_get_map(RID p_region) const override { return RID(); } + void region_set_navigation_layers(RID p_region, uint32_t p_navigation_layers) override {} + uint32_t region_get_navigation_layers(RID p_region) const override { return 0; } + void region_set_transform(RID p_region, Transform3D p_transform) override {} + void region_set_navigation_mesh(RID p_region, Ref<NavigationMesh> p_navigation_mesh) override {} + void region_bake_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) override {} + int region_get_connections_count(RID p_region) const override { return 0; } + Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override { return Vector3(); } + Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override { return Vector3(); } + RID link_create() override { return RID(); } + void link_set_map(RID p_link, RID p_map) override {} + RID link_get_map(RID p_link) const override { return RID(); } + void link_set_bidirectional(RID p_link, bool p_bidirectional) override {} + bool link_is_bidirectional(RID p_link) const override { return false; } + void link_set_navigation_layers(RID p_link, uint32_t p_navigation_layers) override {} + uint32_t link_get_navigation_layers(RID p_link) const override { return 0; } + void link_set_start_position(RID p_link, Vector3 p_position) override {} + Vector3 link_get_start_position(RID p_link) const override { return Vector3(); } + void link_set_end_position(RID p_link, Vector3 p_position) override {} + Vector3 link_get_end_position(RID p_link) const override { return Vector3(); } + void link_set_enter_cost(RID p_link, real_t p_enter_cost) override {} + real_t link_get_enter_cost(RID p_link) const override { return 0; } + void link_set_travel_cost(RID p_link, real_t p_travel_cost) override {} + real_t link_get_travel_cost(RID p_link) const override { return 0; } + void link_set_owner_id(RID p_link, ObjectID p_owner_id) override {} + ObjectID link_get_owner_id(RID p_link) const override { return ObjectID(); } + RID agent_create() override { return RID(); } + void agent_set_map(RID p_agent, RID p_map) override {} + RID agent_get_map(RID p_agent) const override { return RID(); } + void agent_set_neighbor_distance(RID p_agent, real_t p_distance) override {} + void agent_set_max_neighbors(RID p_agent, int p_count) override {} + void agent_set_time_horizon(RID p_agent, real_t p_time) override {} + void agent_set_radius(RID p_agent, real_t p_radius) override {} + void agent_set_max_speed(RID p_agent, real_t p_max_speed) override {} + void agent_set_velocity(RID p_agent, Vector3 p_velocity) override {} + void agent_set_target_velocity(RID p_agent, Vector3 p_velocity) override {} + void agent_set_position(RID p_agent, Vector3 p_position) override {} + void agent_set_ignore_y(RID p_agent, bool p_ignore) override {} + bool agent_is_map_changed(RID p_agent) const override { return false; } + void agent_set_callback(RID p_agent, Callable p_callback) override {} + void free(RID p_object) override {} + void set_active(bool p_active) override {} + void process(real_t delta_time) override {} + NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const override { return NavigationUtilities::PathQueryResult(); } + int get_process_info(ProcessInfo p_info) const override { return 0; } + void set_debug_enabled(bool p_enabled) {} + bool get_debug_enabled() const { return false; } +}; + +#endif // NAVIGATION_SERVER_3D_DUMMY_H diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp index 3b5fbbced8..bbaec8be2b 100644 --- a/servers/physics_2d/godot_step_2d.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -30,6 +30,7 @@ #include "godot_step_2d.h" +#include "core/object/worker_thread_pool.h" #include "core/os/os.h" #define BODY_ISLAND_COUNT_RESERVE 128 diff --git a/servers/physics_2d/godot_step_2d.h b/servers/physics_2d/godot_step_2d.h index 75eeba4a3d..c08c6379de 100644 --- a/servers/physics_2d/godot_step_2d.h +++ b/servers/physics_2d/godot_step_2d.h @@ -33,7 +33,6 @@ #include "godot_space_2d.h" -#include "core/object/worker_thread_pool.h" #include "core/templates/local_vector.h" class GodotStep2D { diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp index 300dca4e08..d566d612ce 100644 --- a/servers/physics_3d/godot_shape_3d.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -1092,6 +1092,8 @@ void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) { if (err != OK) { ERR_PRINT("Failed to build convex hull"); } + extreme_vertices.resize(0); + vertex_neighbors.resize(0); AABB _aabb; diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp index 4119c58897..d09a3b4e6d 100644 --- a/servers/physics_3d/godot_step_3d.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -32,6 +32,7 @@ #include "godot_joint_3d.h" +#include "core/object/worker_thread_pool.h" #include "core/os/os.h" #define BODY_ISLAND_COUNT_RESERVE 128 diff --git a/servers/physics_3d/godot_step_3d.h b/servers/physics_3d/godot_step_3d.h index be7266b264..1c9b0af422 100644 --- a/servers/physics_3d/godot_step_3d.h +++ b/servers/physics_3d/godot_step_3d.h @@ -33,7 +33,6 @@ #include "godot_space_3d.h" -#include "core/object/worker_thread_pool.h" #include "core/templates/local_vector.h" class GodotStep3D { diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 6a163c86d2..c9cf8f99af 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -429,7 +429,7 @@ Vector<real_t> PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQue return ret; } -TypedArray<PackedVector2Array> PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) { +TypedArray<PackedVector3Array> PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) { ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); Vector<Vector3> ret; @@ -437,9 +437,9 @@ TypedArray<PackedVector2Array> PhysicsDirectSpaceState3D::_collide_shape(const R int rc = 0; bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc); if (!res) { - return TypedArray<PackedVector2Array>(); + return TypedArray<PackedVector3Array>(); } - TypedArray<PackedVector2Array> r; + TypedArray<PackedVector3Array> r; r.resize(rc * 2); for (int i = 0; i < rc * 2; i++) { r[i] = ret[i]; diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index abf22e68a4..2c7ebeea66 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -125,7 +125,7 @@ private: TypedArray<Dictionary> _intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results = 32); TypedArray<Dictionary> _intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32); Vector<real_t> _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query); - TypedArray<PackedVector2Array> _collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32); + TypedArray<PackedVector3Array> _collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32); Dictionary _get_rest_info(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query); protected: diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h index 9a3918fd86..b9e8bcc6f1 100644 --- a/servers/rendering/dummy/storage/light_storage.h +++ b/servers/rendering/dummy/storage/light_storage.h @@ -80,6 +80,7 @@ public: virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override { return RS::LIGHT_BAKE_DISABLED; } virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; } virtual uint64_t light_get_version(RID p_light) const override { return 0; } + virtual uint32_t light_get_cull_mask(RID p_light) const override { return 0; } /* LIGHT INSTANCE API */ diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index 41251b348c..67661ce821 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -145,6 +145,7 @@ public: virtual void decal_set_normal_fade(RID p_decal, float p_fade) override {} virtual AABB decal_get_aabb(RID p_decal) const override { return AABB(); } + virtual uint32_t decal_get_cull_mask(RID p_decal) const override { return 0; } virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp index 2b5d36d686..9389f8149e 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.cpp +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -411,12 +411,21 @@ SSEffects::~SSEffects() { /* SS Downsampler */ -void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, bool p_invalidate_uniform_set, Size2i p_full_screen_size, const Projection &p_projection) { +void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_view, const Projection &p_projection) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); ERR_FAIL_NULL(material_storage); + uint32_t view_count = p_render_buffers->get_view_count(); + Size2i full_screen_size = p_render_buffers->get_internal_size(); + Size2i size((full_screen_size.x + 1) / 2, (full_screen_size.y + 1) / 2); + + // Make sure our buffers exist, buffers are automatically cleared if view count or size changes. + if (!p_render_buffers->has_texture(RB_SCOPE_SSDS, RB_LINEAR_DEPTH)) { + p_render_buffers->create_texture(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, RD::DATA_FORMAT_R16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, size, view_count * 4, 5); + } + // Downsample and deinterleave the depth buffer for SSAO and SSIL RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -447,48 +456,35 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_ } } + RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode); int depth_index = use_half_size ? 1 : 0; RD::get_singleton()->draw_command_begin_label("Downsample Depth"); - if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) { - if (ss_effects.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects.downsample_uniform_set)) { - RD::get_singleton()->free(ss_effects.downsample_uniform_set); - ss_effects.downsample_uniform_set = RID(); - } - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.append_id(p_depth_mipmaps[depth_index + 1]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 1; - u.append_id(p_depth_mipmaps[depth_index + 2]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 2; - u.append_id(p_depth_mipmaps[depth_index + 3]); - uniforms.push_back(u); - } - if (use_full_mips) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 3; - u.append_id(p_depth_mipmaps[4]); - uniforms.push_back(u); + RID downsample_uniform_set; + if (use_mips) { + // Grab our downsample uniform set from cache, these are automatically cleaned up if the depth textures are cleared. + // This also ensures we can switch between left eye and right eye uniform sets without recreating the uniform twice a frame. + Vector<RD::Uniform> u_depths; + + // Note, use_full_mips is true if either SSAO or SSIL uses half size, but the other full size and we're using mips. + // That means we're filling all 5 levels. + // In this scenario `depth_index` will be 0. + for (int i = 0; i < (use_full_mips ? 4 : 3); i++) { + RID depth_mipmap = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, depth_index + i + 1, 4, 1); + + RD::Uniform u_depth; + u_depth.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u_depth.binding = i; + u_depth.append_id(depth_mipmap); + u_depths.push_back(u_depth); } - ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2); + + // This before only used SS_EFFECTS_DOWNSAMPLE_MIPMAP or SS_EFFECTS_DOWNSAMPLE_FULL_MIPS + downsample_uniform_set = uniform_set_cache->get_cache_vec(shader, 2, u_depths); } - float depth_linearize_mul = -p_projection.columns[3][2]; + float depth_linearize_mul = -p_projection.columns[3][2] * 0.5; float depth_linearize_add = p_projection.columns[2][2]; if (depth_linearize_mul * depth_linearize_add < 0) { depth_linearize_add = -depth_linearize_add; @@ -501,25 +497,30 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_ ss_effects.downsample_push_constant.z_near = p_projection.get_z_near(); ss_effects.downsample_push_constant.z_far = p_projection.get_z_far(); } - ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x; - ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y; + ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / full_screen_size.x; + ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / full_screen_size.y; ss_effects.downsample_push_constant.radius_sq = 1.0; - RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode); RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_buffer })); - RD::Uniform u_depth_mipmaps(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_depth_mipmaps[depth_index + 0] })); + RID depth_texture = p_render_buffers->get_depth_texture(p_view); + RID depth_mipmap = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, depth_index, 4, 1); + + RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, depth_texture })); + RD::Uniform u_depth_mipmap(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_mipmap })); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_depth_buffer), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmaps), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmap), 1); if (use_mips) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, downsample_uniform_set, 2); } RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant)); - Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1))); + if (use_half_size) { + size.x = MAX(1, size.x >> 1); + size.y = MAX(1, size.y >> 1); + } RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1); RD::get_singleton()->compute_list_add_barrier(compute_list); @@ -543,7 +544,7 @@ void SSEffects::ssil_set_quality(RS::EnvironmentSSILQuality p_quality, bool p_ha ssil_fadeout_to = p_fadeout_to; } -void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) { +void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const RID *p_ssil_slices, const RID *p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); @@ -578,12 +579,13 @@ void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> RD::get_singleton()->compute_list_add_barrier(p_compute_list); } -void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth) { +void SSEffects::ssil_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings) { if (p_ssil_buffers.half_size != ssil_half_size) { - ssil_free(p_ssil_buffers); + p_render_buffers->clear_context(RB_SCOPE_SSIL); } - if (ssil_half_size) { + p_ssil_buffers.half_size = ssil_half_size; + if (p_ssil_buffers.half_size) { p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4; p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4; p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8; @@ -595,104 +597,59 @@ void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const S p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4; } - if (p_ssil_buffers.ssil_final.is_null()) { - { - p_ssil_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, ssil_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY); - } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = p_settings.full_screen_size.x; - tf.height = p_settings.full_screen_size.y; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - p_ssil_buffers.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssil_buffers.ssil_final, "SSIL texture"); - RD::get_singleton()->texture_clear(p_ssil_buffers.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1); - if (p_ssil_buffers.last_frame.is_null()) { - tf.mipmaps = 6; - p_ssil_buffers.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssil_buffers.last_frame, "Last Frame Radiance"); - RD::get_singleton()->texture_clear(p_ssil_buffers.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1); - for (uint32_t i = 0; i < 6; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.last_frame, 0, i); - p_ssil_buffers.last_frame_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " "); - } - } - } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = p_ssil_buffers.buffer_width; - tf.height = p_ssil_buffers.buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - p_ssil_buffers.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssil_buffers.deinterleaved, "SSIL deinterleaved buffer"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.deinterleaved, i, 0); - p_ssil_buffers.deinterleaved_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " "); - } - } + uint32_t view_count = p_render_buffers->get_view_count(); + Size2i full_size = Size2i(p_ssil_buffers.buffer_width, p_ssil_buffers.buffer_height); + Size2i half_size = Size2i(p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height); - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = p_ssil_buffers.buffer_width; - tf.height = p_ssil_buffers.buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - p_ssil_buffers.pong = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssil_buffers.pong, "SSIL deinterleaved pong buffer"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.pong, i, 0); - p_ssil_buffers.pong_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " "); - } - } + // We create our intermediate and final results as render buffers. + // These are automatically cached and cleaned up when our viewport resizes + // or when our viewport gets destroyed. - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = p_ssil_buffers.buffer_width; - tf.height = p_ssil_buffers.buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - p_ssil_buffers.edges = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssil_buffers.edges, "SSIL edges buffer"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.edges, i, 0); - p_ssil_buffers.edges_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " "); - } - } + if (!p_render_buffers->has_texture(RB_SCOPE_SSIL, RB_FINAL)) { // We don't strictly have to check if it exists but we only want to clear it when we create it... + RID final = p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_FINAL, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT); + RD::get_singleton()->texture_clear(final, Color(0, 0, 0, 0), 0, 1, 0, view_count); + } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = p_ssil_buffers.half_buffer_width; - tf.height = p_ssil_buffers.half_buffer_height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - p_ssil_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[0], "SSIL Importance Map"); - p_ssil_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[1], "SSIL Importance Map Pong"); - } - p_ssil_buffers.half_size = ssil_half_size; + if (!p_render_buffers->has_texture(RB_SCOPE_SSIL, RB_LAST_FRAME)) { + RID last_frame = p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_LAST_FRAME, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT, RD::TEXTURE_SAMPLES_1, p_settings.full_screen_size, 0, 6); + RD::get_singleton()->texture_clear(last_frame, Color(0, 0, 0, 0), 0, 6, 0, view_count); } + + // As we're not clearing these, and render buffers will return the cached texture if it already exists, + // we don't first check has_texture here + + p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_DEINTERLEAVED, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count); + p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count); + p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_EDGES, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count); + p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_IMPORTANCE_MAP, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, half_size); + p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_IMPORTANCE_PONG, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, half_size); } -void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings) { +void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, uint32_t p_view, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); ERR_FAIL_NULL(material_storage); RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting"); + + // Obtain our (cached) buffer slices for the view we are rendering. + RID last_frame = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_LAST_FRAME, p_view, 0, 1, 6); + RID deinterleaved = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED, p_view * 4, 0, 4, 1); + RID deinterleaved_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, 4 * p_view, 0, 4, 1); + RID edges = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_EDGES, 4 * p_view, 0, 4, 1); + RID importance_map = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_IMPORTANCE_MAP, p_view, 0); + RID importance_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_IMPORTANCE_PONG, p_view, 0); + + RID deinterleaved_slices[4]; + RID deinterleaved_pong_slices[4]; + RID edges_slices[4]; + for (uint32_t i = 0; i < 4; i++) { + deinterleaved_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED, p_view * 4 + i, 0); + deinterleaved_pong_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, p_view * 4 + i, 0); + edges_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_EDGES, p_view * 4 + i, 0); + } + //Store projection info before starting the compute list SSILProjectionUniforms projection_uniforms; store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix); @@ -701,7 +658,7 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant)); - RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0); + RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, SSIL_GATHER); 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); @@ -711,8 +668,14 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; - ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width; - ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height; + ssil.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x; + ssil.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y; + if (ssil_half_size) { + ssil.gather_push_constant.half_screen_pixel_size[0] *= 2.0; + ssil.gather_push_constant.half_screen_pixel_size[1] *= 2.0; + } + ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.75; + ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.75; float tan_half_fov_x = 1.0 / p_projection.columns[0][0]; float tan_half_fov_y = 1.0 / p_projection.columns[1][1]; ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; @@ -723,9 +686,6 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers ssil.gather_push_constant.z_far = p_projection.get_z_far(); ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); - ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25; - ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25; - ssil.gather_push_constant.radius = p_settings.radius; float radius_near_limit = (p_settings.radius * 1.2f); if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) { @@ -749,78 +709,69 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers ssil.gather_push_constant.quality = MAX(0, ssil_quality - 1); ssil.gather_push_constant.size_multiplier = ssil_half_size ? 2 : 1; - if (p_ssil_buffers.projection_uniform_set.is_null()) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(default_mipmap_sampler); - u.append_id(p_ssil_buffers.last_frame); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 1; - u.append_id(ssil.projection_uniform_buffer); - uniforms.push_back(u); - } - p_ssil_buffers.projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3); + // We are using our uniform cache so our uniform sets are automatically freed when our textures are freed. + // It also ensures that we're reusing the right cached entry in a multiview situation without us having to + // remember each instance of the uniform set. + + RID projection_uniform_set; + { + RD::Uniform u_last_frame; + u_last_frame.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u_last_frame.binding = 0; + u_last_frame.append_id(default_mipmap_sampler); + u_last_frame.append_id(last_frame); + + RD::Uniform u_projection; + u_projection.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u_projection.binding = 1; + u_projection.append_id(ssil.projection_uniform_buffer); + + projection_uniform_set = uniform_set_cache->get_cache(shader, 3, u_last_frame, u_projection); } - if (p_ssil_buffers.gather_uniform_set.is_null()) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(default_sampler); - u.append_id(p_ssil_buffers.depth_texture_view); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 1; - u.append_id(p_normal_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 2; - u.append_id(ss_effects.gather_constants_buffer); - uniforms.push_back(u); - } - p_ssil_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0); + RID gather_uniform_set; + { + RID depth_texture_view = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, ssil_half_size ? 1 : 0, 4, 4); + + RD::Uniform u_depth_texture_view; + u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u_depth_texture_view.binding = 0; + u_depth_texture_view.append_id(ss_effects.mirror_sampler); + u_depth_texture_view.append_id(depth_texture_view); + + RD::Uniform u_normal_buffer; + u_normal_buffer.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u_normal_buffer.binding = 1; + u_normal_buffer.append_id(p_normal_buffer); + + RD::Uniform u_gather_constants_buffer; + u_gather_constants_buffer.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u_gather_constants_buffer.binding = 2; + u_gather_constants_buffer.append_id(ss_effects.gather_constants_buffer); + + gather_uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth_texture_view, u_normal_buffer, u_gather_constants_buffer); } - if (p_ssil_buffers.importance_map_uniform_set.is_null()) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.append_id(p_ssil_buffers.pong); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 1; - u.append_id(default_sampler); - u.append_id(p_ssil_buffers.importance_map[0]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 2; - u.append_id(ssil.importance_map_load_counter); - uniforms.push_back(u); - } - p_ssil_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1); + RID importance_map_uniform_set; + { + RD::Uniform u_pong; + u_pong.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u_pong.binding = 0; + u_pong.append_id(deinterleaved_pong); + + RD::Uniform u_importance_map; + u_importance_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u_importance_map.binding = 1; + u_importance_map.append_id(default_sampler); + u_importance_map.append_id(importance_map); + + RD::Uniform u_load_counter; + u_load_counter.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u_load_counter.binding = 2; + u_load_counter.append_id(ssil.importance_map_load_counter); + + RID shader_adaptive = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, SSIL_GATHER_ADAPTIVE); + importance_map_uniform_set = uniform_set_cache->get_cache(shader_adaptive, 1, u_pong, u_importance_map, u_load_counter); } if (ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) { @@ -828,38 +779,42 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width; ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height; ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI; + //base pass RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]); - gather_ssil(compute_list, p_ssil_buffers.pong_slices, p_ssil_buffers.edges_slices, p_settings, true, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set); + gather_ssil(compute_list, deinterleaved_pong_slices, edges_slices, p_settings, true, gather_uniform_set, importance_map_uniform_set, projection_uniform_set); //generate importance map - RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong })); - RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[0] })); + RID gen_imp_shader = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 0); + RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong })); + RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map })); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_with_sampler), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 0, u_ssil_pong_with_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1); RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1); RD::get_singleton()->compute_list_add_barrier(compute_list); // process Importance Map A - RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[0] })); - RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[1] })); + RID proc_imp_shader_a = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 1); + RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map })); + RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong })); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 0, u_importance_map_with_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 1, u_importance_map_pong), 1); RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1); RD::get_singleton()->compute_list_add_barrier(compute_list); // process Importance Map B - RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[1] })); + RID proc_imp_shader_b = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2); + RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong })); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 0, u_importance_map_pong_with_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2); RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant)); RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1); @@ -872,7 +827,7 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]); } - gather_ssil(compute_list, p_ssil_buffers.deinterleaved_slices, p_ssil_buffers.edges_slices, p_settings, false, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set); + gather_ssil(compute_list, deinterleaved_slices, edges_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set, projection_uniform_set); RD::get_singleton()->draw_command_end_label(); //Gather } @@ -895,6 +850,8 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers } } + RID blur_shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, blur_pipeline - SSIL_BLUR_PASS); + for (int i = 0; i < 4; i++) { if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { continue; @@ -903,30 +860,30 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]); if (pass % 2 == 0) { if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { - RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0); + RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_slice), 0); } else { - RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.deinterleaved_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0); + RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_slice), 0); } - RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.pong_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong_slice), 1); + RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ deinterleaved_pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ssil_pong_slice), 1); } else { if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) { - RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0); + RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_pong_slice), 0); } else { - RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.pong_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0); + RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, deinterleaved_pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_pong_slice), 0); } - RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.deinterleaved_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_slice), 1); + RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ssil_slice), 1); } - RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges_slice), 2); + RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ edges_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 2, u_edges_slice), 2); RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant)); @@ -961,18 +918,19 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]); - RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.ssil_final })); + RID final = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_FINAL, p_view, 0); + RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ final })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_destination), 0); if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW && ssil_blur_passes % 2 == 0) { - RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved })); + RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil), 1); } else { - RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong })); + RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong), 1); } - RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges })); + RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ edges })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges), 2); RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant)); @@ -990,34 +948,6 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier } -void SSEffects::ssil_free(SSILRenderBuffers &p_ssil_buffers) { - if (p_ssil_buffers.ssil_final.is_valid()) { - RD::get_singleton()->free(p_ssil_buffers.ssil_final); - RD::get_singleton()->free(p_ssil_buffers.deinterleaved); - RD::get_singleton()->free(p_ssil_buffers.pong); - RD::get_singleton()->free(p_ssil_buffers.edges); - RD::get_singleton()->free(p_ssil_buffers.importance_map[0]); - RD::get_singleton()->free(p_ssil_buffers.importance_map[1]); - RD::get_singleton()->free(p_ssil_buffers.last_frame); - - p_ssil_buffers.ssil_final = RID(); - p_ssil_buffers.deinterleaved = RID(); - p_ssil_buffers.pong = RID(); - p_ssil_buffers.edges = RID(); - p_ssil_buffers.deinterleaved_slices.clear(); - p_ssil_buffers.pong_slices.clear(); - p_ssil_buffers.edges_slices.clear(); - p_ssil_buffers.importance_map[0] = RID(); - p_ssil_buffers.importance_map[1] = RID(); - p_ssil_buffers.last_frame = RID(); - p_ssil_buffers.last_frame_slices.clear(); - - p_ssil_buffers.gather_uniform_set = RID(); - p_ssil_buffers.importance_map_uniform_set = RID(); - p_ssil_buffers.projection_uniform_set = RID(); - } -} - /* SSAO */ void SSEffects::ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { @@ -1029,13 +959,13 @@ void SSEffects::ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_ha ssao_fadeout_to = p_fadeout_to; } -void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) { +void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const RID *p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0); if ((ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) { - RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 0); + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1); } RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 1); // @@ -1062,11 +992,12 @@ void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> RD::get_singleton()->compute_list_add_barrier(p_compute_list); } -void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth) { +void SSEffects::ssao_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings) { if (p_ssao_buffers.half_size != ssao_half_size) { - ssao_free(p_ssao_buffers); + p_render_buffers->clear_context(RB_SCOPE_SSAO); } + p_ssao_buffers.half_size = ssao_half_size; if (ssao_half_size) { p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4; p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4; @@ -1079,79 +1010,45 @@ void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const S p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4; } - if (p_ssao_buffers.ao_deinterleaved.is_null()) { - { - p_ssao_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, ssao_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY); - } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8G8_UNORM; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = p_ssao_buffers.buffer_width; - tf.height = p_ssao_buffers.buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - p_ssao_buffers.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_deinterleaved, "SSAO De-interleaved Array"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_deinterleaved, i, 0); - p_ssao_buffers.ao_deinterleaved_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " "); - } - } + uint32_t view_count = p_render_buffers->get_view_count(); + Size2i full_size = Size2i(p_ssao_buffers.buffer_width, p_ssao_buffers.buffer_height); + Size2i half_size = Size2i(p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height); - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8G8_UNORM; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = p_ssao_buffers.buffer_width; - tf.height = p_ssao_buffers.buffer_height; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - p_ssao_buffers.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_pong, "SSAO De-interleaved Array Pong"); - for (uint32_t i = 0; i < 4; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_pong, i, 0); - p_ssao_buffers.ao_pong_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong"); - } - } + // As we're not clearing these, and render buffers will return the cached texture if it already exists, + // we don't first check has_texture here - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = p_ssao_buffers.buffer_width; - tf.height = p_ssao_buffers.buffer_height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - p_ssao_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[0], "SSAO Importance Map"); - p_ssao_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[1], "SSAO Importance Map Pong"); - } - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = p_settings.full_screen_size.x; - tf.height = p_settings.full_screen_size.y; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - p_ssao_buffers.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_final, "SSAO Final"); - } - p_ssao_buffers.half_size = ssao_half_size; - } + p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_DEINTERLEAVED, RD::DATA_FORMAT_R8G8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count); + p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, RD::DATA_FORMAT_R8G8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count); + p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_IMPORTANCE_MAP, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, half_size); + p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_IMPORTANCE_PONG, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, half_size); + p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_FINAL, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1); } -void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings) { +void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, uint32_t p_view, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); ERR_FAIL_NULL(material_storage); + // Obtain our (cached) buffer slices for the view we are rendering. + RID ao_deinterleaved = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED, p_view * 4, 0, 4, 1); + RID ao_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, p_view * 4, 0, 4, 1); + RID importance_map = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_IMPORTANCE_MAP, p_view, 0); + RID importance_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_IMPORTANCE_PONG, p_view, 0); + RID ao_final = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_FINAL, p_view, 0); + + RID ao_deinterleaved_slices[4]; + RID ao_pong_slices[4]; + for (uint32_t i = 0; i < 4; i++) { + ao_deinterleaved_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED, p_view * 4 + i, 0); + ao_pong_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, p_view * 4 + i, 0); + } + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant)); /* FIRST PASS */ - RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0); + RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, SSAO_GATHER); RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion"); @@ -1162,8 +1059,14 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; - ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width; - ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height; + ssao.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x; + ssao.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y; + if (ssao_half_size) { + ssao.gather_push_constant.half_screen_pixel_size[0] *= 2.0; + ssao.gather_push_constant.half_screen_pixel_size[1] *= 2.0; + } + ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.75; + ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.75; float tan_half_fov_x = 1.0 / p_projection.columns[0][0]; float tan_half_fov_y = 1.0 / p_projection.columns[1][1]; ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; @@ -1172,9 +1075,6 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y; ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); - ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25; - ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25; - ssao.gather_push_constant.radius = p_settings.radius; float radius_near_limit = (p_settings.radius * 1.2f); if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) { @@ -1201,60 +1101,52 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu ssao.gather_push_constant.quality = MAX(0, ssao_quality - 1); ssao.gather_push_constant.size_multiplier = ssao_half_size ? 2 : 1; - if (p_ssao_buffers.gather_uniform_set.is_null()) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(default_sampler); - u.append_id(p_ssao_buffers.depth_texture_view); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 1; - u.append_id(p_normal_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 2; - u.append_id(ss_effects.gather_constants_buffer); - uniforms.push_back(u); - } - p_ssao_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader, 0); - RD::get_singleton()->set_resource_name(p_ssao_buffers.gather_uniform_set, "SSAO Gather Uniform Set"); + // We are using our uniform cache so our uniform sets are automatically freed when our textures are freed. + // It also ensures that we're reusing the right cached entry in a multiview situation without us having to + // remember each instance of the uniform set. + RID gather_uniform_set; + { + RID depth_texture_view = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, ssao_half_size ? 1 : 0, 4, 4); + + RD::Uniform u_depth_texture_view; + u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u_depth_texture_view.binding = 0; + u_depth_texture_view.append_id(ss_effects.mirror_sampler); + u_depth_texture_view.append_id(depth_texture_view); + + RD::Uniform u_normal_buffer; + u_normal_buffer.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u_normal_buffer.binding = 1; + u_normal_buffer.append_id(p_normal_buffer); + + RD::Uniform u_gather_constants_buffer; + u_gather_constants_buffer.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u_gather_constants_buffer.binding = 2; + u_gather_constants_buffer.append_id(ss_effects.gather_constants_buffer); + + gather_uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth_texture_view, u_normal_buffer, u_gather_constants_buffer); } - if (p_ssao_buffers.importance_map_uniform_set.is_null()) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.append_id(p_ssao_buffers.ao_pong); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 1; - u.append_id(default_sampler); - u.append_id(p_ssao_buffers.importance_map[0]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 2; - u.append_id(ssao.importance_map_load_counter); - uniforms.push_back(u); - } - p_ssao_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1); - RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map_uniform_set, "SSAO Importance Map Uniform Set"); + RID importance_map_uniform_set; + { + RD::Uniform u_pong; + u_pong.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u_pong.binding = 0; + u_pong.append_id(ao_pong); + + RD::Uniform u_importance_map; + u_importance_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u_importance_map.binding = 1; + u_importance_map.append_id(default_sampler); + u_importance_map.append_id(importance_map); + + RD::Uniform u_load_counter; + u_load_counter.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u_load_counter.binding = 2; + u_load_counter.append_id(ssao.importance_map_load_counter); + + RID shader_adaptive = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, SSAO_GATHER_ADAPTIVE); + importance_map_uniform_set = uniform_set_cache->get_cache(shader_adaptive, 1, u_pong, u_importance_map, u_load_counter); } if (ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) { @@ -1266,41 +1158,44 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu //base pass RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]); - gather_ssao(compute_list, p_ssao_buffers.ao_pong_slices, p_settings, true, p_ssao_buffers.gather_uniform_set, RID()); + gather_ssao(compute_list, ao_pong_slices, p_settings, true, gather_uniform_set, RID()); //generate importance map + RID gen_imp_shader = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 0); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]); - RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_with_sampler), 0); + RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 0, u_ao_pong_with_sampler), 0); - RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[0] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1); + RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1); RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1); RD::get_singleton()->compute_list_add_barrier(compute_list); //process importance map A + RID proc_imp_shader_a = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 1); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]); - RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[0] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0); + RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 0, u_importance_map_with_sampler), 0); - RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[1] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1); + RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 1, u_importance_map_pong), 1); RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1); RD::get_singleton()->compute_list_add_barrier(compute_list); //process Importance Map B + RID proc_imp_shader_b = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]); - RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[1] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0); + RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 0, u_importance_map_pong_with_sampler), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2); RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1); @@ -1312,7 +1207,7 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]); } - gather_ssao(compute_list, p_ssao_buffers.ao_deinterleaved_slices, p_settings, false, p_ssao_buffers.gather_uniform_set, p_ssao_buffers.importance_map_uniform_set); + gather_ssao(compute_list, ao_deinterleaved_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set); RD::get_singleton()->draw_command_end_label(); // Gather SSAO } @@ -1344,29 +1239,30 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu continue; } + RID blur_shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, blur_pipeline - SSAO_BLUR_PASS); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]); if (pass % 2 == 0) { if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { - RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0); + RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_slices_with_sampler), 0); } else { - RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0); + RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, ao_deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_slices_with_sampler), 0); } - RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_pong_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_pong_slices), 1); + RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ao_pong_slices), 1); } else { if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { - RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0); + RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_pong_slices_with_sampler), 0); } else { - RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_pong_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0); + RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, ao_pong_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_pong_slices_with_sampler), 0); } - RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_deinterleaved_slices[i] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_slices), 1); + RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_deinterleaved_slices[i] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ao_slices), 1); } RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); @@ -1400,17 +1296,18 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu interleave_pipeline = SSAO_INTERLEAVE_SMART; } + RID interleave_shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, interleave_pipeline - SSAO_INTERLEAVE); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]); - RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_final })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_buffer), 0); + RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_final })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 0, u_upscale_buffer), 0); if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW && ssao_blur_passes % 2 == 0) { - RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1); + RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 1, u_ao), 1); } else { - RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1); + RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 1, u_ao), 1); } RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant)); @@ -1426,116 +1323,43 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier } -void SSEffects::ssao_free(SSAORenderBuffers &p_ssao_buffers) { - if (p_ssao_buffers.ao_final.is_valid()) { - RD::get_singleton()->free(p_ssao_buffers.ao_deinterleaved); - RD::get_singleton()->free(p_ssao_buffers.ao_pong); - RD::get_singleton()->free(p_ssao_buffers.ao_final); - - RD::get_singleton()->free(p_ssao_buffers.importance_map[0]); - RD::get_singleton()->free(p_ssao_buffers.importance_map[1]); - - p_ssao_buffers.ao_deinterleaved = RID(); - p_ssao_buffers.ao_pong = RID(); - p_ssao_buffers.ao_final = RID(); - p_ssao_buffers.importance_map[0] = RID(); - p_ssao_buffers.importance_map[1] = RID(); - p_ssao_buffers.ao_deinterleaved_slices.clear(); - p_ssao_buffers.ao_pong_slices.clear(); - - p_ssao_buffers.gather_uniform_set = RID(); - p_ssao_buffers.importance_map_uniform_set = RID(); - } -} - /* Screen Space Reflection */ void SSEffects::ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) { ssr_roughness_quality = p_quality; } -void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, const Size2i &p_screen_size, const uint32_t p_view_count) { - // As we are processing one view at a time, we can reuse buffers, only our output needs to have layers for each view. - if (p_ssr_buffers.size != p_screen_size || p_ssr_buffers.roughness_quality != ssr_roughness_quality) { - ssr_free(p_ssr_buffers); +void SSEffects::ssr_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format) { + if (p_ssr_buffers.roughness_quality != ssr_roughness_quality) { + // Buffers will already be cleared if view count or viewport size has changed, also cleared them if we change roughness. + p_render_buffers->clear_context(RB_SCOPE_SSR); } - if (p_ssr_buffers.output.is_valid()) { - // already allocated - return; - } - - p_ssr_buffers.size = p_screen_size; + Size2i internal_size = p_render_buffers->get_internal_size(); + p_ssr_buffers.size = Size2i(internal_size.x / 2, internal_size.y / 2); p_ssr_buffers.roughness_quality = ssr_roughness_quality; - if (p_ssr_buffers.depth_scaled.is_null()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R32_SFLOAT; - tf.width = p_screen_size.x; - tf.height = p_screen_size.y; - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.array_layers = 1; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; - - p_ssr_buffers.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssr_buffers.depth_scaled, "SSR Depth Scaled"); + // We are using barriers so we do not need to allocate textures for both views on anything but output... - tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + p_render_buffers->create_texture(RB_SCOPE_SSR, RB_DEPTH_SCALED, RD::DATA_FORMAT_R32_SFLOAT, RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 1); + p_render_buffers->create_texture(RB_SCOPE_SSR, RB_NORMAL_SCALED, RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 1); - p_ssr_buffers.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssr_buffers.normal_scaled, "SSR Normal Scaled"); + if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_render_buffers->has_texture(RB_SCOPE_SSR, RB_BLUR_RADIUS)) { + p_render_buffers->create_texture(RB_SCOPE_SSR, RB_BLUR_RADIUS, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 2); // 2 layers, for our two blur stages } - if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_ssr_buffers.blur_radius[0].is_valid()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = p_screen_size.x; - tf.height = p_screen_size.y; - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.array_layers = 1; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - - p_ssr_buffers.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[0], "SSR Blur Radius 0"); - p_ssr_buffers.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[1], "SSR Blur Radius 1"); - } - - if (p_ssr_buffers.intermediate.is_null()) { - RD::TextureFormat tf; - tf.format = p_color_format; - tf.width = p_screen_size.x; - tf.height = p_screen_size.y; - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.array_layers = 1; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - - p_ssr_buffers.intermediate = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssr_buffers.intermediate, "SSR Intermediate"); - - if (p_view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.array_layers = p_view_count; - } else { - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.array_layers = 1; - } - - p_ssr_buffers.output = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(p_ssr_buffers.output, "SSR Output"); - - for (uint32_t v = 0; v < p_view_count; v++) { - p_ssr_buffers.output_slices[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssr_buffers.output, v, 0); - } - } + p_render_buffers->create_texture(RB_SCOPE_SSR, RB_INTERMEDIATE, p_color_format, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 1); + p_render_buffers->create_texture(RB_SCOPE_SSR, RB_OUTPUT, p_color_format, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size); } -void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets) { +void SSEffects::screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const Projection *p_projections, const Vector3 *p_eye_offsets) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); ERR_FAIL_NULL(material_storage); + uint32_t view_count = p_render_buffers->get_view_count(); + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); { @@ -1546,7 +1370,7 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R ssr.ubo = RD::get_singleton()->uniform_buffer_create(sizeof(ScreenSpaceReflectionSceneData)); } - for (uint32_t v = 0; v < p_view_count; v++) { + for (uint32_t v = 0; v < view_count; v++) { store_camera(p_projections[v], scene_data.projection[v]); store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]); scene_data.eye_offset[v][0] = p_eye_offsets[v].x; @@ -1559,13 +1383,27 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R } uint32_t pipeline_specialization = 0; - if (p_view_count > 1) { + if (view_count > 1) { pipeline_specialization |= SSR_MULTIVIEW; } RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - for (uint32_t v = 0; v < p_view_count; v++) { + for (uint32_t v = 0; v < view_count; v++) { + // get buffers we need to use for this view + RID diffuse_slice = p_render_buffers->get_internal_texture(v); + RID depth_slice = p_render_buffers->get_depth_texture(v); + RID depth_scaled = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_DEPTH_SCALED); + RID normal_scaled = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_NORMAL_SCALED); + RID intermediate = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_INTERMEDIATE); + RID output = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_OUTPUT, v, 0); + + RID blur_radius[2]; + if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { + blur_radius[0] = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_BLUR_RADIUS, 0, 0); + blur_radius[1] = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_BLUR_RADIUS, 1, 0); + } + RD::get_singleton()->draw_command_begin_label(String("SSR View ") + itos(v)); { //scale color and depth to half @@ -1577,34 +1415,29 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R push_constant.camera_z_near = p_projections[v].get_z_near(); push_constant.orthogonal = p_projections[v].is_orthogonal(); push_constant.filter = false; //enabling causes arctifacts - push_constant.screen_size[0] = p_screen_size.x; - push_constant.screen_size[1] = p_screen_size.y; + push_constant.screen_size[0] = p_ssr_buffers.size.x; + push_constant.screen_size[1] = p_ssr_buffers.size.y; RID shader = ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipelines[pipeline_specialization]); - RD::Uniform u_diffuse(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse_slices[v] })); + RD::Uniform u_diffuse(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, diffuse_slice })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse), 0); - RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_slices[v] })); + RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, depth_slice })); RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_normal_roughness_slices[v] })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth, u_normal_roughness), 1); - if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { - RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output), 2); - } else { - RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2); - } + RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2); - RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled })); - RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.normal_scaled })); + RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_scaled })); + RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ normal_scaled })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth, u_scale_normal), 3); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionScalePushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1); RD::get_singleton()->compute_list_add_barrier(compute_list); @@ -1619,15 +1452,15 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R push_constant.camera_z_far = p_projections[v].get_z_far(); push_constant.camera_z_near = p_projections[v].get_z_near(); push_constant.orthogonal = p_projections[v].is_orthogonal(); - push_constant.screen_size[0] = p_screen_size.x; - push_constant.screen_size[1] = p_screen_size.y; + push_constant.screen_size[0] = p_ssr_buffers.size.x; + push_constant.screen_size[1] = p_ssr_buffers.size.y; push_constant.curve_fade_in = p_fade_in; push_constant.distance_fade = p_fade_out; push_constant.num_steps = p_max_steps; push_constant.depth_tolerance = p_tolerance; push_constant.use_half_res = true; - push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].columns[0][0]); - push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].columns[1][1]); + push_constant.proj_info[0] = -2.0f / (p_ssr_buffers.size.width * p_projections[v].columns[0][0]); + push_constant.proj_info[1] = -2.0f / (p_ssr_buffers.size.height * p_projections[v].columns[1][1]); push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0]; push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1]; @@ -1639,35 +1472,30 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4); + // read from intermediate + RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate })); + RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ depth_scaled })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_scale_depth), 0); + if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { - // read from output slices (our scale wrote into these) - RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] })); - RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output, u_scale_depth), 0); - - // write to intermediate (our roughness pass will output into output slices) - RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate })); - RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate, u_blur_radius), 1); + // write to output and blur radius + RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output })); + RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[0] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_output, u_blur_radius), 1); } else { - // read from intermediate (our scale wrote into these) - RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate })); - RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_scale_depth), 0); - - // We are not performing our blur so go directly to output. - RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] })); + // We are only writing output + RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_output), 1); } - RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled })); + RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ normal_scaled })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_scale_normal), 2); RD::Uniform u_metallic(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_metallic_slices[v] })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_metallic), 3); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1); RD::get_singleton()->draw_command_end_label(); } @@ -1682,8 +1510,8 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R push_constant.view_index = v; push_constant.orthogonal = p_projections[v].is_orthogonal(); push_constant.edge_tolerance = Math::sin(Math::deg_to_rad(15.0)); - push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].columns[0][0]); - push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].columns[1][1]); + push_constant.proj_info[0] = -2.0f / (p_ssr_buffers.size.width * p_projections[v].columns[0][0]); + push_constant.proj_info[1] = -2.0f / (p_ssr_buffers.size.height * p_projections[v].columns[1][1]); push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0]; push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1]; push_constant.vertical = 0; @@ -1698,8 +1526,8 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R push_constant.increment = 1; } - push_constant.screen_size[0] = p_screen_size.width; - push_constant.screen_size[1] = p_screen_size.height; + push_constant.screen_size[0] = p_ssr_buffers.size.width; + push_constant.screen_size[1] = p_ssr_buffers.size.height; // Horizontal pass @@ -1709,25 +1537,25 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]); - RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4); - - RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate })); - RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_blur_radius), 0); + RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output })); + RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[0] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output, u_blur_radius), 0); - RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled })); + RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ normal_scaled })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1); - RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] })); - RD::Uniform u_blur_radius2(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[1] })); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur, u_blur_radius2), 2); + RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate })); + RD::Uniform u_blur_radius2(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[1] })); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate, u_blur_radius2), 2); - RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled })); + RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_scaled })); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3); + RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1); RD::get_singleton()->compute_list_add_barrier(compute_list); // Vertical pass @@ -1739,16 +1567,16 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R push_constant.vertical = 1; - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_blur_radius2), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_blur_radius2), 0); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output), 2); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1); - if (v != p_view_count - 1) { + if (v != view_count - 1) { RD::get_singleton()->compute_list_add_barrier(compute_list); } @@ -1761,36 +1589,6 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R RD::get_singleton()->compute_list_end(); } -void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) { - for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { - p_ssr_buffers.output_slices[v] = RID(); - } - - if (p_ssr_buffers.output.is_valid()) { - RD::get_singleton()->free(p_ssr_buffers.output); - p_ssr_buffers.output = RID(); - } - - if (p_ssr_buffers.intermediate.is_valid()) { - RD::get_singleton()->free(p_ssr_buffers.intermediate); - p_ssr_buffers.intermediate = RID(); - } - - if (p_ssr_buffers.blur_radius[0].is_valid()) { - RD::get_singleton()->free(p_ssr_buffers.blur_radius[0]); - RD::get_singleton()->free(p_ssr_buffers.blur_radius[1]); - p_ssr_buffers.blur_radius[0] = RID(); - p_ssr_buffers.blur_radius[1] = RID(); - } - - if (p_ssr_buffers.depth_scaled.is_valid()) { - RD::get_singleton()->free(p_ssr_buffers.depth_scaled); - p_ssr_buffers.depth_scaled = RID(); - RD::get_singleton()->free(p_ssr_buffers.normal_scaled); - p_ssr_buffers.normal_scaled = RID(); - } -} - /* Subsurface scattering */ void SSEffects::sss_set_quality(RS::SubSurfaceScatteringQuality p_quality) { diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h index bac1d9b786..8585277e19 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.h +++ b/servers/rendering/renderer_rd/effects/ss_effects.h @@ -48,6 +48,26 @@ #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering_server.h" +#define RB_SCOPE_SSDS SNAME("rb_ssds") +#define RB_SCOPE_SSIL SNAME("rb_ssil") +#define RB_SCOPE_SSAO SNAME("rb_ssao") +#define RB_SCOPE_SSR SNAME("rb_ssr") + +#define RB_LINEAR_DEPTH SNAME("linear_depth") +#define RB_FINAL SNAME("final") +#define RB_LAST_FRAME SNAME("last_frame") +#define RB_DEINTERLEAVED SNAME("deinterleaved") +#define RB_DEINTERLEAVED_PONG SNAME("deinterleaved_pong") +#define RB_EDGES SNAME("edges") +#define RB_IMPORTANCE_MAP SNAME("importance_map") +#define RB_IMPORTANCE_PONG SNAME("importance_pong") + +#define RB_DEPTH_SCALED SNAME("depth_scaled") +#define RB_NORMAL_SCALED SNAME("normal_scaled") +#define RB_BLUR_RADIUS SNAME("blur_radius") +#define RB_INTERMEDIATE SNAME("intermediate") +#define RB_OUTPUT SNAME("output") + class RenderSceneBuffersRD; namespace RendererRD { @@ -64,7 +84,7 @@ public: /* SS Downsampler */ - void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, bool p_invalidate_uniform_set, Size2i p_full_screen_size, const Projection &p_projection); + void downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_view, const Projection &p_projection); /* SSIL */ void ssil_set_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to); @@ -75,23 +95,6 @@ public: int buffer_height; int half_buffer_width; int half_buffer_height; - - RID ssil_final; - RID deinterleaved; - Vector<RID> deinterleaved_slices; - RID pong; - Vector<RID> pong_slices; - RID edges; - Vector<RID> edges_slices; - RID importance_map[2]; - RID depth_texture_view; - - RID last_frame; - Vector<RID> last_frame_slices; - - RID gather_uniform_set; - RID importance_map_uniform_set; - RID projection_uniform_set; }; struct SSILSettings { @@ -103,9 +106,8 @@ public: Size2i full_screen_size; }; - void ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth); - void screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings); - void ssil_free(SSILRenderBuffers &p_ssil_buffers); + void ssil_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings); + void screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, uint32_t p_view, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings); /* SSAO */ void ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to); @@ -116,17 +118,6 @@ public: int buffer_height; int half_buffer_width; int half_buffer_height; - - RID ao_deinterleaved; - Vector<RID> ao_deinterleaved_slices; - RID ao_pong; - Vector<RID> ao_pong_slices; - RID ao_final; - RID importance_map[2]; - RID depth_texture_view; - - RID gather_uniform_set; - RID importance_map_uniform_set; }; struct SSAOSettings { @@ -140,9 +131,8 @@ public: Size2i full_screen_size; }; - void ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth); - void generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings); - void ssao_free(SSAORenderBuffers &p_ssao_buffers); + void ssao_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings); + void generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, uint32_t p_view, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings); /* Screen Space Reflection */ void ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality); @@ -150,18 +140,10 @@ public: struct SSRRenderBuffers { Size2i size; RenderingServer::EnvironmentSSRRoughnessQuality roughness_quality = RenderingServer::ENV_SSR_ROUGHNESS_QUALITY_DISABLED; - - RID normal_scaled; - RID depth_scaled; - RID blur_radius[2]; - RID intermediate; - RID output; - RID output_slices[RendererSceneRender::MAX_RENDER_VIEWS]; }; - void ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, const Size2i &p_screen_size, const uint32_t p_view_count); - void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets); - void ssr_free(SSRRenderBuffers &p_ssr_buffers); + void ssr_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format); + void screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const Projection *p_projections, const Vector3 *p_eye_offsets); /* subsurface scattering */ void sss_set_quality(RS::SubSurfaceScatteringQuality p_quality); @@ -223,7 +205,6 @@ private: SSEffectsDownsamplePushConstant downsample_push_constant; SsEffectsDownsampleShaderRD downsample_shader; RID downsample_shader_version; - RID downsample_uniform_set; bool used_half_size_last_frame = false; bool used_mips_last_frame = false; bool used_full_mips_last_frame = false; @@ -332,7 +313,7 @@ private: RID pipelines[SSIL_MAX]; } ssil; - void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set); + void gather_ssil(RD::ComputeListID p_compute_list, const RID *p_ssil_slices, const RID *p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set); /* SSAO */ @@ -426,7 +407,7 @@ private: RID pipelines[SSAO_MAX]; } ssao; - void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set); + void gather_ssao(RD::ComputeListID p_compute_list, const RID *p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set); /* Screen Space Reflection */ 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 59e1f559c7..6d5e55ee6a 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -30,6 +30,7 @@ #include "render_forward_clustered.h" #include "core/config/project_settings.h" +#include "core/object/worker_thread_pool.h" #include "servers/rendering/renderer_rd/framebuffer_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/storage_rd/light_storage.h" @@ -108,6 +109,10 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::free_data() { // JIC, should already have been cleared if (render_buffers) { render_buffers->clear_context(RB_SCOPE_FORWARD_CLUSTERED); + render_buffers->clear_context(RB_SCOPE_SSDS); + render_buffers->clear_context(RB_SCOPE_SSIL); + render_buffers->clear_context(RB_SCOPE_SSAO); + render_buffers->clear_context(RB_SCOPE_SSR); } if (cluster_builder) { @@ -118,21 +123,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::free_data() { if (!render_sdfgi_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_sdfgi_uniform_set)) { RD::get_singleton()->free(render_sdfgi_uniform_set); } - - if (ss_effects_data.linear_depth.is_valid()) { - RD::get_singleton()->free(ss_effects_data.linear_depth); - ss_effects_data.linear_depth = RID(); - ss_effects_data.linear_depth_slices.clear(); - } - - if (ss_effects_data.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects_data.downsample_uniform_set)) { - RD::get_singleton()->free(ss_effects_data.downsample_uniform_set); - ss_effects_data.downsample_uniform_set = RID(); - } - - RenderForwardClustered::get_singleton()->get_ss_effects()->ssao_free(ss_effects_data.ssao); - RenderForwardClustered::get_singleton()->get_ss_effects()->ssil_free(ss_effects_data.ssil); - RenderForwardClustered::get_singleton()->get_ss_effects()->ssr_free(ss_effects_data.ssr); } void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RenderSceneBuffersRD *p_render_buffers) { @@ -1252,7 +1242,7 @@ void RenderForwardClustered::setup_added_decal(const Transform3D &p_transform, c /* Render scene */ -void RenderForwardClustered::_process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection) { +void RenderForwardClustered::_process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_buffers, const Projection *p_projections) { ERR_FAIL_NULL(ss_effects); ERR_FAIL_COND(p_render_buffers.is_null()); ERR_FAIL_COND(p_environment.is_null()); @@ -1271,11 +1261,14 @@ void RenderForwardClustered::_process_ssao(Ref<RenderSceneBuffersRD> p_render_bu settings.sharpness = environment_get_ssao_sharpness(p_environment); settings.full_screen_size = p_render_buffers->get_internal_size(); - ss_effects->ssao_allocate_buffers(rb_data->ss_effects_data.ssao, settings, rb_data->ss_effects_data.linear_depth); - ss_effects->generate_ssao(rb_data->ss_effects_data.ssao, p_normal_buffer, p_projection, settings); + ss_effects->ssao_allocate_buffers(p_render_buffers, rb_data->ss_effects_data.ssao, settings); + + for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) { + ss_effects->generate_ssao(p_render_buffers, rb_data->ss_effects_data.ssao, v, p_normal_buffers[v], p_projections[v], settings); + } } -void RenderForwardClustered::_process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform) { +void RenderForwardClustered::_process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_buffers, const Projection *p_projections, const Transform3D &p_transform) { ERR_FAIL_NULL(ss_effects); ERR_FAIL_COND(p_render_buffers.is_null()); ERR_FAIL_COND(p_environment.is_null()); @@ -1292,36 +1285,46 @@ void RenderForwardClustered::_process_ssil(Ref<RenderSceneBuffersRD> p_render_bu settings.normal_rejection = environment_get_ssil_normal_rejection(p_environment); settings.full_screen_size = p_render_buffers->get_internal_size(); - Projection correction; - correction.set_depth_correction(true); - Projection projection = correction * p_projection; + ss_effects->ssil_allocate_buffers(p_render_buffers, rb_data->ss_effects_data.ssil, settings); + Transform3D transform = p_transform; transform.set_origin(Vector3(0.0, 0.0, 0.0)); - Projection last_frame_projection = rb_data->ss_effects_data.last_frame_projection * Projection(rb_data->ss_effects_data.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse(); - ss_effects->ssil_allocate_buffers(rb_data->ss_effects_data.ssil, settings, rb_data->ss_effects_data.linear_depth); - ss_effects->screen_space_indirect_lighting(rb_data->ss_effects_data.ssil, p_normal_buffer, p_projection, last_frame_projection, settings); - rb_data->ss_effects_data.last_frame_projection = projection; + for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) { + Projection correction; + correction.set_depth_correction(true); + Projection projection = correction * p_projections[v]; + Projection last_frame_projection = rb_data->ss_effects_data.last_frame_projections[v] * Projection(rb_data->ss_effects_data.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse(); + + ss_effects->screen_space_indirect_lighting(p_render_buffers, rb_data->ss_effects_data.ssil, v, p_normal_buffers[v], p_projections[v], last_frame_projection, settings); + + rb_data->ss_effects_data.last_frame_projections[v] = projection; + } rb_data->ss_effects_data.last_frame_transform = transform; } void RenderForwardClustered::_copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers) { ERR_FAIL_COND(p_render_buffers.is_null()); - Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); - ERR_FAIL_COND(rb_data.is_null()); - - if (rb_data->ss_effects_data.ssil.last_frame.is_valid()) { + if (p_render_buffers->has_texture(RB_SCOPE_SSIL, RB_LAST_FRAME)) { Size2i size = p_render_buffers->get_internal_size(); - RID texture = p_render_buffers->get_internal_texture(); - copy_effects->copy_to_rect(texture, rb_data->ss_effects_data.ssil.last_frame, Rect2i(0, 0, size.x, size.y)); - - int width = size.x; - int height = size.y; - for (int i = 0; i < rb_data->ss_effects_data.ssil.last_frame_slices.size() - 1; i++) { - width = MAX(1, width >> 1); - height = MAX(1, height >> 1); - copy_effects->make_mipmap(rb_data->ss_effects_data.ssil.last_frame_slices[i], rb_data->ss_effects_data.ssil.last_frame_slices[i + 1], Size2i(width, height)); + uint32_t mipmaps = p_render_buffers->get_texture_format(RB_SCOPE_SSIL, RB_LAST_FRAME).mipmaps; + for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) { + RID source = p_render_buffers->get_internal_texture(v); + RID dest = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_LAST_FRAME, v, 0); + copy_effects->copy_to_rect(source, dest, Rect2i(0, 0, size.x, size.y)); + + int width = size.x; + int height = size.y; + for (uint32_t m = 1; m < mipmaps; m++) { + width = MAX(1, width >> 1); + height = MAX(1, height >> 1); + + source = dest; + dest = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_LAST_FRAME, v, m); + + copy_effects->make_mipmap(source, dest, Size2i(width, height)); + } } } } @@ -1421,41 +1424,23 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo } if (rb_data.is_valid() && ss_effects) { - if (p_use_ssao || p_use_ssil) { - Size2i size = rb->get_internal_size(); + // Note, in multiview we're allocating buffers for each eye/view we're rendering. + // This should allow most of the processing to happen in parallel even if we're doing + // drawcalls per eye/view. It will all sync up at the barrier. - bool invalidate_uniform_set = false; - if (rb_data->ss_effects_data.linear_depth.is_null()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16_SFLOAT; - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = (size.x + 1) / 2; - tf.height = (size.y + 1) / 2; - tf.mipmaps = 5; - tf.array_layers = 4; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb_data->ss_effects_data.linear_depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb_data->ss_effects_data.linear_depth, "SS Effects Depth"); - for (uint32_t i = 0; i < tf.mipmaps; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb_data->ss_effects_data.linear_depth, 0, i, 1, RD::TEXTURE_SLICE_2D_ARRAY); - rb_data->ss_effects_data.linear_depth_slices.push_back(slice); - RD::get_singleton()->set_resource_name(slice, "SS Effects Depth Mip " + itos(i) + " "); - } - invalidate_uniform_set = true; + if (p_use_ssao || p_use_ssil) { + // Convert our depth buffer data to linear data in + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + ss_effects->downsample_depth(rb, v, p_render_data->scene_data->view_projection[v]); } - RID depth_texture = rb->get_depth_texture(); - ss_effects->downsample_depth(depth_texture, rb_data->ss_effects_data.linear_depth_slices, invalidate_uniform_set, size, p_render_data->scene_data->cam_projection); - } - - if (p_use_ssao) { - // TODO make these proper stereo - _process_ssao(rb, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->scene_data->cam_projection); - } + if (p_use_ssao) { + _process_ssao(rb, p_render_data->environment, p_normal_roughness_slices, p_render_data->scene_data->view_projection); + } - if (p_use_ssil) { - // TODO make these proper stereo - _process_ssil(rb, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform); + if (p_use_ssil) { + _process_ssil(rb, p_render_data->environment, p_normal_roughness_slices, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform); + } } } @@ -1514,17 +1499,11 @@ void RenderForwardClustered::_process_ssr(Ref<RenderSceneBuffersRD> p_render_buf ERR_FAIL_COND(p_environment.is_null()); ERR_FAIL_COND(!environment_get_ssr_enabled(p_environment)); - Size2i half_size = Size2i(internal_size.x / 2, internal_size.y / 2); - ss_effects->ssr_allocate_buffers(rb_data->ss_effects_data.ssr, _render_buffers_get_color_format(), half_size, view_count); + ss_effects->ssr_allocate_buffers(p_render_buffers, rb_data->ss_effects_data.ssr, _render_buffers_get_color_format()); + ss_effects->screen_space_reflection(p_render_buffers, rb_data->ss_effects_data.ssr, p_normal_slices, p_metallic_slices, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), p_projections, p_eye_offsets); - RID texture_slices[RendererSceneRender::MAX_RENDER_VIEWS]; - RID depth_slices[RendererSceneRender::MAX_RENDER_VIEWS]; - for (uint32_t v = 0; v < view_count; v++) { - texture_slices[v] = p_render_buffers->get_internal_texture(v); - depth_slices[v] = p_render_buffers->get_depth_texture(v); - } - ss_effects->screen_space_reflection(rb_data->ss_effects_data.ssr, texture_slices, p_normal_slices, p_metallic_slices, depth_slices, half_size, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), view_count, p_projections, p_eye_offsets); - copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), rb_data->ss_effects_data.ssr.output, view_count); + RID output = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_OUTPUT); + copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), output, view_count); } void RenderForwardClustered::_process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera) { @@ -2129,14 +2108,16 @@ void RenderForwardClustered::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD RID render_target = p_render_buffers->get_render_target(); - if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb_data->ss_effects_data.ssao.ao_final.is_valid()) { + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSAO && p_render_buffers->has_texture(RB_SCOPE_SSAO, RB_FINAL)) { + RID final = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_FINAL, 0, 0); Size2i rtsize = texture_storage->render_target_get_size(render_target); - copy_effects->copy_to_fb_rect(rb_data->ss_effects_data.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, true); + copy_effects->copy_to_fb_rect(final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, true); } - if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb_data->ss_effects_data.ssil.ssil_final.is_valid()) { + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSIL && p_render_buffers->has_texture(RB_SCOPE_SSIL, RB_FINAL)) { + RID final = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_FINAL, 0, 0); Size2i rtsize = texture_storage->render_target_get_size(render_target); - copy_effects->copy_to_fb_rect(rb_data->ss_effects_data.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false); + copy_effects->copy_to_fb_rect(final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false); } if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) { @@ -3058,7 +3039,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID aot = rb_data.is_valid() ? rb_data->get_ao_texture() : RID(); + RID aot = rb.is_valid() && rb->has_texture(RB_SCOPE_SSAO, RB_FINAL) ? rb->get_texture(RB_SCOPE_SSAO, RB_FINAL) : RID(); RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); @@ -3144,7 +3125,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 20; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID ssil = rb_data.is_valid() ? rb_data->get_ssil_texture() : RID(); + RID ssil = rb.is_valid() && rb->has_texture(RB_SCOPE_SSIL, RB_FINAL) ? rb->get_texture(RB_SCOPE_SSIL, RB_FINAL) : RID(); RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); 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 8eb17ba6f4..e07d2f2258 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -104,16 +104,11 @@ class RenderForwardClustered : public RendererSceneRenderRD { ClusterBuilderRD *cluster_builder = nullptr; struct SSEffectsData { - RID linear_depth; - Vector<RID> linear_depth_slices; - - RID downsample_uniform_set; - - Projection last_frame_projection; + Projection last_frame_projections[RendererSceneRender::MAX_RENDER_VIEWS]; Transform3D last_frame_transform; - RendererRD::SSEffects::SSAORenderBuffers ssao; RendererRD::SSEffects::SSILRenderBuffers ssil; + RendererRD::SSEffects::SSAORenderBuffers ssao; RendererRD::SSEffects::SSRRenderBuffers ssr; } ss_effects_data; @@ -155,9 +150,6 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID get_depth_fb(DepthFrameBufferType p_type = DEPTH_FB); RID get_specular_only_fb(); - RID get_ao_texture() const { return ss_effects_data.ssao.ao_final; } - RID get_ssil_texture() const { return ss_effects_data.ssil.ssil_final; } - virtual void configure(RenderSceneBuffersRD *p_render_buffers) override; virtual void free_data() override; }; @@ -600,8 +592,8 @@ class RenderForwardClustered : public RendererSceneRenderRD { void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS); /* Render Scene */ - void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection); - void _process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform); + void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_buffers, const Projection *p_projections); + void _process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_buffers, const Projection *p_projections, const Transform3D &p_transform); void _copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers); void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer); void _process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 7d9ca070b0..45fe067a6f 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -30,6 +30,7 @@ #include "render_forward_mobile.h" #include "core/config/project_settings.h" +#include "core/object/worker_thread_pool.h" #include "servers/rendering/renderer_rd/storage_rd/light_storage.h" #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" #include "servers/rendering/renderer_rd/storage_rd/particles_storage.h" @@ -593,12 +594,10 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { bool render_shadows = p_render_data->directional_shadows.size() || p_render_data->shadows.size(); + //prepare shadow rendering if (render_shadows) { RENDER_TIMESTAMP("Render Shadows"); - } - //prepare shadow rendering - if (render_shadows) { _render_shadow_begin(); //render directional shadows diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index bd8c11186e..f102bc0650 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -2634,6 +2634,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { // Default CanvasGroup shader. shader_type canvas_item; +render_mode unshaded; uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest; @@ -2661,6 +2662,7 @@ void fragment() { // Default clip children shader. shader_type canvas_item; +render_mode unshaded; uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 885ea18151..efd961fd89 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -280,7 +280,7 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData for (int i = 1; i < mipmaps; i++) { RID source = dest; dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i); - Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i); + Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, i); if (can_use_storage) { copy_effects->make_mipmap(source, dest, msize); @@ -448,7 +448,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende float luminance_multiplier = _render_buffers_get_luminance_multiplier(); for (uint32_t l = 0; l < rb->get_view_count(); l++) { for (int i = 0; i < (max_glow_level + 1); i++) { - Size2i vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i); + Size2i vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, i); if (i == 0) { RID luminance_texture; @@ -502,7 +502,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.glow_levels[i] = environment_get_glow_levels(p_render_data->environment)[i]; } - Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0); + Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0); tonemap.glow_texture_size.x = msize.width; tonemap.glow_texture_size.y = msize.height; tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale; @@ -1110,6 +1110,8 @@ float RendererSceneRenderRD::screen_space_roughness_limiter_get_limit() const { } TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) { + ERR_FAIL_COND_V_MSG(p_image_size.width <= 0, TypedArray<Image>(), "Image width must be greater than 0."); + ERR_FAIL_COND_V_MSG(p_image_size.height <= 0, TypedArray<Image>(), "Image height must be greater than 0."); RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; tf.width = p_image_size.width; // Always 64x64 diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index 533a912a34..c85ece6366 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -33,6 +33,7 @@ #include "core/io/compression.h" #include "core/io/dir_access.h" #include "core/io/file_access.h" +#include "core/object/worker_thread_pool.h" #include "core/version.h" #include "renderer_compositor_rd.h" #include "servers/rendering/rendering_device.h" diff --git a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl index b1ff46dd3b..4f81e36c58 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl @@ -161,17 +161,11 @@ void prepare_depths_and_mips(vec4 p_samples, uvec2 p_output_coord, uvec2 p_gtid) still_alive = p_gtid.x % 16 == depth_array_offset.x && depth_array_offset.y % 16 == depth_array_offset.y; p_output_coord /= 2; - groupMemoryBarrier(); - barrier(); if (still_alive) { + // Use the previous average, not ideal, but still not bad. float sample_00 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 0]; - float sample_01 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 8]; - float sample_10 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 0]; - float sample_11 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 8]; - - float avg = mip_smart_average(vec4(sample_00, sample_01, sample_10, sample_11)); - imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(avg)); + imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(sample_00)); } #endif } @@ -190,6 +184,7 @@ void prepare_depths(vec4 p_samples, uvec2 p_tid) { void main() { #ifdef USE_HALF_BUFFERS +// Half buffers means that we divide depth into two half res buffers (we only capture 1/4 of pixels). #ifdef USE_HALF_SIZE float sample_00 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 0, 4 * gl_GlobalInvocationID.y + 0), 0).x; float sample_11 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 2, 4 * gl_GlobalInvocationID.y + 2), 0).x; @@ -219,11 +214,11 @@ void main() { vec2 uv = (vec2(depth_buffer_coord) + 0.5f) * params.pixel_size; vec4 samples = textureGather(source_depth, uv); -#endif +#endif //USE_HALF_SIZE #ifdef GENERATE_MIPS prepare_depths_and_mips(samples, output_coord, gl_LocalInvocationID.xy); #else prepare_depths(samples, gl_GlobalInvocationID.xy); #endif -#endif +#endif //USE_HALF_BUFFERS } diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index 21fa7fa148..c8ad1f0312 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -1390,7 +1390,11 @@ void fragment_shader(in SceneData scene_data) { #endif // !USE_LIGHTMAP if (bool(implementation_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSAO)) { +#ifdef USE_MULTIVIEW + float ssao = texture(sampler2DArray(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(screen_uv, ViewIndex)).r; +#else float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r; +#endif ao = min(ao, ssao); ao_light_affect = mix(ao_light_affect, max(ao_light_affect, implementation_data.ssao_light_affect), implementation_data.ssao_ao_affect); } @@ -1473,7 +1477,11 @@ void fragment_shader(in SceneData scene_data) { ambient_light *= ao; if (bool(implementation_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSIL)) { +#ifdef USE_MULTIVIEW + vec4 ssil = textureLod(sampler2DArray(ssil_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(screen_uv, ViewIndex), 0.0); +#else vec4 ssil = textureLod(sampler2D(ssil_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv, 0.0); +#endif // USE_MULTIVIEW ambient_light *= 1.0 - ssil.a; ambient_light += ssil.rgb * albedo.rgb; } diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl index 8ff7a784dc..043bba1e4e 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl @@ -275,6 +275,7 @@ layout(r32ui, set = 1, binding = 13) uniform restrict uimage3D geom_facing_grid; layout(set = 1, binding = 10) uniform texture2DArray depth_buffer; layout(set = 1, binding = 11) uniform texture2DArray color_buffer; layout(set = 1, binding = 12) uniform texture2DArray normal_roughness_buffer; +layout(set = 1, binding = 13) uniform texture2DArray ao_buffer; layout(set = 1, binding = 14) uniform texture2DArray ambient_buffer; layout(set = 1, binding = 15) uniform texture2DArray reflection_buffer; #define multiviewSampler sampler2DArray @@ -282,11 +283,11 @@ layout(set = 1, binding = 15) uniform texture2DArray reflection_buffer; layout(set = 1, binding = 10) uniform texture2D depth_buffer; layout(set = 1, binding = 11) uniform texture2D color_buffer; layout(set = 1, binding = 12) uniform texture2D normal_roughness_buffer; +layout(set = 1, binding = 13) uniform texture2D ao_buffer; layout(set = 1, binding = 14) uniform texture2D ambient_buffer; layout(set = 1, binding = 15) uniform texture2D reflection_buffer; #define multiviewSampler sampler2D #endif -layout(set = 1, binding = 13) uniform texture2D ao_buffer; layout(set = 1, binding = 16) uniform texture2DArray sdfgi_lightprobe_texture; layout(set = 1, binding = 17) uniform texture3D sdfgi_occlusion_cascades; @@ -312,7 +313,11 @@ voxel_gi_instances; layout(set = 1, binding = 19) uniform texture3D volumetric_fog_texture; +#ifdef USE_MULTIVIEW +layout(set = 1, binding = 20) uniform texture2DArray ssil_buffer; +#else layout(set = 1, binding = 20) uniform texture2D ssil_buffer; +#endif // USE_MULTIVIEW #endif diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index 968f804593..e65d842a67 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -389,6 +389,13 @@ uint64_t LightStorage::light_get_version(RID p_light) const { return light->version; } +uint32_t LightStorage::light_get_cull_mask(RID p_light) const { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, 0); + + return light->cull_mask; +} + AABB LightStorage::light_get_aabb(RID p_light) const { const Light *light = light_owner.get_or_null(p_light); ERR_FAIL_COND_V(!light, AABB()); diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index 68f439ddef..c36d1ef503 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -517,13 +517,6 @@ public: return light->color; } - _FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) { - const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, 0); - - return light->cull_mask; - } - _FORCE_INLINE_ bool light_is_distance_fade_enabled(RID p_light) { const Light *light = light_owner.get_or_null(p_light); return light->distance_fade; @@ -575,6 +568,7 @@ public: virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override; virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override; virtual uint64_t light_get_version(RID p_light) const override; + virtual uint32_t light_get_cull_mask(RID p_light) const override; Dependency *light_get_dependency(RID p_light) const; diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index d631a89dd2..6f67d628a9 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -2803,6 +2803,7 @@ void MaterialStorage::material_set_render_priority(RID p_material, int priority) if (material->data) { material->data->set_render_priority(priority); } + material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); } bool MaterialStorage::material_is_animated(RID p_material) { diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index f65676185c..96618c3352 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -586,6 +586,8 @@ void MeshStorage::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); ERR_FAIL_COND(!mesh); mesh->custom_aabb = p_aabb; + + mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } AABB MeshStorage::mesh_get_custom_aabb(RID p_mesh) const { @@ -1803,8 +1805,12 @@ void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible } if (multimesh->data_cache.size()) { - //there is a data cache.. + // There is a data cache, but we may need to update some sections. _multimesh_mark_all_dirty(multimesh, false, true); + int start = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; + for (int i = start; i < p_visible; i++) { + _multimesh_mark_dirty(multimesh, i, true); + } } multimesh->visible_instances = p_visible; diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp index 255719183f..f5d6404f01 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp @@ -50,25 +50,19 @@ void RenderSceneBuffersRD::_bind_methods() { // ClassDB::bind_method(D_METHOD("create_texture_view", "context", "name", "view_name", "view"), &RenderSceneBuffersRD::has_texture); ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture); // ClassDB::bind_method(D_METHOD("get_texture_format", "context", "name"), &RenderSceneBuffersRD::get_texture_format); - ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice); - ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size); + ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap", "layers", "mipmaps"), &RenderSceneBuffersRD::get_texture_slice); + ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size); ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context); } void RenderSceneBuffersRD::update_sizes(NamedTexture &p_named_texture) { ERR_FAIL_COND(p_named_texture.texture.is_null()); - uint32_t size = p_named_texture.format.array_layers * p_named_texture.format.mipmaps; - p_named_texture.sizes.resize(size); + p_named_texture.sizes.resize(p_named_texture.format.mipmaps); Size2i mipmap_size = Size2i(p_named_texture.format.width, p_named_texture.format.height); - for (uint32_t mipmap = 0; mipmap < p_named_texture.format.mipmaps; mipmap++) { - for (uint32_t layer = 0; layer < p_named_texture.format.array_layers; layer++) { - uint32_t index = layer * p_named_texture.format.mipmaps + mipmap; - - p_named_texture.sizes.ptrw()[index] = mipmap_size; - } + p_named_texture.sizes.ptrw()[mipmap] = mipmap_size; mipmap_size.width = MAX(1, mipmap_size.width >> 1); mipmap_size.height = MAX(1, mipmap_size.height >> 1); @@ -324,7 +318,7 @@ const RD::TextureFormat RenderSceneBuffersRD::get_texture_format(const StringNam return named_textures[key].format; } -RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) { +RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers, const uint32_t p_mipmaps) { NTKey key(p_context, p_texture_name); // check if this is a known texture @@ -334,36 +328,41 @@ RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const S // check if we're in bounds ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, RID()); + ERR_FAIL_COND_V(p_layers == 0, RID()); + ERR_FAIL_COND_V(p_layer + p_layers > named_texture.format.array_layers, RID()); ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, RID()); + ERR_FAIL_COND_V(p_mipmaps == 0, RID()); + ERR_FAIL_COND_V(p_mipmap + p_mipmaps > named_texture.format.mipmaps, RID()); - // if we don't have multiple layers or mipmaps, we can just return our texture as is - if (named_texture.format.array_layers == 1 && named_texture.format.mipmaps == 1) { + // asking the whole thing? just return the original + if (p_layer == 0 && p_mipmap == 0 && named_texture.format.array_layers == p_layers && named_texture.format.mipmaps == p_mipmaps) { return named_texture.texture; } - // get our index and make sure we have enough entries in our slices vector - uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap; - while (named_texture.slices.size() <= int(index)) { - named_texture.slices.push_back(RID()); + // see if we have this + NTSliceKey slice_key(p_layer, p_layers, p_mipmap, p_mipmaps); + if (named_texture.slices.has(slice_key)) { + return named_texture.slices[slice_key]; } - // create our slice if we don't have it already - if (named_texture.slices[index].is_null()) { - named_texture.slices.ptrw()[index] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap); + // create our slice + RID &slice = named_texture.slices[slice_key]; + slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap, p_mipmaps, p_layers > 1 ? RD::TEXTURE_SLICE_2D_ARRAY : RD::TEXTURE_SLICE_2D, p_layers); - Array arr; - arr.push_back(p_context); - arr.push_back(p_texture_name); - arr.push_back(itos(p_layer)); - arr.push_back(itos(p_mipmap)); - RD::get_singleton()->set_resource_name(named_texture.slices[index], String("RenderBuffer {0}/{1} slice {2}/{3}").format(arr)); - } + Array arr; + arr.push_back(p_context); + arr.push_back(p_texture_name); + arr.push_back(itos(p_layer)); + arr.push_back(itos(p_layers)); + arr.push_back(itos(p_mipmap)); + arr.push_back(itos(p_mipmaps)); + RD::get_singleton()->set_resource_name(slice, String("RenderBuffer {0}/{1}, layer {2}/{3}, mipmap {4}/{5}").format(arr)); // and return our slice - return named_texture.slices[index]; + return slice; } -Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) { +Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_mipmap) { NTKey key(p_context, p_texture_name); // check if this is a known texture @@ -372,14 +371,10 @@ Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, ERR_FAIL_COND_V(named_texture.texture.is_null(), Size2i()); // check if we're in bounds - ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, Size2i()); ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, Size2i()); - // get our index - uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap; - - // and return our size - return named_texture.sizes[index]; + // return our size + return named_texture.sizes[p_mipmap]; } void RenderSceneBuffersRD::clear_context(const StringName &p_context) { diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h index 50fb06c0d9..9a299a3415 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h @@ -93,7 +93,6 @@ private: } static uint32_t hash(const NTKey &p_val) { - // FIXME, properly hash two stringnames together uint32_t h = p_val.context.hash(); h = hash_murmur3_one_32(p_val.buffer_name.hash(), h); return hash_fmix32(h); @@ -106,6 +105,33 @@ private: } }; + struct NTSliceKey { + uint32_t layer; + uint32_t layers; + uint32_t mipmap; + uint32_t mipmaps; + + bool operator==(const NTSliceKey &p_val) const { + return (layer == p_val.layer) && (layers == p_val.layers) && (mipmap == p_val.mipmap) && (mipmaps == p_val.mipmaps); + } + + static uint32_t hash(const NTSliceKey &p_val) { + uint32_t h = hash_murmur3_one_32(p_val.layer); + h = hash_murmur3_one_32(p_val.layers, h); + h = hash_murmur3_one_32(p_val.mipmap, h); + h = hash_murmur3_one_32(p_val.mipmaps, h); + return hash_fmix32(h); + } + + NTSliceKey() {} + NTSliceKey(uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps) { + layer = p_layer; + layers = p_layers; + mipmap = p_mipmap; + mipmaps = p_mipmaps; + } + }; + struct NamedTexture { // Cache the data used to create our texture RD::TextureFormat format; @@ -113,7 +139,7 @@ private: // Our texture objects, slices are lazy (i.e. only created when requested). RID texture; - Vector<RID> slices; + mutable HashMap<NTSliceKey, RID, NTSliceKey> slices; Vector<Size2i> sizes; }; @@ -154,8 +180,8 @@ public: RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view = RD::TextureView()); RID get_texture(const StringName &p_context, const StringName &p_texture_name) const; const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const; - RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap); - Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap); + RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1); + Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_mipmap); void clear_context(const StringName &p_context); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 5d845ce510..0ee9b28826 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -1906,7 +1906,7 @@ void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) { Decal *decal = decal_owner.get_or_null(p_decal); ERR_FAIL_COND(!decal); decal->cull_mask = p_layers; - decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); + decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_DECAL); } void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) { @@ -1952,6 +1952,13 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const { return AABB(-decal->size / 2, decal->size); } +uint32_t TextureStorage::decal_get_cull_mask(RID p_decal) const { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND_V(!decal, 0); + + return decal->cull_mask; +} + Dependency *TextureStorage::decal_get_dependency(RID p_decal) { Decal *decal = decal_owner.get_or_null(p_decal); ERR_FAIL_COND_V(!decal, nullptr); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index aeab3bf3cb..c16f5274ad 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -638,6 +638,7 @@ public: } virtual AABB decal_get_aabb(RID p_decal) const override; + virtual uint32_t decal_get_cull_mask(RID p_decal) const override; Dependency *decal_get_dependency(RID p_decal); /* DECAL INSTANCE API */ diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index d696955800..813c1fa4ff 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -31,6 +31,7 @@ #include "renderer_scene_cull.h" #include "core/config/project_settings.h" +#include "core/object/worker_thread_pool.h" #include "core/os/os.h" #include "rendering_server_default.h" #include "rendering_server_globals.h" @@ -1787,6 +1788,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { pair.pair_allocator = &pair_allocator; pair.pair_pass = pair_pass; pair.pair_mask = 0; + pair.cull_mask = 0xFFFFFFFF; if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { pair.pair_mask |= 1 << RS::INSTANCE_LIGHT; @@ -1807,12 +1809,14 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { pair.pair_mask |= (1 << RS::INSTANCE_VOXEL_GI); pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES]; } + pair.cull_mask = RSG::light_storage->light_get_cull_mask(p_instance->base); } else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE)) { pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK; pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; } else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (p_instance->base_type == RS::INSTANCE_DECAL)) { pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK; pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; + pair.cull_mask = RSG::texture_storage->decal_get_cull_mask(p_instance->base); } else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) { pair.pair_mask = (1 << RS::INSTANCE_PARTICLES); pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 2ec75b03ef..b3874ee7ae 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -485,6 +485,7 @@ public: singleton->_instance_queue_update(instance, true, false); } break; + case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: case Dependency::DEPENDENCY_CHANGED_MATERIAL: { singleton->_instance_queue_update(instance, false, true); } break; @@ -496,9 +497,6 @@ public: case Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE: { singleton->_instance_queue_update(instance, true, true); } break; - case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { - //ignored - } break; case Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR: { //requires repairing if (instance->indexer_id.is_valid()) { @@ -735,11 +733,12 @@ public: DynamicBVH *bvh2 = nullptr; //some may need to cull in two uint32_t pair_mask; uint64_t pair_pass; + uint32_t cull_mask = 0xFFFFFFFF; // Needed for decals and lights in the mobile and compatibility renderers. _FORCE_INLINE_ bool operator()(void *p_data) { Instance *p_instance = (Instance *)p_data; - if (instance != p_instance && instance->transformed_aabb.intersects(p_instance->transformed_aabb) && (pair_mask & (1 << p_instance->base_type))) { + if (instance != p_instance && instance->transformed_aabb.intersects(p_instance->transformed_aabb) && (pair_mask & (1 << p_instance->base_type)) && (cull_mask & p_instance->layer_mask)) { //test is more coarse in indexer p_instance->pair_check = pair_pass; InstancePair *pair = pair_allocator->alloc(); diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index aecd0593bc..0e2a3c682d 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -31,6 +31,7 @@ #include "renderer_viewport.h" #include "core/config/project_settings.h" +#include "core/object/worker_thread_pool.h" #include "renderer_canvas_cull.h" #include "renderer_scene_cull.h" #include "rendering_server_globals.h" @@ -229,6 +230,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { bool scenario_draw_canvas_bg = false; //draw canvas, or some layer of it, as BG for 3D instead of in front int scenario_canvas_max_layer = 0; + bool force_clear_render_target = false; for (int i = 0; i < RS::VIEWPORT_RENDER_INFO_TYPE_MAX; i++) { for (int j = 0; j < RS::VIEWPORT_RENDER_INFO_MAX; j++) { @@ -236,11 +238,16 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { } } - if (!p_viewport->disable_2d && !viewport_is_environment_disabled(p_viewport) && RSG::scene->is_scenario(p_viewport->scenario)) { + if (RSG::scene->is_scenario(p_viewport->scenario)) { RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario); if (RSG::scene->is_environment(environment)) { - scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS; - scenario_canvas_max_layer = RSG::scene->environment_get_canvas_max_layer(environment); + if (!p_viewport->disable_2d && !viewport_is_environment_disabled(p_viewport)) { + scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS; + scenario_canvas_max_layer = RSG::scene->environment_get_canvas_max_layer(environment); + } else if (RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS) { + // The scene renderer will still copy over the last frame, so we need to clear the render target. + force_clear_render_target = true; + } } } @@ -263,6 +270,9 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { } if (!scenario_draw_canvas_bg && can_draw_3d) { + if (force_clear_render_target) { + RSG::texture_storage->render_target_do_clear_request(p_viewport->render_target); + } _draw_3d(p_viewport); } @@ -844,7 +854,7 @@ void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_sca } void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) { - ERR_FAIL_COND(p_width < 0 && p_height < 0); + ERR_FAIL_COND(p_width < 0 || p_height < 0); Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 28f872761a..286d1b683f 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -746,7 +746,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("buffer_update", "buffer", "offset", "size_bytes", "data", "post_barrier"), &RenderingDevice::_buffer_update, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::buffer_clear, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); - ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer"), &RenderingDevice::buffer_get_data); + ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer", "offset_bytes", "size_bytes"), &RenderingDevice::buffer_get_data, DEFVAL(0), DEFVAL(0)); ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags", "for_render_pass", "specialization_constants"), &RenderingDevice::_render_pipeline_create, DEFVAL(0), DEFVAL(0), DEFVAL(TypedArray<RDPipelineSpecializationConstant>())); ClassDB::bind_method(D_METHOD("render_pipeline_is_valid", "render_pipeline"), &RenderingDevice::render_pipeline_is_valid); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 08ca25b64b..447627b08e 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -530,7 +530,7 @@ public: TEXTURE_SLICE_2D_ARRAY, }; - virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D) = 0; + virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D, uint32_t p_layers = 0) = 0; virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0; virtual Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer) = 0; // CPU textures will return immediately, while GPU textures will most likely force a flush @@ -828,7 +828,7 @@ public: virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0; virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0; - virtual Vector<uint8_t> buffer_get_data(RID p_buffer) = 0; //this causes stall, only use to retrieve large buffers for saving + virtual Vector<uint8_t> buffer_get_data(RID p_buffer, uint32_t p_offset = 0, uint32_t p_size = 0) = 0; // This causes stall, only use to retrieve large buffers for saving. /******************************************/ /**** PIPELINE SPECIALIZATION CONSTANT ****/ diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 4f52a63b2f..a3bdf7d146 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -31,6 +31,7 @@ #ifndef RENDERING_SERVER_DEFAULT_H #define RENDERING_SERVER_DEFAULT_H +#include "core/os/thread.h" #include "core/templates/command_queue_mt.h" #include "core/templates/hash_map.h" #include "renderer_canvas_cull.h" diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 2710724066..8737d3b217 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -1151,6 +1151,9 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene bool is_texture_func = false; bool is_screen_texture = false; + bool texture_func_no_uv = false; + bool texture_func_returns_data = false; + if (onode->op == SL::OP_STRUCT) { code += _mkid(vnode->name); } else if (onode->op == SL::OP_CONSTRUCT) { @@ -1164,6 +1167,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (is_internal_func) { code += vnode->name; is_texture_func = texture_functions.has(vnode->name); + texture_func_no_uv = (vnode->name == "textureSize" || vnode->name == "textureQueryLevels"); + texture_func_returns_data = texture_func_no_uv || vnode->name == "textureQueryLod"; } else if (p_default_actions.renames.has(vnode->name)) { code += p_default_actions.renames[vnode->name]; } else { @@ -1313,7 +1318,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } else { code += node_code; } - } else if (multiview_uv_needed && i == 2) { + } else if (multiview_uv_needed && !texture_func_no_uv && i == 2) { // UV coordinate after using color, depth or normal roughness texture. node_code = "multiview_uv(" + node_code + ".xy)"; @@ -1323,7 +1328,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } } code += ")"; - if (is_screen_texture && actions.apply_luminance_multiplier) { + if (is_screen_texture && !texture_func_returns_data && actions.apply_luminance_multiplier) { code = "(" + code + " * vec4(vec3(sc_luminance_multiplier), 1.0))"; } } break; diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 2dc1c70064..940363a7e8 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -2901,10 +2901,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { // Modern functions. // fma - { "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, - { "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, - { "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, - { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, + { "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, true }, + { "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, true }, + { "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, true }, + { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, true }, // Packing/Unpacking functions. @@ -6553,7 +6553,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons OperatorNode *op = alloc_node<OperatorNode>(); op->op = expression[i].op; if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_function_info)) { - _set_error(RTR("Can't use increment/decrement operator in a constant expression.")); + _set_error(RTR("Invalid use of increment/decrement operator in a constant expression.")); return nullptr; } op->arguments.push_back(expression[i + 1].node); @@ -8421,7 +8421,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f _set_error(vformat(RTR("The '%s' data type is not supported for uniforms."), "struct")); return ERR_PARSE_ERROR; } else { - _set_error(vformat(RTR("The '%s' data type not allowed here."), "struct")); + _set_error(vformat(RTR("The '%s' data type is not allowed here."), "struct")); return ERR_PARSE_ERROR; } } @@ -8780,7 +8780,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f --texture_uniforms; --texture_binding; if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { - _set_error(RTR("'hint_normal_roughness_texture is not supported in gl_compatibility shaders.")); + _set_error(RTR("'hint_normal_roughness_texture' is not supported in gl_compatibility shaders.")); return ERR_PARSE_ERROR; } } break; diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h index 2b7d2c274e..f198af66f0 100644 --- a/servers/rendering/shader_preprocessor.h +++ b/servers/rendering/shader_preprocessor.h @@ -182,7 +182,7 @@ private: } void _set_unexpected_token_error(const String &p_what, int p_line) { - set_error(vformat(RTR("Unexpected token '%s'."), p_what), p_line); + set_error(vformat(RTR("Unexpected token: '%s'."), p_what), p_line); } void process_directive(Tokenizer *p_tokenizer); diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h index 9f3f5dd8e4..5bd4297179 100644 --- a/servers/rendering/storage/light_storage.h +++ b/servers/rendering/storage/light_storage.h @@ -84,6 +84,7 @@ public: virtual RS::LightBakeMode light_get_bake_mode(RID p_light) = 0; virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0; virtual uint64_t light_get_version(RID p_light) const = 0; + virtual uint32_t light_get_cull_mask(RID p_light) const = 0; /* LIGHT INSTANCE API */ diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h index 3a9034ad0d..227d44aa27 100644 --- a/servers/rendering/storage/texture_storage.h +++ b/servers/rendering/storage/texture_storage.h @@ -118,6 +118,7 @@ public: virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0; virtual AABB decal_get_aabb(RID p_decal) const = 0; + virtual uint32_t decal_get_cull_mask(RID p_decal) const = 0; virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 1c19b9dcd0..3d0443b494 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -31,6 +31,7 @@ #include "rendering_server.h" #include "core/config/project_settings.h" +#include "core/object/worker_thread_pool.h" #include "core/variant/typed_array.h" #include "servers/rendering/rendering_server_globals.h" #include "servers/rendering/shader_language.h" @@ -2675,6 +2676,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_filter", "light", "filter"), &RenderingServer::canvas_light_set_shadow_filter); ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_color", "light", "color"), &RenderingServer::canvas_light_set_shadow_color); ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_smooth", "light", "smooth"), &RenderingServer::canvas_light_set_shadow_smooth); + ClassDB::bind_method(D_METHOD("canvas_light_set_blend_mode", "light", "mode"), &RenderingServer::canvas_light_set_blend_mode); BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_POINT); BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_DIRECTIONAL); @@ -2854,8 +2856,8 @@ RenderingServer::RenderingServer() { } void RenderingServer::init() { - GLOBAL_DEF_RST("rendering/textures/vram_compression/import_s3tc_bptc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_S3TC_BPTC); - GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc2_astc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_ETC2_ASTC); + GLOBAL_DEF_RST_NOVAL_BASIC("rendering/textures/vram_compression/import_s3tc_bptc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_S3TC_BPTC); + GLOBAL_DEF_RST_NOVAL_BASIC("rendering/textures/vram_compression/import_etc2_astc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_ETC2_ASTC); GLOBAL_DEF("rendering/textures/lossless_compression/force_png", false); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 1f9bff7c3f..b53b7d2ff9 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -35,7 +35,6 @@ #include "core/math/geometry_3d.h" #include "core/math/transform_2d.h" #include "core/object/class_db.h" -#include "core/object/worker_thread_pool.h" #include "core/templates/rid.h" #include "core/variant/typed_array.h" #include "core/variant/variant.h" diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp index 9968a47b0c..7f3d8668a4 100644 --- a/servers/xr/xr_interface.cpp +++ b/servers/xr/xr_interface.cpp @@ -75,6 +75,10 @@ void XRInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("get_transform_for_view", "view", "cam_transform"), &XRInterface::get_transform_for_view); ClassDB::bind_method(D_METHOD("get_projection_for_view", "view", "aspect", "near", "far"), &XRInterface::get_projection_for_view); + /** environment blend mode. */ + ClassDB::bind_method(D_METHOD("get_supported_environment_blend_modes"), &XRInterface::get_supported_environment_blend_modes); + ClassDB::bind_method(D_METHOD("set_environment_blend_mode", "mode"), &XRInterface::set_environment_blend_mode); + ADD_GROUP("AR", "ar_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ar_is_anchor_detection_enabled"), "set_anchor_detection_is_enabled", "get_anchor_detection_is_enabled"); @@ -97,6 +101,10 @@ void XRInterface::_bind_methods() { BIND_ENUM_CONSTANT(XR_PLAY_AREA_SITTING); BIND_ENUM_CONSTANT(XR_PLAY_AREA_ROOMSCALE); BIND_ENUM_CONSTANT(XR_PLAY_AREA_STAGE); + + BIND_ENUM_CONSTANT(XR_ENV_BLEND_MODE_OPAQUE); + BIND_ENUM_CONSTANT(XR_ENV_BLEND_MODE_ADDITIVE); + BIND_ENUM_CONSTANT(XR_ENV_BLEND_MODE_ALPHA_BLEND); }; bool XRInterface::is_primary() { @@ -273,3 +281,9 @@ XRInterface::TrackingStatus XRInterface::get_tracking_status() const { void XRInterface::trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec) { } + +Array XRInterface::get_supported_environment_blend_modes() { + Array default_blend_modes; + default_blend_modes.push_back(XR_ENV_BLEND_MODE_OPAQUE); + return default_blend_modes; +} diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h index 6f70f75772..c32455f466 100644 --- a/servers/xr/xr_interface.h +++ b/servers/xr/xr_interface.h @@ -78,6 +78,12 @@ public: XR_PLAY_AREA_STAGE, /* Same as roomscale but origin point is fixed to the center of the physical space, XRServer.center_on_hmd disabled */ }; + enum EnvironmentBlendMode { + XR_ENV_BLEND_MODE_OPAQUE, /* You cannot see the real world, VR like */ + XR_ENV_BLEND_MODE_ADDITIVE, /* You can see the real world, AR like */ + XR_ENV_BLEND_MODE_ALPHA_BLEND, /* Real world is passed through where alpha channel is 0.0 and gradually blends to opaque for value 1.0. */ + }; + protected: _THREAD_SAFE_CLASS_ @@ -138,6 +144,10 @@ public: virtual bool start_passthrough() { return false; } virtual void stop_passthrough() {} + /** environment blend mode. */ + virtual Array get_supported_environment_blend_modes(); + virtual bool set_environment_blend_mode(EnvironmentBlendMode mode) { return false; } + XRInterface(); ~XRInterface(); @@ -151,5 +161,6 @@ private: VARIANT_ENUM_CAST(XRInterface::Capabilities); VARIANT_ENUM_CAST(XRInterface::TrackingStatus); VARIANT_ENUM_CAST(XRInterface::PlayAreaMode); +VARIANT_ENUM_CAST(XRInterface::EnvironmentBlendMode); #endif // XR_INTERFACE_H |