diff options
Diffstat (limited to 'servers')
65 files changed, 1242 insertions, 511 deletions
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index b5333d91c6..dc54e01ec8 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -442,7 +442,7 @@ void AudioStreamRandomizer::add_stream(int p_index, Ref<AudioStream> p_stream, f ERR_FAIL_COND(p_index > audio_stream_pool.size()); PoolEntry entry{ p_stream, p_weight }; audio_stream_pool.insert(p_index, entry); - emit_signal(SNAME("changed")); + emit_signal(CoreStringName(changed)); notify_property_list_changed(); } @@ -459,21 +459,21 @@ void AudioStreamRandomizer::move_stream(int p_index_from, int p_index_to) { p_index_from++; } audio_stream_pool.remove_at(p_index_from); - emit_signal(SNAME("changed")); + emit_signal(CoreStringName(changed)); notify_property_list_changed(); } void AudioStreamRandomizer::remove_stream(int p_index) { ERR_FAIL_INDEX(p_index, audio_stream_pool.size()); audio_stream_pool.remove_at(p_index); - emit_signal(SNAME("changed")); + emit_signal(CoreStringName(changed)); notify_property_list_changed(); } void AudioStreamRandomizer::set_stream(int p_index, Ref<AudioStream> p_stream) { ERR_FAIL_INDEX(p_index, audio_stream_pool.size()); audio_stream_pool.write[p_index].stream = p_stream; - emit_signal(SNAME("changed")); + emit_signal(CoreStringName(changed)); } Ref<AudioStream> AudioStreamRandomizer::get_stream(int p_index) const { @@ -484,7 +484,7 @@ Ref<AudioStream> AudioStreamRandomizer::get_stream(int p_index) const { void AudioStreamRandomizer::set_stream_probability_weight(int p_index, float p_weight) { ERR_FAIL_INDEX(p_index, audio_stream_pool.size()); audio_stream_pool.write[p_index].weight = p_weight; - emit_signal(SNAME("changed")); + emit_signal(CoreStringName(changed)); } float AudioStreamRandomizer::get_stream_probability_weight(int p_index) const { @@ -618,7 +618,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_sequential() { if (entry.stream.is_null()) { continue; } - if (local_pool.find(entry.stream) != -1) { + if (local_pool.has(entry.stream)) { WARN_PRINT("Duplicate stream in sequential playback pool"); continue; } @@ -711,6 +711,7 @@ void AudioStreamRandomizer::_bind_methods() { PoolEntry defaults; base_property_helper.set_prefix("stream_"); + base_property_helper.set_array_length_getter(&AudioStreamRandomizer::get_streams_count); base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), defaults.stream, &AudioStreamRandomizer::set_stream, &AudioStreamRandomizer::get_stream); base_property_helper.register_property(PropertyInfo(Variant::FLOAT, "weight", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), defaults.weight, &AudioStreamRandomizer::set_stream_probability_weight, &AudioStreamRandomizer::get_stream_probability_weight); } diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 820e0bbeb6..d37836ed96 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -762,7 +762,7 @@ void AudioServer::set_bus_count(int p_count) { buses[i]->bypass = false; buses[i]->volume_db = 0; if (i > 0) { - buses[i]->send = SceneStringNames::get_singleton()->Master; + buses[i]->send = SceneStringName(Master); } bus_map[attempt] = buses[i]; @@ -1600,7 +1600,7 @@ void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) { for (int i = 0; i < p_bus_layout->buses.size(); i++) { Bus *bus = memnew(Bus); if (i == 0) { - bus->name = SceneStringNames::get_singleton()->Master; + bus->name = SceneStringName(Master); } else { bus->name = p_bus_layout->buses[i].name; bus->send = p_bus_layout->buses[i].send; @@ -1923,5 +1923,5 @@ void AudioBusLayout::_get_property_list(List<PropertyInfo> *p_list) const { AudioBusLayout::AudioBusLayout() { buses.resize(1); - buses.write[0].name = SceneStringNames::get_singleton()->Master; + buses.write[0].name = SceneStringName(Master); } diff --git a/servers/debugger/servers_debugger.cpp b/servers/debugger/servers_debugger.cpp index 06be73acc5..eded0ecfe5 100644 --- a/servers/debugger/servers_debugger.cpp +++ b/servers/debugger/servers_debugger.cpp @@ -97,12 +97,10 @@ Array ServersDebugger::ServersProfilerFrame::serialize() { arr.push_back(script_time); arr.push_back(servers.size()); - for (int i = 0; i < servers.size(); i++) { - ServerInfo &s = servers[i]; + for (const ServerInfo &s : servers) { arr.push_back(s.name); arr.push_back(s.functions.size() * 2); - for (int j = 0; j < s.functions.size(); j++) { - ServerFunctionInfo &f = s.functions[j]; + for (const ServerFunctionInfo &f : s.functions) { arr.push_back(f.name); arr.push_back(f.time); } diff --git a/servers/display_server.cpp b/servers/display_server.cpp index fcbedbc1f8..2150a3038e 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -996,6 +996,8 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("tablet_get_current_driver"), &DisplayServer::tablet_get_current_driver); ClassDB::bind_method(D_METHOD("tablet_set_current_driver", "name"), &DisplayServer::tablet_set_current_driver); + ClassDB::bind_method(D_METHOD("is_window_transparency_available"), &DisplayServer::is_window_transparency_available); + #ifndef DISABLE_DEPRECATED BIND_ENUM_CONSTANT(FEATURE_GLOBAL_MENU); #endif @@ -1183,9 +1185,9 @@ Vector<String> DisplayServer::get_create_function_rendering_drivers(int p_index) return server_create_functions[p_index].get_rendering_drivers_function(); } -DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) { +DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error) { ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr); - return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, r_error); + return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, p_context, r_error); } void DisplayServer::_input_set_mouse_mode(Input::MouseMode p_mode) { diff --git a/servers/display_server.h b/servers/display_server.h index 30f6ee5ccf..5224d59c04 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -82,7 +82,13 @@ public: OPENGL_CONTEXT, }; - typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Point2i *, const Size2i &, int p_screen, Error &r_error); + enum Context { + CONTEXT_EDITOR, + CONTEXT_PROJECTMAN, + CONTEXT_ENGINE, + }; + + typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Point2i *, const Size2i &, int p_screen, Context, Error &r_error); typedef Vector<String> (*GetRenderingDriversFunction)(); private: @@ -572,19 +578,15 @@ public: virtual Rect2 status_indicator_get_rect(IndicatorID p_id) const; virtual void delete_status_indicator(IndicatorID p_id); - enum Context { - CONTEXT_EDITOR, - CONTEXT_PROJECTMAN, - CONTEXT_ENGINE, - }; - virtual void set_context(Context p_context); + virtual bool is_window_transparency_available() const { return false; } + static void register_create_function(const char *p_name, CreateFunction p_function, GetRenderingDriversFunction p_get_drivers); static int get_create_function_count(); static const char *get_create_function_name(int p_index); static Vector<String> get_create_function_rendering_drivers(int p_index); - static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error); + static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error); DisplayServer(); ~DisplayServer(); diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h index 7a44645b1e..51755ddfbd 100644 --- a/servers/display_server_headless.h +++ b/servers/display_server_headless.h @@ -45,7 +45,7 @@ private: return drivers; } - static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) { + static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error) { r_error = OK; RasterizerDummy::make_current(); return memnew(DisplayServerHeadless()); @@ -57,6 +57,9 @@ public: bool has_feature(Feature p_feature) const override { return false; } String get_name() const override { return "headless"; } + // Stub implementations to prevent warnings from being printed for methods + // that don't affect the project's behavior in headless mode. + int get_screen_count() const override { return 0; } int get_primary_screen() const override { return 0; }; Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Point2i(); } @@ -66,6 +69,8 @@ public: float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return 1; } float screen_get_max_scale() const override { return 1; } float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return SCREEN_REFRESH_RATE_FALLBACK; } + void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW) override {} + void screen_set_keep_on(bool p_enable) override {} Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); } @@ -130,10 +135,47 @@ public: void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override {} void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override {} + int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override { return 0; } + void process_events() override {} + void set_native_icon(const String &p_filename) override {} void set_icon(const Ref<Image> &p_icon) override {} + void help_set_search_callbacks(const Callable &p_search_callback = Callable(), const Callable &p_action_callback = Callable()) override {} + + bool tts_is_speaking() const override { return false; } + bool tts_is_paused() const override { return false; } + TypedArray<Dictionary> tts_get_voices() const override { return TypedArray<Dictionary>(); } + void tts_speak(const String &p_text, const String &p_voice, int p_volume = 50, float p_pitch = 1.0f, float p_rate = 1.0f, int p_utterance_id = 0, bool p_interrupt = false) override {} + void tts_pause() override {} + void tts_resume() override {} + void tts_stop() override {} + + void mouse_set_mode(MouseMode p_mode) override {} + void clipboard_set(const String &p_text) override {} + void clipboard_set_primary(const String &p_text) override {} + + void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override {} + void virtual_keyboard_hide() override {} + + void cursor_set_shape(CursorShape p_shape) override {} + void cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override {} + + Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override { return ERR_UNAVAILABLE; } + Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override { return ERR_UNAVAILABLE; } + Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override { return ERR_UNAVAILABLE; } + Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override { return ERR_UNAVAILABLE; } + + void release_rendering_thread() override {} + void swap_buffers() override {} + + IndicatorID create_status_indicator(const Ref<Texture2D> &p_icon, const String &p_tooltip, const Callable &p_callback) override { return INVALID_INDICATOR_ID; } + void status_indicator_set_icon(IndicatorID p_id, const Ref<Texture2D> &p_icon) override {} + void status_indicator_set_tooltip(IndicatorID p_id, const String &p_tooltip) override {} + void status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) override {} + void delete_status_indicator(IndicatorID p_id) override {} + DisplayServerHeadless() { native_menu = memnew(NativeMenu); } diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp index 6eb983d5e0..70b6bcf19e 100644 --- a/servers/physics_3d/godot_shape_3d.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -1133,7 +1133,7 @@ void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) { max_support = s; } } - if (extreme_vertices.find(best_vertex) == -1) + if (!extreme_vertices.has(best_vertex)) extreme_vertices.push_back(best_vertex); } } diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp index e621977326..7284076a47 100644 --- a/servers/physics_3d/godot_soft_body_3d.cpp +++ b/servers/physics_3d/godot_soft_body_3d.cpp @@ -140,7 +140,12 @@ void GodotSoftBody3D::set_mesh(RID p_mesh) { Array arrays = RenderingServer::get_singleton()->mesh_surface_get_arrays(soft_mesh, 0); ERR_FAIL_COND(arrays.is_empty()); - bool success = create_from_trimesh(arrays[RenderingServer::ARRAY_INDEX], arrays[RenderingServer::ARRAY_VERTEX]); + const Vector<int> &indices = arrays[RenderingServer::ARRAY_INDEX]; + const Vector<Vector3> &vertices = arrays[RenderingServer::ARRAY_VERTEX]; + ERR_FAIL_COND_MSG(indices.is_empty(), "Soft body's mesh needs to have indices"); + ERR_FAIL_COND_MSG(vertices.is_empty(), "Soft body's mesh needs to have vertices"); + + bool success = create_from_trimesh(indices, vertices); if (!success) { destroy(); } @@ -626,11 +631,11 @@ void GodotSoftBody3D::generate_bending_constraints(int p_distance) { for (Link &link : links) { const int ia = (int)(link.n[0] - &nodes[0]); const int ib = (int)(link.n[1] - &nodes[0]); - if (node_links[ia].find(ib) == -1) { + if (!node_links[ia].has(ib)) { node_links[ia].push_back(ib); } - if (node_links[ib].find(ia) == -1) { + if (!node_links[ib].has(ia)) { node_links[ib].push_back(ia); } } diff --git a/servers/physics_server_2d_wrap_mt.cpp b/servers/physics_server_2d_wrap_mt.cpp index 4548bb91cb..8e9f7aa8fc 100644 --- a/servers/physics_server_2d_wrap_mt.cpp +++ b/servers/physics_server_2d_wrap_mt.cpp @@ -32,45 +32,37 @@ #include "core/os/os.h" -void PhysicsServer2DWrapMT::thread_exit() { - exit = true; +void PhysicsServer2DWrapMT::_assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id) { + server_thread = Thread::get_caller_id(); + server_task_id = p_pump_task_id; } -void PhysicsServer2DWrapMT::thread_step(real_t p_delta) { - physics_server_2d->step(p_delta); - step_sem.post(); +void PhysicsServer2DWrapMT::_thread_exit() { + exit = true; } -void PhysicsServer2DWrapMT::thread_loop() { - server_thread = Thread::get_caller_id(); - - physics_server_2d->init(); - - command_queue.set_pump_task_id(server_task_id); +void PhysicsServer2DWrapMT::_thread_loop() { while (!exit) { WorkerThreadPool::get_singleton()->yield(); command_queue.flush_all(); } - - command_queue.flush_all(); - - physics_server_2d->finish(); } /* EVENT QUEUING */ void PhysicsServer2DWrapMT::step(real_t p_step) { if (create_thread) { - command_queue.push(this, &PhysicsServer2DWrapMT::thread_step, p_step); + command_queue.push(physics_server_2d, &PhysicsServer2D::step, p_step); } else { - command_queue.flush_all(); // Flush all pending from other threads. physics_server_2d->step(p_step); } } void PhysicsServer2DWrapMT::sync() { if (create_thread) { - step_sem.wait(); + command_queue.sync(); + } else { + command_queue.flush_all(); // Flush all pending from other threads. } physics_server_2d->sync(); } @@ -85,21 +77,26 @@ void PhysicsServer2DWrapMT::end_sync() { void PhysicsServer2DWrapMT::init() { if (create_thread) { - exit = false; - server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer2DWrapMT::thread_loop), true); - step_sem.post(); + WorkerThreadPool::TaskID tid = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer2DWrapMT::_thread_loop), true); + command_queue.set_pump_task_id(tid); + command_queue.push(this, &PhysicsServer2DWrapMT::_assign_mt_ids, tid); + command_queue.push_and_sync(physics_server_2d, &PhysicsServer2D::init); + DEV_ASSERT(server_task_id == tid); } else { + server_thread = Thread::MAIN_ID; physics_server_2d->init(); } } void PhysicsServer2DWrapMT::finish() { if (create_thread) { - command_queue.push(this, &PhysicsServer2DWrapMT::thread_exit); + command_queue.push(physics_server_2d, &PhysicsServer2D::finish); + command_queue.push(this, &PhysicsServer2DWrapMT::_thread_exit); if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) { WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id); server_task_id = WorkerThreadPool::INVALID_TASK_ID; } + server_thread = Thread::MAIN_ID; } else { physics_server_2d->finish(); } @@ -108,9 +105,6 @@ void PhysicsServer2DWrapMT::finish() { PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) { physics_server_2d = p_contained; create_thread = p_create_thread; - if (!create_thread) { - server_thread = Thread::MAIN_ID; - } } PhysicsServer2DWrapMT::~PhysicsServer2DWrapMT() { diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h index 5e2b3b4086..f0c36a906f 100644 --- a/servers/physics_server_2d_wrap_mt.h +++ b/servers/physics_server_2d_wrap_mt.h @@ -53,17 +53,14 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D { mutable CommandQueueMT command_queue; - void thread_loop(); - Thread::ID server_thread = Thread::UNASSIGNED_ID; WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID; bool exit = false; - Semaphore step_sem; bool create_thread = false; - void thread_step(real_t p_delta); - - void thread_exit(); + void _assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id); + void _thread_exit(); + void _thread_loop(); public: #define ServerName PhysicsServer2D diff --git a/servers/physics_server_3d_wrap_mt.cpp b/servers/physics_server_3d_wrap_mt.cpp index f8f60281a7..95b71217c4 100644 --- a/servers/physics_server_3d_wrap_mt.cpp +++ b/servers/physics_server_3d_wrap_mt.cpp @@ -32,45 +32,37 @@ #include "core/os/os.h" -void PhysicsServer3DWrapMT::thread_exit() { - exit = true; +void PhysicsServer3DWrapMT::_assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id) { + server_thread = Thread::get_caller_id(); + server_task_id = p_pump_task_id; } -void PhysicsServer3DWrapMT::thread_step(real_t p_delta) { - physics_server_3d->step(p_delta); - step_sem.post(); +void PhysicsServer3DWrapMT::_thread_exit() { + exit = true; } -void PhysicsServer3DWrapMT::thread_loop() { - server_thread = Thread::get_caller_id(); - - physics_server_3d->init(); - - command_queue.set_pump_task_id(server_task_id); +void PhysicsServer3DWrapMT::_thread_loop() { while (!exit) { WorkerThreadPool::get_singleton()->yield(); command_queue.flush_all(); } - - command_queue.flush_all(); // flush all - - physics_server_3d->finish(); } /* EVENT QUEUING */ void PhysicsServer3DWrapMT::step(real_t p_step) { if (create_thread) { - command_queue.push(this, &PhysicsServer3DWrapMT::thread_step, p_step); + command_queue.push(physics_server_3d, &PhysicsServer3D::step, p_step); } else { - command_queue.flush_all(); // Flush all pending from other threads. physics_server_3d->step(p_step); } } void PhysicsServer3DWrapMT::sync() { if (create_thread) { - step_sem.wait(); + command_queue.sync(); + } else { + command_queue.flush_all(); // Flush all pending from other threads. } physics_server_3d->sync(); } @@ -85,21 +77,26 @@ void PhysicsServer3DWrapMT::end_sync() { void PhysicsServer3DWrapMT::init() { if (create_thread) { - exit = false; - server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer3DWrapMT::thread_loop), true); - step_sem.post(); + WorkerThreadPool::TaskID tid = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer3DWrapMT::_thread_loop), true); + command_queue.set_pump_task_id(tid); + command_queue.push(this, &PhysicsServer3DWrapMT::_assign_mt_ids, tid); + command_queue.push_and_sync(physics_server_3d, &PhysicsServer3D::init); + DEV_ASSERT(server_task_id == tid); } else { + server_thread = Thread::MAIN_ID; physics_server_3d->init(); } } void PhysicsServer3DWrapMT::finish() { if (create_thread) { - command_queue.push(this, &PhysicsServer3DWrapMT::thread_exit); + command_queue.push(physics_server_3d, &PhysicsServer3D::finish); + command_queue.push(this, &PhysicsServer3DWrapMT::_thread_exit); if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) { WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id); server_task_id = WorkerThreadPool::INVALID_TASK_ID; } + server_thread = Thread::MAIN_ID; } else { physics_server_3d->finish(); } @@ -108,9 +105,6 @@ void PhysicsServer3DWrapMT::finish() { PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread) { physics_server_3d = p_contained; create_thread = p_create_thread; - if (!create_thread) { - server_thread = Thread::MAIN_ID; - } } PhysicsServer3DWrapMT::~PhysicsServer3DWrapMT() { diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h index 22f3ee0e45..0909c46b55 100644 --- a/servers/physics_server_3d_wrap_mt.h +++ b/servers/physics_server_3d_wrap_mt.h @@ -52,17 +52,15 @@ class PhysicsServer3DWrapMT : public PhysicsServer3D { mutable CommandQueueMT command_queue; - void thread_loop(); - Thread::ID server_thread = Thread::UNASSIGNED_ID; WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID; bool exit = false; - Semaphore step_sem; bool create_thread = false; - void thread_step(real_t p_delta); - - void thread_exit(); + void _assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id); + void _thread_exit(); + void _thread_step(real_t p_delta); + void _thread_loop(); public: #define ServerName PhysicsServer3D diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 1a75614a4c..7a15d202a3 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -325,6 +325,7 @@ void register_server_types() { PhysicsServer3DManager::get_singleton()->set_default_server("GodotPhysics3D"); GDREGISTER_ABSTRACT_CLASS(XRInterface); + GDREGISTER_CLASS(XRVRS); GDREGISTER_CLASS(XRBodyTracker); GDREGISTER_CLASS(XRControllerTracker); GDREGISTER_CLASS(XRFaceTracker); diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index 1331ca72c2..43572b65e0 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -193,6 +193,8 @@ public: virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override {} virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_DISABLED; } + virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) override {} + virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_UPDATE_DISABLED; } virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {} virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); } diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index e48c72cec7..42de831e7a 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -38,6 +38,12 @@ #include "rendering_server_globals.h" #include "servers/rendering/storage/texture_storage.h" +// Use the same antialiasing feather size as StyleBoxFlat's default +// (but doubled, as it's specified for both sides here). +// This value is empirically determined to provide good antialiasing quality +// while not making lines appear too soft. +const static float FEATHER_SIZE = 1.25f; + void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) { RENDER_TIMESTAMP("Cull CanvasItem Tree"); @@ -638,11 +644,8 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, } if (p_antialiased) { - // Use the same antialiasing feather size as StyleBoxFlat's default - // (but doubled, as it's specified for both sides here). - // This value is empirically determined to provide good antialiasing quality - // while not making lines appear too soft. - float border_size = 1.25f; + float border_size = FEATHER_SIZE; + if (0.0f <= p_width && p_width < 1.0f) { border_size *= p_width; } @@ -651,7 +654,7 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, Vector2 border = dir * border_size; Vector2 border2 = dir2 * border_size; - Color transparent = Color(p_color.r, p_color.g, p_color.b, 0.0); + Color transparent = Color(p_color, 0.0); { Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>(); @@ -903,11 +906,7 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point Color *colors_ptr = colors.ptrw(); if (p_antialiased) { - // Use the same antialiasing feather size as StyleBoxFlat's default - // (but doubled, as it's specified for both sides here). - // This value is empirically determined to provide good antialiasing quality - // while not making lines appear too soft. - float border_size = 1.25f; + float border_size = FEATHER_SIZE; if (p_width < 1.0f) { border_size *= p_width; } @@ -1094,12 +1093,15 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point pline->polygon.create(indices, points, colors); } -void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) { +void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) { ERR_FAIL_COND(p_points.is_empty() || p_points.size() % 2 != 0); ERR_FAIL_COND(p_colors.size() != 1 && p_colors.size() * 2 != p_points.size()); // TODO: `canvas_item_add_line`(`multiline`, `polyline`) share logic, should factor out. if (p_width < 0) { + if (p_antialiased) { + WARN_PRINT("Antialiasing is not supported for thin multilines drawn using line strips (`p_width < 0`)."); + } Item *canvas_item = canvas_item_owner.get_or_null(p_item); ERR_FAIL_NULL(canvas_item); @@ -1127,7 +1129,7 @@ void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Poin Vector2 from = p_points[i * 2 + 0]; Vector2 to = p_points[i * 2 + 1]; - canvas_item_add_line(p_item, from, to, color, p_width); + canvas_item_add_line(p_item, from, to, color, p_width, p_antialiased); } } else { //} else if (p_colors.size() << 1 == p_points.size()) { for (int i = 0; i < p_colors.size(); i++) { @@ -1135,13 +1137,13 @@ void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Poin Vector2 from = p_points[i * 2 + 0]; Vector2 to = p_points[i * 2 + 1]; - canvas_item_add_line(p_item, from, to, color, p_width); + canvas_item_add_line(p_item, from, to, color, p_width, p_antialiased); } } } } -void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) { +void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased) { Item *canvas_item = canvas_item_owner.get_or_null(p_item); ERR_FAIL_NULL(canvas_item); @@ -1149,45 +1151,251 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c ERR_FAIL_NULL(rect); rect->modulate = p_color; rect->rect = p_rect; + + // Add feathers. + if (p_antialiased) { + float border_size = FEATHER_SIZE; + + const real_t size = MIN(p_rect.size.width, p_rect.size.height); + if (0.0f <= size && size < 1.0f) { + border_size *= size; + } + + const Vector2 vec_down = Vector2(0.0f, p_rect.size.height); + const Vector2 vec_right = Vector2(p_rect.size.width, 0.0f); + + const Vector2 begin_left = p_rect.position; + const Vector2 begin_right = p_rect.position + vec_down; + const Vector2 end_left = p_rect.position + vec_right; + const Vector2 end_right = p_rect.position + p_rect.size; + + const Vector2 dir = Vector2(0.0f, -1.0f); + const Vector2 dir2 = Vector2(-1.0f, 0.0f); + const Vector2 border = dir * border_size; + const Vector2 border2 = dir2 * border_size; + + Color transparent = Color(p_color, 0.0); + + { + Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>(); + ERR_FAIL_NULL(left_border); + + left_border->points[0] = begin_left; + left_border->points[1] = begin_left + border; + left_border->points[2] = end_left + border; + left_border->points[3] = end_left; + + left_border->colors[0] = p_color; + left_border->colors[1] = transparent; + left_border->colors[2] = transparent; + left_border->colors[3] = p_color; + + left_border->point_count = 4; + } + { + Item::CommandPrimitive *right_border = canvas_item->alloc_command<Item::CommandPrimitive>(); + ERR_FAIL_NULL(right_border); + + right_border->points[0] = begin_right; + right_border->points[1] = begin_right - border; + right_border->points[2] = end_right - border; + right_border->points[3] = end_right; + + right_border->colors[0] = p_color; + right_border->colors[1] = transparent; + right_border->colors[2] = transparent; + right_border->colors[3] = p_color; + + right_border->point_count = 4; + } + { + Item::CommandPrimitive *top_border = canvas_item->alloc_command<Item::CommandPrimitive>(); + ERR_FAIL_NULL(top_border); + + top_border->points[0] = begin_left; + top_border->points[1] = begin_left + border2; + top_border->points[2] = begin_right + border2; + top_border->points[3] = begin_right; + + top_border->colors[0] = p_color; + top_border->colors[1] = transparent; + top_border->colors[2] = transparent; + top_border->colors[3] = p_color; + + top_border->point_count = 4; + } + { + Item::CommandPrimitive *bottom_border = canvas_item->alloc_command<Item::CommandPrimitive>(); + ERR_FAIL_NULL(bottom_border); + + bottom_border->points[0] = end_left; + bottom_border->points[1] = end_left - border2; + bottom_border->points[2] = end_right - border2; + bottom_border->points[3] = end_right; + + bottom_border->colors[0] = p_color; + bottom_border->colors[1] = transparent; + bottom_border->colors[2] = transparent; + bottom_border->colors[3] = p_color; + + bottom_border->point_count = 4; + } + { + Item::CommandPrimitive *top_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>(); + ERR_FAIL_NULL(top_left_corner); + + top_left_corner->points[0] = begin_left; + top_left_corner->points[1] = begin_left + border2; + top_left_corner->points[2] = begin_left + border + border2; + top_left_corner->points[3] = begin_left + border; + + top_left_corner->colors[0] = p_color; + top_left_corner->colors[1] = transparent; + top_left_corner->colors[2] = transparent; + top_left_corner->colors[3] = transparent; + + top_left_corner->point_count = 4; + } + { + Item::CommandPrimitive *top_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>(); + ERR_FAIL_NULL(top_right_corner); + + top_right_corner->points[0] = begin_right; + top_right_corner->points[1] = begin_right + border2; + top_right_corner->points[2] = begin_right - border + border2; + top_right_corner->points[3] = begin_right - border; + + top_right_corner->colors[0] = p_color; + top_right_corner->colors[1] = transparent; + top_right_corner->colors[2] = transparent; + top_right_corner->colors[3] = transparent; + + top_right_corner->point_count = 4; + } + { + Item::CommandPrimitive *bottom_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>(); + ERR_FAIL_NULL(bottom_left_corner); + + bottom_left_corner->points[0] = end_left; + bottom_left_corner->points[1] = end_left - border2; + bottom_left_corner->points[2] = end_left + border - border2; + bottom_left_corner->points[3] = end_left + border; + + bottom_left_corner->colors[0] = p_color; + bottom_left_corner->colors[1] = transparent; + bottom_left_corner->colors[2] = transparent; + bottom_left_corner->colors[3] = transparent; + + bottom_left_corner->point_count = 4; + } + { + Item::CommandPrimitive *bottom_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>(); + ERR_FAIL_NULL(bottom_right_corner); + + bottom_right_corner->points[0] = end_right; + bottom_right_corner->points[1] = end_right - border2; + bottom_right_corner->points[2] = end_right - border - border2; + bottom_right_corner->points[3] = end_right - border; + + bottom_right_corner->colors[0] = p_color; + bottom_right_corner->colors[1] = transparent; + bottom_right_corner->colors[2] = transparent; + bottom_right_corner->colors[3] = transparent; + + bottom_right_corner->point_count = 4; + } + } } -void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) { +void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased) { Item *canvas_item = canvas_item_owner.get_or_null(p_item); ERR_FAIL_NULL(canvas_item); - Item::CommandPolygon *circle = canvas_item->alloc_command<Item::CommandPolygon>(); - ERR_FAIL_NULL(circle); + static const int circle_segments = 64; - circle->primitive = RS::PRIMITIVE_TRIANGLES; + { + Item::CommandPolygon *circle = canvas_item->alloc_command<Item::CommandPolygon>(); + ERR_FAIL_NULL(circle); - Vector<int> indices; - Vector<Vector2> points; + circle->primitive = RS::PRIMITIVE_TRIANGLES; - static const int circle_points = 64; + Vector<int> indices; + Vector<Vector2> points; - points.resize(circle_points); - Vector2 *points_ptr = points.ptrw(); - const real_t circle_point_step = Math_TAU / circle_points; + points.resize(circle_segments + 2); + Vector2 *points_ptr = points.ptrw(); - for (int i = 0; i < circle_points; i++) { - float angle = i * circle_point_step; - points_ptr[i].x = Math::cos(angle) * p_radius; - points_ptr[i].y = Math::sin(angle) * p_radius; - points_ptr[i] += p_pos; - } + // Store circle center in the last point. + points_ptr[circle_segments + 1] = p_pos; - indices.resize((circle_points - 2) * 3); - int *indices_ptr = indices.ptrw(); + const real_t circle_point_step = Math_TAU / circle_segments; + + for (int i = 0; i < circle_segments + 1; i++) { + float angle = i * circle_point_step; + points_ptr[i].x = Math::cos(angle) * p_radius; + points_ptr[i].y = Math::sin(angle) * p_radius; + points_ptr[i] += p_pos; + } - for (int i = 0; i < circle_points - 2; i++) { - indices_ptr[i * 3 + 0] = 0; - indices_ptr[i * 3 + 1] = i + 1; - indices_ptr[i * 3 + 2] = i + 2; + indices.resize(circle_segments * 3); + int *indices_ptr = indices.ptrw(); + + for (int i = 0; i < circle_segments; i++) { + indices_ptr[i * 3 + 0] = circle_segments + 1; + indices_ptr[i * 3 + 1] = i; + indices_ptr[i * 3 + 2] = i + 1; + } + + Vector<Color> color; + color.push_back(p_color); + circle->polygon.create(indices, points, color); } - Vector<Color> color; - color.push_back(p_color); - circle->polygon.create(indices, points, color); + if (p_antialiased) { + float border_size = FEATHER_SIZE; + + const float diameter = p_radius * 2.0f; + if (0.0f <= diameter && diameter < 1.0f) { + border_size *= p_radius; + } + + Item::CommandPolygon *feather = canvas_item->alloc_command<Item::CommandPolygon>(); + ERR_FAIL_NULL(feather); + feather->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; + + Color transparent = Color(p_color, 0.0); + + Vector<int> indices; + Vector<Color> colors; + Vector<Vector2> points; + + points.resize(2 * circle_segments + 2); + colors.resize(2 * circle_segments + 2); + + const real_t circle_point_step = Math_TAU / circle_segments; + + Vector2 *points_ptr = points.ptrw(); + Color *colors_ptr = colors.ptrw(); + + for (int i = 0; i < circle_segments + 1; i++) { + const float angle = i * circle_point_step; + const float c = Math::cos(angle); + const float s = Math::sin(angle); + + points_ptr[i * 2].x = c * p_radius; + points_ptr[i * 2].y = s * p_radius; + points_ptr[i * 2] += p_pos; + + points_ptr[i * 2 + 1].x = c * (p_radius + border_size); + points_ptr[i * 2 + 1].y = s * (p_radius + border_size); + points_ptr[i * 2 + 1] += p_pos; + + colors_ptr[i * 2] = p_color; + colors_ptr[i * 2 + 1] = transparent; + } + + feather->polygon.create(indices, points, colors); + } } void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose) { diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 961506ca28..9f8cbea2e9 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -233,9 +233,9 @@ public: void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false); void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false); - void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0); - void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color); - void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); + void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false); + void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased); + void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased); void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false); void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0); diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index a363b03dd8..c7a7532d76 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -661,10 +661,9 @@ void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) { RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u); RD::get_singleton()->draw_list_end(); } @@ -927,10 +926,9 @@ void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u); RD::get_singleton()->draw_list_end(); } diff --git a/servers/rendering/renderer_rd/effects/debug_effects.cpp b/servers/rendering/renderer_rd/effects/debug_effects.cpp index 017ad41fdc..04afaf63d7 100644 --- a/servers/rendering/renderer_rd/effects/debug_effects.cpp +++ b/servers/rendering/renderer_rd/effects/debug_effects.cpp @@ -354,7 +354,9 @@ void DebugEffects::draw_motion_vectors(RID p_velocity, RID p_depth, RID p_dest_f RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, motion_vectors.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_fb), false, RD::get_singleton()->draw_list_get_current_pass())); - Projection reprojection = p_previous_projection.flipped_y() * p_previous_transform.affine_inverse() * p_current_transform * p_current_projection.flipped_y().inverse(); + Projection correction; + correction.set_depth_correction(true, true, false); + Projection reprojection = (correction * p_previous_projection) * p_previous_transform.affine_inverse() * p_current_transform * (correction * p_current_projection).inverse(); RendererRD::MaterialStorage::store_camera(reprojection, motion_vectors.push_constant.reprojection_matrix); motion_vectors.push_constant.resolution[0] = p_resolution.width; diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp index 30c318fb9a..94453bf95f 100644 --- a/servers/rendering/renderer_rd/effects/vrs.cpp +++ b/servers/rendering/renderer_rd/effects/vrs.cpp @@ -80,7 +80,16 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); - VRSMode mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT; + VRSPushConstant push_constant = {}; + + int mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT; + + // Set maximum texel factor based on maximum fragment size, some GPUs do not support 8x8 (fragment shading rate approach). + if (MIN(RD::get_singleton()->limit_get(RD::LIMIT_VRS_MAX_FRAGMENT_WIDTH), RD::get_singleton()->limit_get(RD::LIMIT_VRS_MAX_FRAGMENT_HEIGHT)) > 4) { + push_constant.max_texel_factor = 3.0; + } else { + push_constant.max_texel_factor = 2.0; + } RID shader = vrs_shader.shader.version_get_shader(vrs_shader.shader_version, mode); ERR_FAIL_COND(shader.is_null()); @@ -88,7 +97,7 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>()); RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); - // RD::get_singleton()->draw_list_set_push_constant(draw_list, &vrs_shader.push_constant, sizeof(VRSPushConstant)); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(VRSPushConstant)); RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u); RD::get_singleton()->draw_list_end(); } @@ -111,12 +120,11 @@ Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const { void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) { TextureStorage *texture_storage = TextureStorage::get_singleton(); RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target); + RS::ViewportVRSUpdateMode vrs_update_mode = texture_storage->render_target_get_vrs_update_mode(p_render_target); - if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) { + if (vrs_mode != RS::VIEWPORT_VRS_DISABLED && vrs_update_mode != RS::VIEWPORT_VRS_UPDATE_DISABLED) { RD::get_singleton()->draw_command_begin_label("VRS Setup"); - // TODO figure out if image has changed since it was last copied so we can save some resources.. - if (vrs_mode == RS::VIEWPORT_VRS_TEXTURE) { RID vrs_texture = texture_storage->render_target_get_vrs_texture(p_render_target); if (vrs_texture.is_valid()) { @@ -145,6 +153,10 @@ void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) { #endif // _3D_DISABLED } + if (vrs_update_mode == RS::VIEWPORT_VRS_UPDATE_ONCE) { + texture_storage->render_target_set_vrs_update_mode(p_render_target, RS::VIEWPORT_VRS_UPDATE_DISABLED); + } + RD::get_singleton()->draw_command_end_label(); } } diff --git a/servers/rendering/renderer_rd/effects/vrs.h b/servers/rendering/renderer_rd/effects/vrs.h index b18cf55791..94878e4661 100644 --- a/servers/rendering/renderer_rd/effects/vrs.h +++ b/servers/rendering/renderer_rd/effects/vrs.h @@ -47,11 +47,12 @@ private: VRS_MAX, }; - /* we have no push constant here (yet) struct VRSPushConstant { - + float max_texel_factor; // 4x8, 8x4 and 8x8 are only available on some GPUs. + float res1; + float res2; + float res3; }; - */ struct VRSShader { // VRSPushConstant push_constant; 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 2df0331688..aae32f0b3e 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -972,14 +972,14 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con float distance = 0.0; // Check if camera is NOT inside the mesh AABB. - if (!inst->transformed_aabb.has_point(p_render_data->scene_data->cam_transform.origin)) { + if (!inst->transformed_aabb.has_point(p_render_data->scene_data->main_cam_transform.origin)) { // Get the LOD support points on the mesh AABB. - Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z)); - Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z)); + Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->scene_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z)); + Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->scene_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z)); // Get the distances to those points on the AABB from the camera origin. - float distance_min = (float)p_render_data->scene_data->cam_transform.origin.distance_to(lod_support_min); - float distance_max = (float)p_render_data->scene_data->cam_transform.origin.distance_to(lod_support_max); + float distance_min = (float)p_render_data->scene_data->main_cam_transform.origin.distance_to(lod_support_min); + float distance_max = (float)p_render_data->scene_data->main_cam_transform.origin.distance_to(lod_support_max); if (distance_min * distance_max < 0.0) { //crossing plane @@ -1388,7 +1388,6 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo p_render_data->shadows.clear(); p_render_data->directional_shadows.clear(); - Plane camera_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin); float lod_distance_multiplier = p_render_data->scene_data->cam_projection.get_lod_multiplier(); { for (int i = 0; i < p_render_data->render_shadow_count; i++) { @@ -1407,7 +1406,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo RENDER_TIMESTAMP("Render OmniLight Shadows"); // Cube shadows are rendered in their own way. for (const int &index : p_render_data->cube_shadows) { - _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform); + _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform); } if (p_render_data->directional_shadows.size()) { @@ -1437,11 +1436,11 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo //render directional shadows for (uint32_t i = 0; i < p_render_data->directional_shadows.size(); i++) { - _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform); + _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform); } //render positional shadows for (uint32_t i = 0; i < p_render_data->shadows.size(); i++) { - _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform); + _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform); } _render_shadow_process(); @@ -1812,6 +1811,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment); float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment); bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment); + RS::EnvironmentReflectionSource reflection_source = environment_get_reflection_source(p_render_data->environment); if (p_render_data->camera_attributes.is_valid()) { bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); @@ -1823,7 +1823,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.r *= bg_energy_multiplier; clear_color.g *= bg_energy_multiplier; clear_color.b *= bg_energy_multiplier; - if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) { + if (!p_render_data->transparent_bg && rb->has_custom_data(RB_SCOPE_FOG) && environment_get_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } @@ -1833,13 +1833,13 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.r *= bg_energy_multiplier; clear_color.g *= bg_energy_multiplier; clear_color.b *= bg_energy_multiplier; - if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) { + if (!p_render_data->transparent_bg && rb->has_custom_data(RB_SCOPE_FOG) && environment_get_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } } break; case RS::ENV_BG_SKY: { - draw_sky = true; + draw_sky = !p_render_data->transparent_bg; } break; case RS::ENV_BG_CANVAS: { if (!is_reflection_probe) { @@ -1859,7 +1859,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } // setup sky if used for ambient, reflections, or background - if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { + if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); RD::get_singleton()->draw_command_begin_label("Setup Sky"); @@ -2289,11 +2289,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co params.delta_time = float(time_step); params.reset_accumulation = false; // FIXME: The engine does not provide a way to reset the accumulation. + Projection correction; + correction.set_depth_correction(true, true, false); + const Projection &prev_proj = p_render_data->scene_data->prev_cam_projection; const Projection &cur_proj = p_render_data->scene_data->cam_projection; const Transform3D &prev_transform = p_render_data->scene_data->prev_cam_transform; const Transform3D &cur_transform = p_render_data->scene_data->cam_transform; - params.reprojection = prev_proj.flipped_y() * prev_transform.affine_inverse() * cur_transform * cur_proj.flipped_y().inverse(); + params.reprojection = (correction * prev_proj) * prev_transform.affine_inverse() * cur_transform * (correction * cur_proj).inverse(); fsr2_effect->upscale(params); } @@ -2367,7 +2370,7 @@ void RenderForwardClustered::_render_buffers_debug_draw(const RenderDataRD *p_re } } -void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size, const Transform3D &p_main_cam_transform) { +void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size, const Transform3D &p_main_cam_transform) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); ERR_FAIL_COND(!light_storage->owns_light_instance(p_light)); @@ -2522,7 +2525,7 @@ void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas if (render_cubemap) { //rendering to cubemap - _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info, p_viewport_size, p_main_cam_transform); + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, false, false, use_pancake, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info, p_viewport_size, p_main_cam_transform); if (finalize_cubemap) { _render_shadow_process(); _render_shadow_end(); @@ -2540,7 +2543,7 @@ void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas } else { //render shadow - _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info, p_viewport_size, p_main_cam_transform); + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info, p_viewport_size, p_main_cam_transform); } } @@ -2553,7 +2556,7 @@ void RenderForwardClustered::_render_shadow_begin() { scene_state.instance_data[RENDER_LIST_SECONDARY].clear(); } -void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size, const Transform3D &p_main_cam_transform) { +void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size, const Transform3D &p_main_cam_transform) { uint32_t shadow_pass_index = scene_state.shadow_passes.size(); SceneState::ShadowPass shadow_pass; @@ -2611,7 +2614,6 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page shadow_pass.pass_mode = pass_mode; shadow_pass.rp_uniform_set = RID(); //will be filled later when instance buffer is complete - shadow_pass.camera_plane = p_camera_plane; shadow_pass.screen_mesh_lod_threshold = scene_data.screen_mesh_lod_threshold; shadow_pass.lod_distance_multiplier = scene_data.lod_distance_multiplier; @@ -3575,11 +3577,11 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RID RenderForwardClustered::_render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) { Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); - return p_render_buffers->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED ? rb_data->get_normal_roughness() : rb_data->get_normal_roughness_msaa(); + return rb_data->get_normal_roughness(); } RID RenderForwardClustered::_render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) { - return p_render_buffers->get_velocity_buffer(p_render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED); + return p_render_buffers->get_velocity_buffer(false); } void RenderForwardClustered::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) { 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 1f12d92754..ae9e5e7c10 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -347,7 +347,6 @@ class RenderForwardClustered : public RendererSceneRenderRD { PassMode pass_mode; RID rp_uniform_set; - Plane camera_plane; float lod_distance_multiplier; float screen_mesh_lod_threshold; @@ -594,9 +593,9 @@ class RenderForwardClustered : public RendererSceneRenderRD { /* Render shadows */ - void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1), const Transform3D &p_main_cam_transform = Transform3D()); + void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1), const Transform3D &p_main_cam_transform = Transform3D()); void _render_shadow_begin(); - void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1), const Transform3D &p_main_cam_transform = Transform3D()); + void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1), const Transform3D &p_main_cam_transform = Transform3D()); void _render_shadow_process(); void _render_shadow_end(); 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 5715d94d95..194a70dc22 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -590,7 +590,6 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { p_render_data->shadows.clear(); p_render_data->directional_shadows.clear(); - Plane camera_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin); float lod_distance_multiplier = p_render_data->scene_data->cam_projection.get_lod_multiplier(); { for (int i = 0; i < p_render_data->render_shadow_count; i++) { @@ -608,7 +607,7 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { //cube shadows are rendered in their own way for (const int &index : p_render_data->cube_shadows) { - _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, p_render_data->scene_data->cam_transform); + _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, p_render_data->scene_data->cam_transform); } if (p_render_data->directional_shadows.size()) { @@ -629,11 +628,11 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { //render directional shadows for (uint32_t i = 0; i < p_render_data->directional_shadows.size(); i++) { - _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info, p_render_data->scene_data->cam_transform); + _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info, p_render_data->scene_data->cam_transform); } //render positional shadows for (uint32_t i = 0; i < p_render_data->shadows.size(); i++) { - _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info, p_render_data->scene_data->cam_transform); + _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info, p_render_data->scene_data->cam_transform); } _render_shadow_process(); @@ -830,6 +829,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment); float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment); bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment); + RS::EnvironmentReflectionSource reflection_source = environment_get_reflection_source(p_render_data->environment); if (p_render_data->camera_attributes.is_valid()) { bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); @@ -841,7 +841,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color clear_color.r *= bg_energy_multiplier; clear_color.g *= bg_energy_multiplier; clear_color.b *= bg_energy_multiplier; - if (environment_get_fog_enabled(p_render_data->environment)) { + if (!p_render_data->transparent_bg && environment_get_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } @@ -851,13 +851,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color clear_color.r *= bg_energy_multiplier; clear_color.g *= bg_energy_multiplier; clear_color.b *= bg_energy_multiplier; - if (environment_get_fog_enabled(p_render_data->environment)) { + if (!p_render_data->transparent_bg && environment_get_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } } break; case RS::ENV_BG_SKY: { - draw_sky = true; + draw_sky = !p_render_data->transparent_bg; } break; case RS::ENV_BG_CANVAS: { if (rb_data.is_valid()) { @@ -874,7 +874,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } // setup sky if used for ambient, reflections, or background - if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { + if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); RD::get_singleton()->draw_command_begin_label("Setup Sky"); @@ -1114,7 +1114,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color /* these are being called from RendererSceneRenderRD::_pre_opaque_render */ -void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info, const Transform3D &p_main_cam_transform) { +void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info, const Transform3D &p_main_cam_transform) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); ERR_FAIL_COND(!light_storage->owns_light_instance(p_light)); @@ -1268,7 +1268,7 @@ void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, i if (render_cubemap) { //rendering to cubemap - _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info, p_main_cam_transform); + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info, p_main_cam_transform); if (finalize_cubemap) { _render_shadow_process(); _render_shadow_end(); @@ -1287,7 +1287,7 @@ void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, i } else { //render shadow - _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info, p_main_cam_transform); + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info, p_main_cam_transform); } } @@ -1299,7 +1299,7 @@ void RenderForwardMobile::_render_shadow_begin() { render_list[RENDER_LIST_SECONDARY].clear(); } -void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Transform3D &p_main_cam_transform) { +void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Transform3D &p_main_cam_transform) { uint32_t shadow_pass_index = scene_state.shadow_passes.size(); SceneState::ShadowPass shadow_pass; @@ -1356,7 +1356,6 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr shadow_pass.pass_mode = pass_mode; shadow_pass.rp_uniform_set = RID(); //will be filled later when instance buffer is complete - shadow_pass.camera_plane = p_camera_plane; shadow_pass.screen_mesh_lod_threshold = scene_data.screen_mesh_lod_threshold; shadow_pass.lod_distance_multiplier = scene_data.lod_distance_multiplier; @@ -1878,25 +1877,27 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const // LOD if (p_render_data->scene_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { - // Get the LOD support points on the mesh AABB. - Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z)); - Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z)); - - // Get the distances to those points on the AABB from the camera origin. - float distance_min = (float)p_render_data->scene_data->cam_transform.origin.distance_to(lod_support_min); - float distance_max = (float)p_render_data->scene_data->cam_transform.origin.distance_to(lod_support_max); - float distance = 0.0; - if (distance_min * distance_max < 0.0) { - //crossing plane - distance = 0.0; - } else if (distance_min >= 0.0) { - distance = distance_min; - } else if (distance_max <= 0.0) { - distance = -distance_max; + // Check if camera is NOT inside the mesh AABB. + if (!inst->transformed_aabb.has_point(p_render_data->scene_data->main_cam_transform.origin)) { + // Get the LOD support points on the mesh AABB. + Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->scene_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z)); + Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->scene_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z)); + + // Get the distances to those points on the AABB from the camera origin. + float distance_min = (float)p_render_data->scene_data->main_cam_transform.origin.distance_to(lod_support_min); + float distance_max = (float)p_render_data->scene_data->main_cam_transform.origin.distance_to(lod_support_max); + + if (distance_min * distance_max < 0.0) { + //crossing plane + distance = 0.0; + } else if (distance_min >= 0.0) { + distance = distance_min; + } else if (distance_max <= 0.0) { + distance = -distance_max; + } } - if (p_render_data->scene_data->cam_orthogonal) { distance = 1.0; } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index f29503e5ec..aa1b8f34b2 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -178,9 +178,9 @@ private: /* Render shadows */ - void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Transform3D &p_main_cam_transform = Transform3D()); + void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Transform3D &p_main_cam_transform = Transform3D()); void _render_shadow_begin(); - void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Transform3D &p_main_cam_transform = Transform3D()); + void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Transform3D &p_main_cam_transform = Transform3D()); void _render_shadow_process(); void _render_shadow_end(); @@ -270,7 +270,6 @@ private: PassMode pass_mode; RID rp_uniform_set; - Plane camera_plane; float lod_distance_multiplier; float screen_mesh_lod_threshold; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 733cbd1ff2..dd722cc2dd 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -587,7 +587,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; - actions.usage_defines["LIGHT_VERTEX"] = "#define LIGHT_VERTEX\n"; + actions.usage_defines["LIGHT_VERTEX"] = "#define LIGHT_VERTEX_USED\n"; actions.usage_defines["ALPHA_SCISSOR_THRESHOLD"] = "#define ALPHA_SCISSOR_USED\n"; actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n"; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 012451a5cd..14d138181f 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -169,7 +169,11 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color return; } - RD::get_singleton()->screen_prepare_for_drawing(DisplayServer::MAIN_WINDOW_ID); + Error err = RD::get_singleton()->screen_prepare_for_drawing(DisplayServer::MAIN_WINDOW_ID); + if (err != OK) { + // Window is minimized and does not have valid swapchain, skip drawing without printing errors. + return; + } RID texture = texture_storage->texture_allocate(); texture_storage->texture_2d_initialize(texture, p_image); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 6cb03871c9..1e4880e67a 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -1149,6 +1149,10 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render render_data.sdfgi_update_data = p_sdfgi_update_data; render_data.render_info = r_render_info; + + if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) { + render_data.transparent_bg = texture_storage->render_target_get_transparent(rb->get_render_target()); + } } PagedArray<RID> empty; diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index 789c6c2845..1c1b8366e5 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -687,8 +687,8 @@ void ShaderRD::enable_group(int p_group) { // Compile all versions again to include the new group. List<RID> all_versions; version_owner.get_owned_list(&all_versions); - for (int i = 0; i < all_versions.size(); i++) { - Version *version = version_owner.get_or_null(all_versions[i]); + for (const RID &E : all_versions) { + Version *version = version_owner.get_or_null(E); _compile_version(version, p_group); } } diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl index 23b0373eef..b4fcaa4673 100644 --- a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl @@ -19,6 +19,14 @@ layout(location = 0) out vec3 uv_interp; layout(location = 0) out vec2 uv_interp; #endif +layout(push_constant, std430) uniform Params { + float max_texel_factor; + float res1; + float res2; + float res3; +} +params; + void main() { vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0)); gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0); @@ -53,6 +61,14 @@ layout(set = 0, binding = 0) uniform sampler2D source_color; layout(location = 0) out uint frag_color; +layout(push_constant, std430) uniform Params { + float max_texel_factor; + float res1; + float res2; + float res3; +} +params; + void main() { #ifdef USE_MULTIVIEW vec3 uv = uv_interp; @@ -60,20 +76,22 @@ void main() { vec2 uv = uv_interp; #endif -#ifdef USE_MULTIVIEW + // Input is standardized. R for X, G for Y, 0.0 (0) = 1, 0.33 (85) = 2, 0.66 (170) = 3, 1.0 (255) = 8 vec4 color = textureLod(source_color, uv, 0.0); - frag_color = uint(color.r * 255.0); -#else /* USE_MULTIVIEW */ - vec4 color = textureLod(source_color, uv, 0.0); - - // for user supplied VRS map we do a color mapping - color.r *= 3.0; - frag_color = int(color.r) << 2; - color.g *= 3.0; - frag_color += int(color.g); - - // note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported - // 4x8, 8x4 and 8x8 are only available on some GPUs -#endif /* USE_MULTIVIEW */ + // Output image shading rate image for VRS according to VK_KHR_fragment_shading_rate. + color.r = clamp(floor(color.r * params.max_texel_factor + 0.1), 0.0, params.max_texel_factor); + color.g = clamp(floor(color.g * params.max_texel_factor + 0.1), 0.0, params.max_texel_factor); + + // Note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported: + if (color.r < (color.g - 1.0)) { + color.r = color.g - 1.0; + } + if (color.g < (color.r - 1.0)) { + color.g = color.r - 1.0; + } + + // Encode to frag_color; + frag_color = int(color.r + 0.1) << 2; + frag_color += int(color.g + 0.1); } diff --git a/servers/rendering/renderer_rd/shaders/samplers_inc.glsl b/servers/rendering/renderer_rd/shaders/samplers_inc.glsl index 3f6172795e..ae5dbd4761 100644 --- a/servers/rendering/renderer_rd/shaders/samplers_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/samplers_inc.glsl @@ -9,4 +9,4 @@ layout(set = 0, binding = SAMPLERS_BINDING_FIRST_INDEX + 7) uniform sampler SAMP layout(set = 0, binding = SAMPLERS_BINDING_FIRST_INDEX + 8) uniform sampler SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT; layout(set = 0, binding = SAMPLERS_BINDING_FIRST_INDEX + 9) uniform sampler SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT; layout(set = 0, binding = SAMPLERS_BINDING_FIRST_INDEX + 10) uniform sampler SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT; -layout(set = 0, binding = SAMPLERS_BINDING_FIRST_INDEX + 11) uniform sampler SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT;
\ No newline at end of file +layout(set = 0, binding = SAMPLERS_BINDING_FIRST_INDEX + 11) uniform sampler SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT; diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index d1ff9fc362..3d294ca8cb 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -2025,7 +2025,7 @@ void LightStorage::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits for (int i = 0; i < 4; i++) { //clear subdivisions shadow_atlas->quadrants[i].shadows.clear(); - shadow_atlas->quadrants[i].shadows.resize(int64_t(1) << int64_t(shadow_atlas->quadrants[i].subdivision)); + shadow_atlas->quadrants[i].shadows.resize(int64_t(shadow_atlas->quadrants[i].subdivision * shadow_atlas->quadrants[i].subdivision)); } //erase shadow atlas reference from lights diff --git a/servers/rendering/renderer_rd/storage_rd/render_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_data_rd.h index 2f61899a18..3cd397b8ed 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_data_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_data_rd.h @@ -78,6 +78,9 @@ public: RenderingMethod::RenderInfo *render_info = nullptr; + /* Viewport data */ + bool transparent_bg = false; + /* Shadow data */ const RendererSceneRender::RenderShadowData *render_shadows = nullptr; int render_shadow_count = 0; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 76ff566b18..6e5e8f63e0 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -1457,6 +1457,23 @@ void TextureStorage::texture_set_detect_roughness_callback(RID p_texture, RS::Te } void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) { + List<RID> textures; + texture_owner.get_owned_list(&textures); + + for (List<RID>::Element *E = textures.front(); E; E = E->next()) { + Texture *t = texture_owner.get_or_null(E->get()); + if (!t) { + continue; + } + RS::TextureInfo tinfo; + tinfo.path = t->path; + tinfo.format = t->format; + tinfo.width = t->width; + tinfo.height = t->height; + tinfo.depth = t->depth; + tinfo.bytes = Image::get_image_data_size(t->width, t->height, t->format, t->mipmaps); + r_info->push_back(tinfo); + } } void TextureStorage::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { @@ -3042,6 +3059,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { texture_2d_placeholder_initialize(rt->texture); Texture *tex = get_texture(rt->texture); tex->is_render_target = true; + tex->path = "Render Target (Internal)"; } _clear_render_target(rt); @@ -3960,6 +3978,20 @@ RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_targ return rt->vrs_mode; } +void TextureStorage::render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_NULL(rt); + + rt->vrs_update_mode = p_mode; +} + +RS::ViewportVRSUpdateMode TextureStorage::render_target_get_vrs_update_mode(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_NULL_V(rt, RS::VIEWPORT_VRS_UPDATE_DISABLED); + + return rt->vrs_update_mode; +} + void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_NULL(rt); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 1304b284d5..704f5fb1bd 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -366,6 +366,7 @@ private: // VRS RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED; + RS::ViewportVRSUpdateMode vrs_update_mode = RS::VIEWPORT_VRS_UPDATE_ONCE; RID vrs_texture; // overridden textures @@ -746,6 +747,8 @@ public: virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override; virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override; + virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) override; + virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const override; virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override; virtual RID render_target_get_vrs_texture(RID p_render_target) const override; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 96c0479ac3..b02d3def88 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -958,6 +958,8 @@ void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_sh if (instance->mesh_instance.is_valid()) { RSG::mesh_storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight); } + + _instance_queue_update(instance, false, false); } void RendererSceneCull::instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material) { diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 31d5a9074c..884f8adb8c 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -85,7 +85,7 @@ Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports() } while (!nodes.is_empty()) { - const Viewport *node = nodes[0]; + const Viewport *node = nodes.front()->get(); nodes.pop_front(); for (int i = active_viewports.size() - 1; i >= 0; --i) { @@ -678,7 +678,7 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) { #endif // _3D_DISABLED if (Engine::get_singleton()->is_editor_hint()) { - set_default_clear_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color")); + RSG::texture_storage->set_default_clear_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color")); } if (sorted_active_viewports_dirty) { @@ -1450,6 +1450,13 @@ void RendererViewport::viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode _configure_3d_render_buffers(viewport); } +void RendererViewport::viewport_set_vrs_update_mode(RID p_viewport, RS::ViewportVRSUpdateMode p_mode) { + Viewport *viewport = viewport_owner.get_or_null(p_viewport); + ERR_FAIL_NULL(viewport); + + RSG::texture_storage->render_target_set_vrs_update_mode(viewport->render_target, p_mode); +} + void RendererViewport::viewport_set_vrs_texture(RID p_viewport, RID p_texture) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_NULL(viewport); @@ -1514,10 +1521,6 @@ void RendererViewport::handle_timestamp(String p_timestamp, uint64_t p_cpu_time, } } -void RendererViewport::set_default_clear_color(const Color &p_color) { - RSG::texture_storage->set_default_clear_color(p_color); -} - void RendererViewport::viewport_set_canvas_cull_mask(RID p_viewport, uint32_t p_canvas_cull_mask) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_NULL(viewport); diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index 5107398c54..b36fc7f57f 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -298,11 +298,11 @@ public: virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const; void viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode p_mode); + void viewport_set_vrs_update_mode(RID p_viewport, RS::ViewportVRSUpdateMode p_mode); void viewport_set_vrs_texture(RID p_viewport, RID p_texture); void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time); - void set_default_clear_color(const Color &p_color); void draw_viewports(bool p_swap_buffers); bool free(RID p_rid); diff --git a/servers/rendering/rendering_context_driver.h b/servers/rendering/rendering_context_driver.h index df1424da95..539b3814a0 100644 --- a/servers/rendering/rendering_context_driver.h +++ b/servers/rendering/rendering_context_driver.h @@ -73,10 +73,15 @@ public: DEVICE_TYPE_MAX = 0x5 }; + struct Workarounds { + bool avoid_compute_after_draw = false; + }; + struct Device { String name = "Unknown"; Vendor vendor = VENDOR_UNKNOWN; DeviceType type = DEVICE_TYPE_OTHER; + Workarounds workarounds; }; virtual ~RenderingContextDriver(); diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 962531c866..0227472d0e 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -671,9 +671,9 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture TextureFormat format = p_format; if (format.shareable_formats.size()) { - ERR_FAIL_COND_V_MSG(format.shareable_formats.find(format.format) == -1, RID(), + ERR_FAIL_COND_V_MSG(!format.shareable_formats.has(format.format), RID(), "If supplied a list of shareable formats, the current format must be present in the list"); - ERR_FAIL_COND_V_MSG(p_view.format_override != DATA_FORMAT_MAX && format.shareable_formats.find(p_view.format_override) == -1, RID(), + ERR_FAIL_COND_V_MSG(p_view.format_override != DATA_FORMAT_MAX && !format.shareable_formats.has(p_view.format_override), RID(), "If supplied a list of shareable formats, the current view format override must be present in the list"); } @@ -854,7 +854,7 @@ RID RenderingDevice::texture_create_shared(const TextureView &p_view, RID p_with } else { ERR_FAIL_INDEX_V(p_view.format_override, DATA_FORMAT_MAX, RID()); - ERR_FAIL_COND_V_MSG(texture.allowed_shared_formats.find(p_view.format_override) == -1, RID(), + ERR_FAIL_COND_V_MSG(!texture.allowed_shared_formats.has(p_view.format_override), RID(), "Format override is not in the list of allowed shareable formats for original texture."); tv.format = p_view.format_override; } @@ -984,7 +984,7 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view, } else { ERR_FAIL_INDEX_V(p_view.format_override, DATA_FORMAT_MAX, RID()); - ERR_FAIL_COND_V_MSG(texture.allowed_shared_formats.find(p_view.format_override) == -1, RID(), + ERR_FAIL_COND_V_MSG(!texture.allowed_shared_formats.has(p_view.format_override), RID(), "Format override is not in the list of allowed shareable formats for original texture."); tv.format = p_view.format_override; } @@ -3154,9 +3154,6 @@ Error RenderingDevice::screen_create(DisplayServer::WindowID p_screen) { RDD::SwapChainID swap_chain = driver->swap_chain_create(surface); ERR_FAIL_COND_V_MSG(swap_chain.id == 0, ERR_CANT_CREATE, "Unable to create swap chain."); - Error err = driver->swap_chain_resize(main_queue, swap_chain, _get_swap_chain_desired_count()); - ERR_FAIL_COND_V_MSG(err != OK, ERR_CANT_CREATE, "Unable to resize the new swap chain."); - screen_swap_chains[p_screen] = swap_chain; return OK; @@ -3335,12 +3332,15 @@ Error RenderingDevice::_draw_list_setup_framebuffer(Framebuffer *p_framebuffer, } Error RenderingDevice::_draw_list_render_pass_begin(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i p_viewport_offset, Point2i p_viewport_size, RDD::FramebufferID p_framebuffer_driver_id, RDD::RenderPassID p_render_pass) { - LocalVector<RDD::RenderPassClearValue> clear_values; - LocalVector<RDG::ResourceTracker *> resource_trackers; - LocalVector<RDG::ResourceUsage> resource_usages; + thread_local LocalVector<RDD::RenderPassClearValue> clear_values; + thread_local LocalVector<RDG::ResourceTracker *> resource_trackers; + thread_local LocalVector<RDG::ResourceUsage> resource_usages; bool uses_color = false; bool uses_depth = false; + clear_values.clear(); clear_values.resize(p_framebuffer->texture_ids.size()); + resource_trackers.clear(); + resource_usages.clear(); int clear_values_count = 0; { int color_index = 0; @@ -3451,9 +3451,9 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer, if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { // Check custom region. Rect2i viewport(viewport_offset, viewport_size); Rect2i regioni = p_region; - if (!(regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) && - ((regioni.position.x + regioni.size.x) <= (viewport.position.x + viewport.size.x)) && - ((regioni.position.y + regioni.size.y) <= (viewport.position.y + viewport.size.y))) { + if (!((regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) && + ((regioni.position.x + regioni.size.x) <= (viewport.position.x + viewport.size.x)) && + ((regioni.position.y + regioni.size.y) <= (viewport.position.y + viewport.size.y)))) { ERR_FAIL_V_MSG(INVALID_ID, "When supplying a custom region, it must be contained within the framebuffer rectangle"); } @@ -3774,13 +3774,13 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint #endif - // Bind descriptor sets. - +#ifdef DEBUG_ENABLED for (uint32_t i = 0; i < dl->state.set_count; i++) { if (dl->state.sets[i].pipeline_expected_format == 0) { - continue; // Nothing expected by this pipeline. + // Nothing expected by this pipeline. + continue; } -#ifdef DEBUG_ENABLED + if (dl->state.sets[i].pipeline_expected_format != dl->state.sets[i].uniform_set_format) { if (dl->state.sets[i].uniform_set_format == 0) { ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline."); @@ -3791,9 +3791,22 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(dl->state.pipeline_shader)); } } + } #endif - draw_graph.add_draw_list_uniform_set_prepare_for_use(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + + // Prepare descriptor sets if the API doesn't use pipeline barriers. + if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { + for (uint32_t i = 0; i < dl->state.set_count; i++) { + if (dl->state.sets[i].pipeline_expected_format == 0) { + // Nothing expected by this pipeline. + continue; + } + + draw_graph.add_draw_list_uniform_set_prepare_for_use(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i); + } } + + // Bind descriptor sets. for (uint32_t i = 0; i < dl->state.set_count; i++) { if (dl->state.sets[i].pipeline_expected_format == 0) { continue; // Nothing expected by this pipeline. @@ -3858,6 +3871,8 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint draw_graph.add_draw_list_draw(to_draw, p_instances); } + + dl->state.draw_count++; } void RenderingDevice::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) { @@ -4165,13 +4180,13 @@ void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_g #endif - // Bind descriptor sets. - +#ifdef DEBUG_ENABLED for (uint32_t i = 0; i < cl->state.set_count; i++) { if (cl->state.sets[i].pipeline_expected_format == 0) { - continue; // Nothing expected by this pipeline. + // Nothing expected by this pipeline. + continue; } -#ifdef DEBUG_ENABLED + if (cl->state.sets[i].pipeline_expected_format != cl->state.sets[i].uniform_set_format) { if (cl->state.sets[i].uniform_set_format == 0) { ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline."); @@ -4182,9 +4197,22 @@ void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_g ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader)); } } + } #endif - draw_graph.add_compute_list_uniform_set_prepare_for_use(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i); + + // Prepare descriptor sets if the API doesn't use pipeline barriers. + if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { + for (uint32_t i = 0; i < cl->state.set_count; i++) { + if (cl->state.sets[i].pipeline_expected_format == 0) { + // Nothing expected by this pipeline. + continue; + } + + draw_graph.add_compute_list_uniform_set_prepare_for_use(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i); + } } + + // Bind descriptor sets. for (uint32_t i = 0; i < cl->state.set_count; i++) { if (cl->state.sets[i].pipeline_expected_format == 0) { continue; // Nothing expected by this pipeline. @@ -4201,6 +4229,7 @@ void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_g } draw_graph.add_compute_list_dispatch(p_x_groups, p_y_groups, p_z_groups); + cl->state.dispatch_count++; } void RenderingDevice::compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads) { @@ -4258,16 +4287,16 @@ void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p #endif - // Bind descriptor sets. - +#ifdef DEBUG_ENABLED for (uint32_t i = 0; i < cl->state.set_count; i++) { if (cl->state.sets[i].pipeline_expected_format == 0) { - continue; // Nothing expected by this pipeline. + // Nothing expected by this pipeline. + continue; } -#ifdef DEBUG_ENABLED + if (cl->state.sets[i].pipeline_expected_format != cl->state.sets[i].uniform_set_format) { if (cl->state.sets[i].uniform_set_format == 0) { - ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline"); + ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline."); } else if (uniform_set_owner.owns(cl->state.sets[i].uniform_set)) { UniformSet *us = uniform_set_owner.get_or_null(cl->state.sets[i].uniform_set); ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader)); @@ -4275,9 +4304,22 @@ void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader)); } } + } #endif - draw_graph.add_compute_list_uniform_set_prepare_for_use(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i); + + // Prepare descriptor sets if the API doesn't use pipeline barriers. + if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) { + for (uint32_t i = 0; i < cl->state.set_count; i++) { + if (cl->state.sets[i].pipeline_expected_format == 0) { + // Nothing expected by this pipeline. + continue; + } + + draw_graph.add_compute_list_uniform_set_prepare_for_use(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i); + } } + + // Bind descriptor sets. for (uint32_t i = 0; i < cl->state.set_count; i++) { if (cl->state.sets[i].pipeline_expected_format == 0) { continue; // Nothing expected by this pipeline. @@ -4294,6 +4336,7 @@ void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p } draw_graph.add_compute_list_dispatch_indirect(buffer->driver_id, p_offset); + cl->state.dispatch_count++; if (buffer->draw_tracker != nullptr) { draw_graph.add_compute_list_usage(buffer->draw_tracker, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ); @@ -4694,6 +4737,10 @@ String RenderingDevice::get_device_api_name() const { return driver->get_api_name(); } +bool RenderingDevice::is_composite_alpha_supported() const { + return driver->is_composite_alpha_supported(main_queue); +} + String RenderingDevice::get_device_api_version() const { return driver->get_api_version(); } @@ -4873,25 +4920,78 @@ void RenderingDevice::_end_frame() { ERR_PRINT("Found open compute list at the end of the frame, this should never happen (further compute will likely not work)."); } - draw_graph.end(frames[frame].draw_command_buffer, RENDER_GRAPH_REORDER, RENDER_GRAPH_FULL_BARRIERS); driver->command_buffer_end(frames[frame].setup_command_buffer); - driver->command_buffer_end(frames[frame].draw_command_buffer); + + // The command buffer must be copied into a stack variable as the driver workarounds can change the command buffer in use. + RDD::CommandBufferID command_buffer = frames[frame].draw_command_buffer; + draw_graph.end(RENDER_GRAPH_REORDER, RENDER_GRAPH_FULL_BARRIERS, command_buffer, frames[frame].command_buffer_pool); + driver->command_buffer_end(command_buffer); driver->end_segment(); } void RenderingDevice::_execute_frame(bool p_present) { + // Check whether this frame should present the swap chains and in which queue. const bool frame_can_present = p_present && !frames[frame].swap_chains_to_present.is_empty(); const bool separate_present_queue = main_queue != present_queue; - const VectorView<RDD::SemaphoreID> execute_draw_semaphore = frame_can_present && separate_present_queue ? frames[frame].draw_semaphore : VectorView<RDD::SemaphoreID>(); - const VectorView<RDD::SwapChainID> execute_draw_swap_chains = frame_can_present && !separate_present_queue ? frames[frame].swap_chains_to_present : VectorView<RDD::SwapChainID>(); + thread_local LocalVector<RDD::SwapChainID> swap_chains; + swap_chains.clear(); + + // Execute the setup command buffer. driver->command_queue_execute_and_present(main_queue, {}, frames[frame].setup_command_buffer, frames[frame].setup_semaphore, {}, {}); - driver->command_queue_execute_and_present(main_queue, frames[frame].setup_semaphore, frames[frame].draw_command_buffer, execute_draw_semaphore, frames[frame].draw_fence, execute_draw_swap_chains); + + // Execute command buffers and use semaphores to wait on the execution of the previous one. Normally there's only one command buffer, + // but driver workarounds can force situations where there'll be more. + uint32_t command_buffer_count = 1; + RDG::CommandBufferPool &buffer_pool = frames[frame].command_buffer_pool; + if (buffer_pool.buffers_used > 0) { + command_buffer_count += buffer_pool.buffers_used; + buffer_pool.buffers_used = 0; + } + + RDD::SemaphoreID wait_semaphore = frames[frame].setup_semaphore; + for (uint32_t i = 0; i < command_buffer_count; i++) { + RDD::CommandBufferID command_buffer; + RDD::SemaphoreID signal_semaphore; + RDD::FenceID signal_fence; + if (i > 0) { + command_buffer = buffer_pool.buffers[i - 1]; + signal_semaphore = buffer_pool.semaphores[i - 1]; + } else { + command_buffer = frames[frame].draw_command_buffer; + signal_semaphore = frames[frame].draw_semaphore; + } + + bool signal_semaphore_valid; + if (i == (command_buffer_count - 1)) { + // This is the last command buffer, it should signal the fence. + signal_fence = frames[frame].draw_fence; + signal_semaphore_valid = false; + + if (frame_can_present && separate_present_queue) { + // The semaphore is required if the frame can be presented and a separate present queue is used. + signal_semaphore_valid = true; + } else if (frame_can_present) { + // Just present the swap chains as part of the last command execution. + swap_chains = frames[frame].swap_chains_to_present; + } + } else { + // Semaphores always need to be signaled if it's not the last command buffer. + signal_semaphore_valid = true; + } + + driver->command_queue_execute_and_present(main_queue, wait_semaphore, command_buffer, signal_semaphore_valid ? signal_semaphore : VectorView<RDD::SemaphoreID>(), signal_fence, swap_chains); + + // Make the next command buffer wait on the semaphore signaled by this one. + wait_semaphore = signal_semaphore; + } + + // Indicate the fence has been signaled so the next time the frame's contents need to be used, the CPU needs to wait on the work to be completed. frames[frame].draw_fence_signaled = true; if (frame_can_present) { if (separate_present_queue) { // Issue the presentation separately if the presentation queue is different from the main queue. - driver->command_queue_execute_and_present(present_queue, frames[frame].draw_semaphore, {}, {}, {}, frames[frame].swap_chains_to_present); + driver->command_queue_execute_and_present(present_queue, wait_semaphore, {}, {}, {}, frames[frame].swap_chains_to_present); } frames[frame].swap_chains_to_present.clear(); @@ -5040,6 +5140,9 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ frames[i].timestamp_cpu_result_values.resize(max_timestamp_query_elements); frames[i].timestamp_result_values.resize(max_timestamp_query_elements); frames[i].timestamp_result_count = 0; + + // Assign the main queue family and command pool to the command buffer pool. + frames[i].command_buffer_pool.pool = frames[i].command_pool; } // Start from frame count, so everything else is immediately old. @@ -5051,7 +5154,7 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ driver->command_buffer_begin(frames[0].draw_command_buffer); // Create draw graph and start it initialized as well. - draw_graph.initialize(driver, frames.size(), main_queue_family, SECONDARY_COMMAND_BUFFERS_PER_FRAME); + draw_graph.initialize(driver, device, frames.size(), main_queue_family, SECONDARY_COMMAND_BUFFERS_PER_FRAME); draw_graph.begin(); for (uint32_t i = 0; i < frames.size(); i++) { @@ -5206,8 +5309,8 @@ void RenderingDevice::_free_rids(T &p_owner, const char *p_type) { } void RenderingDevice::capture_timestamp(const String &p_name) { - ERR_FAIL_COND_MSG(draw_list != nullptr, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name); - ERR_FAIL_COND_MSG(compute_list != nullptr, "Capturing timestamps during compute list creation is not allowed. Offending timestamp was: " + p_name); + ERR_FAIL_COND_MSG(draw_list != nullptr && draw_list->state.draw_count > 0, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name); + ERR_FAIL_COND_MSG(compute_list != nullptr && compute_list->state.dispatch_count > 0, "Capturing timestamps during compute list creation is not allowed. Offending timestamp was: " + p_name); ERR_FAIL_COND(frames[frame].timestamp_count >= max_timestamp_query_elements); draw_graph.add_capture_timestamp(frames[frame].timestamp_pool, frames[frame].timestamp_count); @@ -5384,6 +5487,11 @@ void RenderingDevice::finalize() { driver->semaphore_free(frames[i].setup_semaphore); driver->semaphore_free(frames[i].draw_semaphore); driver->fence_free(frames[i].draw_fence); + + RDG::CommandBufferPool &buffer_pool = frames[i].command_buffer_pool; + for (uint32_t j = 0; j < buffer_pool.buffers.size(); j++) { + driver->semaphore_free(buffer_pool.semaphores[j]); + } } if (pipeline_cache_enabled) { diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 9a898a2fca..d0fa4ab1fa 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -797,6 +797,8 @@ private: #endif public: + RenderingContextDriver *get_context_driver() const { return context; } + const RDD::Capabilities &get_device_capabilities() const { return driver->get_capabilities(); } bool has_feature(const Features p_feature) const; @@ -1046,6 +1048,7 @@ private: uint32_t pipeline_shader_layout_hash = 0; RID vertex_array; RID index_array; + uint32_t draw_count = 0; } state; #ifdef DEBUG_ENABLED @@ -1147,6 +1150,7 @@ private: uint32_t local_group_size[3] = { 0, 0, 0 }; uint8_t push_constant_data[MAX_PUSH_CONSTANT_SIZE] = {}; uint32_t push_constant_size = 0; + uint32_t dispatch_count = 0; } state; #ifdef DEBUG_ENABLED @@ -1259,6 +1263,9 @@ private: // Swap chains prepared for drawing during the frame that must be presented. LocalVector<RDD::SwapChainID> swap_chains_to_present; + // Extra command buffer pool used for driver workarounds. + RDG::CommandBufferPool command_buffer_pool; + struct Timestamp { String description; uint64_t value = 0; @@ -1353,6 +1360,8 @@ public: String get_device_api_version() const; String get_device_pipeline_cache_uuid() const; + bool is_composite_alpha_supported() const; + uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0); static RenderingDevice *get_singleton(); diff --git a/servers/rendering/rendering_device_commons.h b/servers/rendering/rendering_device_commons.h index 28d641c879..918bf9b834 100644 --- a/servers/rendering/rendering_device_commons.h +++ b/servers/rendering/rendering_device_commons.h @@ -810,6 +810,8 @@ public: LIMIT_SUBGROUP_OPERATIONS, LIMIT_VRS_TEXEL_WIDTH, LIMIT_VRS_TEXEL_HEIGHT, + LIMIT_VRS_MAX_FRAGMENT_WIDTH, + LIMIT_VRS_MAX_FRAGMENT_HEIGHT, }; enum Features { diff --git a/servers/rendering/rendering_device_driver.h b/servers/rendering/rendering_device_driver.h index e9464ba321..f9a861426a 100644 --- a/servers/rendering/rendering_device_driver.h +++ b/servers/rendering/rendering_device_driver.h @@ -769,6 +769,8 @@ public: virtual String get_pipeline_cache_uuid() const = 0; virtual const Capabilities &get_capabilities() const = 0; + virtual bool is_composite_alpha_supported(CommandQueueID p_queue) const { return false; } + /******************/ virtual ~RenderingDeviceDriver(); diff --git a/servers/rendering/rendering_device_graph.cpp b/servers/rendering/rendering_device_graph.cpp index b04f2ebbaa..c7de5c67cb 100644 --- a/servers/rendering/rendering_device_graph.cpp +++ b/servers/rendering/rendering_device_graph.cpp @@ -753,71 +753,96 @@ void RenderingDeviceGraph::_wait_for_secondary_command_buffer_tasks() { } } -void RenderingDeviceGraph::_run_render_commands(RDD::CommandBufferID p_command_buffer, int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level) { +void RenderingDeviceGraph::_run_render_commands(int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool, int32_t &r_current_label_index, int32_t &r_current_label_level) { for (uint32_t i = 0; i < p_sorted_commands_count; i++) { const uint32_t command_index = p_sorted_commands[i].index; const uint32_t command_data_offset = command_data_offsets[command_index]; const RecordedCommand *command = reinterpret_cast<RecordedCommand *>(&command_data[command_data_offset]); - _run_label_command_change(p_command_buffer, command->label_index, p_level, false, true, &p_sorted_commands[i], p_sorted_commands_count - i, r_current_label_index, r_current_label_level); + _run_label_command_change(r_command_buffer, command->label_index, p_level, false, true, &p_sorted_commands[i], p_sorted_commands_count - i, r_current_label_index, r_current_label_level); switch (command->type) { case RecordedCommand::TYPE_BUFFER_CLEAR: { const RecordedBufferClearCommand *buffer_clear_command = reinterpret_cast<const RecordedBufferClearCommand *>(command); - driver->command_clear_buffer(p_command_buffer, buffer_clear_command->buffer, buffer_clear_command->offset, buffer_clear_command->size); + driver->command_clear_buffer(r_command_buffer, buffer_clear_command->buffer, buffer_clear_command->offset, buffer_clear_command->size); } break; case RecordedCommand::TYPE_BUFFER_COPY: { const RecordedBufferCopyCommand *buffer_copy_command = reinterpret_cast<const RecordedBufferCopyCommand *>(command); - driver->command_copy_buffer(p_command_buffer, buffer_copy_command->source, buffer_copy_command->destination, buffer_copy_command->region); + driver->command_copy_buffer(r_command_buffer, buffer_copy_command->source, buffer_copy_command->destination, buffer_copy_command->region); } break; case RecordedCommand::TYPE_BUFFER_GET_DATA: { const RecordedBufferGetDataCommand *buffer_get_data_command = reinterpret_cast<const RecordedBufferGetDataCommand *>(command); - driver->command_copy_buffer(p_command_buffer, buffer_get_data_command->source, buffer_get_data_command->destination, buffer_get_data_command->region); + driver->command_copy_buffer(r_command_buffer, buffer_get_data_command->source, buffer_get_data_command->destination, buffer_get_data_command->region); } break; case RecordedCommand::TYPE_BUFFER_UPDATE: { const RecordedBufferUpdateCommand *buffer_update_command = reinterpret_cast<const RecordedBufferUpdateCommand *>(command); const RecordedBufferCopy *command_buffer_copies = buffer_update_command->buffer_copies(); for (uint32_t j = 0; j < buffer_update_command->buffer_copies_count; j++) { - driver->command_copy_buffer(p_command_buffer, command_buffer_copies[j].source, buffer_update_command->destination, command_buffer_copies[j].region); + driver->command_copy_buffer(r_command_buffer, command_buffer_copies[j].source, buffer_update_command->destination, command_buffer_copies[j].region); } } break; case RecordedCommand::TYPE_COMPUTE_LIST: { + if (device.workarounds.avoid_compute_after_draw && workarounds_state.draw_list_found) { + // Avoid compute after draw workaround. Refer to the comment that enables this in the Vulkan driver for more information. + workarounds_state.draw_list_found = false; + + // Create or reuse a command buffer and finish recording the current one. + driver->command_buffer_end(r_command_buffer); + + while (r_command_buffer_pool.buffers_used >= r_command_buffer_pool.buffers.size()) { + RDD::CommandBufferID command_buffer = driver->command_buffer_create(r_command_buffer_pool.pool); + RDD::SemaphoreID command_semaphore = driver->semaphore_create(); + r_command_buffer_pool.buffers.push_back(command_buffer); + r_command_buffer_pool.semaphores.push_back(command_semaphore); + } + + // Start recording on the next usable command buffer from the pool. + uint32_t command_buffer_index = r_command_buffer_pool.buffers_used++; + r_command_buffer = r_command_buffer_pool.buffers[command_buffer_index]; + driver->command_buffer_begin(r_command_buffer); + } + const RecordedComputeListCommand *compute_list_command = reinterpret_cast<const RecordedComputeListCommand *>(command); - _run_compute_list_command(p_command_buffer, compute_list_command->instruction_data(), compute_list_command->instruction_data_size); + _run_compute_list_command(r_command_buffer, compute_list_command->instruction_data(), compute_list_command->instruction_data_size); } break; case RecordedCommand::TYPE_DRAW_LIST: { + if (device.workarounds.avoid_compute_after_draw) { + // Indicate that a draw list was encountered for the workaround. + workarounds_state.draw_list_found = true; + } + const RecordedDrawListCommand *draw_list_command = reinterpret_cast<const RecordedDrawListCommand *>(command); const VectorView clear_values(draw_list_command->clear_values(), draw_list_command->clear_values_count); - driver->command_begin_render_pass(p_command_buffer, draw_list_command->render_pass, draw_list_command->framebuffer, draw_list_command->command_buffer_type, draw_list_command->region, clear_values); - _run_draw_list_command(p_command_buffer, draw_list_command->instruction_data(), draw_list_command->instruction_data_size); - driver->command_end_render_pass(p_command_buffer); + driver->command_begin_render_pass(r_command_buffer, draw_list_command->render_pass, draw_list_command->framebuffer, draw_list_command->command_buffer_type, draw_list_command->region, clear_values); + _run_draw_list_command(r_command_buffer, draw_list_command->instruction_data(), draw_list_command->instruction_data_size); + driver->command_end_render_pass(r_command_buffer); } break; case RecordedCommand::TYPE_TEXTURE_CLEAR: { const RecordedTextureClearCommand *texture_clear_command = reinterpret_cast<const RecordedTextureClearCommand *>(command); - driver->command_clear_color_texture(p_command_buffer, texture_clear_command->texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_clear_command->color, texture_clear_command->range); + driver->command_clear_color_texture(r_command_buffer, texture_clear_command->texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_clear_command->color, texture_clear_command->range); } break; case RecordedCommand::TYPE_TEXTURE_COPY: { const RecordedTextureCopyCommand *texture_copy_command = reinterpret_cast<const RecordedTextureCopyCommand *>(command); - driver->command_copy_texture(p_command_buffer, texture_copy_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_copy_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_copy_command->region); + driver->command_copy_texture(r_command_buffer, texture_copy_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_copy_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_copy_command->region); } break; case RecordedCommand::TYPE_TEXTURE_GET_DATA: { const RecordedTextureGetDataCommand *texture_get_data_command = reinterpret_cast<const RecordedTextureGetDataCommand *>(command); const VectorView<RDD::BufferTextureCopyRegion> command_buffer_texture_copy_regions_view(texture_get_data_command->buffer_texture_copy_regions(), texture_get_data_command->buffer_texture_copy_regions_count); - driver->command_copy_texture_to_buffer(p_command_buffer, texture_get_data_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_get_data_command->to_buffer, command_buffer_texture_copy_regions_view); + driver->command_copy_texture_to_buffer(r_command_buffer, texture_get_data_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_get_data_command->to_buffer, command_buffer_texture_copy_regions_view); } break; case RecordedCommand::TYPE_TEXTURE_RESOLVE: { const RecordedTextureResolveCommand *texture_resolve_command = reinterpret_cast<const RecordedTextureResolveCommand *>(command); - driver->command_resolve_texture(p_command_buffer, texture_resolve_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_resolve_command->src_layer, texture_resolve_command->src_mipmap, texture_resolve_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_resolve_command->dst_layer, texture_resolve_command->dst_mipmap); + driver->command_resolve_texture(r_command_buffer, texture_resolve_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_resolve_command->src_layer, texture_resolve_command->src_mipmap, texture_resolve_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_resolve_command->dst_layer, texture_resolve_command->dst_mipmap); } break; case RecordedCommand::TYPE_TEXTURE_UPDATE: { const RecordedTextureUpdateCommand *texture_update_command = reinterpret_cast<const RecordedTextureUpdateCommand *>(command); const RecordedBufferToTextureCopy *command_buffer_to_texture_copies = texture_update_command->buffer_to_texture_copies(); for (uint32_t j = 0; j < texture_update_command->buffer_to_texture_copies_count; j++) { - driver->command_copy_buffer_to_texture(p_command_buffer, command_buffer_to_texture_copies[j].from_buffer, texture_update_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, command_buffer_to_texture_copies[j].region); + driver->command_copy_buffer_to_texture(r_command_buffer, command_buffer_to_texture_copies[j].from_buffer, texture_update_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, command_buffer_to_texture_copies[j].region); } } break; case RecordedCommand::TYPE_CAPTURE_TIMESTAMP: { const RecordedCaptureTimestampCommand *texture_capture_timestamp_command = reinterpret_cast<const RecordedCaptureTimestampCommand *>(command); - driver->command_timestamp_write(p_command_buffer, texture_capture_timestamp_command->pool, texture_capture_timestamp_command->index); + driver->command_timestamp_write(r_command_buffer, texture_capture_timestamp_command->pool, texture_capture_timestamp_command->index); } break; default: { DEV_ASSERT(false && "Unknown recorded command type."); @@ -1229,8 +1254,9 @@ void RenderingDeviceGraph::_print_compute_list(const uint8_t *p_instruction_data } } -void RenderingDeviceGraph::initialize(RDD *p_driver, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame) { +void RenderingDeviceGraph::initialize(RDD *p_driver, RenderingContextDriver::Device p_device, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame) { driver = p_driver; + device = p_device; frames.resize(p_frame_count); for (uint32_t i = 0; i < p_frame_count; i++) { @@ -1805,7 +1831,7 @@ void RenderingDeviceGraph::end_label() { command_label_index = -1; } -void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reorder_commands, bool p_full_barriers) { +void RenderingDeviceGraph::end(bool p_reorder_commands, bool p_full_barriers, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool) { if (command_count == 0) { // No commands have been logged, do nothing. return; @@ -1919,7 +1945,12 @@ void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reo if (command_count > 0) { int32_t current_label_index = -1; int32_t current_label_level = -1; - _run_label_command_change(p_command_buffer, -1, -1, true, true, nullptr, 0, current_label_index, current_label_level); + _run_label_command_change(r_command_buffer, -1, -1, true, true, nullptr, 0, current_label_index, current_label_level); + + if (device.workarounds.avoid_compute_after_draw) { + // Reset the state of the workaround. + workarounds_state.draw_list_found = false; + } if (p_reorder_commands) { #if PRINT_RENDER_GRAPH @@ -1946,8 +1977,8 @@ void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reo RecordedCommandSort *level_command_ptr = &commands_sorted[current_level_start]; uint32_t level_command_count = i - current_level_start; _boost_priority_for_render_commands(level_command_ptr, level_command_count, boosted_priority); - _group_barriers_for_render_commands(p_command_buffer, level_command_ptr, level_command_count, p_full_barriers); - _run_render_commands(p_command_buffer, current_level, level_command_ptr, level_command_count, current_label_index, current_label_level); + _group_barriers_for_render_commands(r_command_buffer, level_command_ptr, level_command_count, p_full_barriers); + _run_render_commands(current_level, level_command_ptr, level_command_count, r_command_buffer, r_command_buffer_pool, current_label_index, current_label_level); current_level = commands_sorted[i].level; current_level_start = i; } @@ -1956,20 +1987,20 @@ void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reo RecordedCommandSort *level_command_ptr = &commands_sorted[current_level_start]; uint32_t level_command_count = command_count - current_level_start; _boost_priority_for_render_commands(level_command_ptr, level_command_count, boosted_priority); - _group_barriers_for_render_commands(p_command_buffer, level_command_ptr, level_command_count, p_full_barriers); - _run_render_commands(p_command_buffer, current_level, level_command_ptr, level_command_count, current_label_index, current_label_level); + _group_barriers_for_render_commands(r_command_buffer, level_command_ptr, level_command_count, p_full_barriers); + _run_render_commands(current_level, level_command_ptr, level_command_count, r_command_buffer, r_command_buffer_pool, current_label_index, current_label_level); #if PRINT_RENDER_GRAPH print_line("COMMANDS", command_count, "LEVELS", current_level + 1); #endif } else { for (uint32_t i = 0; i < command_count; i++) { - _group_barriers_for_render_commands(p_command_buffer, &commands_sorted[i], 1, p_full_barriers); - _run_render_commands(p_command_buffer, i, &commands_sorted[i], 1, current_label_index, current_label_level); + _group_barriers_for_render_commands(r_command_buffer, &commands_sorted[i], 1, p_full_barriers); + _run_render_commands(i, &commands_sorted[i], 1, r_command_buffer, r_command_buffer_pool, current_label_index, current_label_level); } } - _run_label_command_change(p_command_buffer, -1, -1, true, false, nullptr, 0, current_label_index, current_label_level); + _run_label_command_change(r_command_buffer, -1, -1, true, false, nullptr, 0, current_label_index, current_label_level); #if PRINT_COMMAND_RECORDING print_line(vformat("Recorded %d commands", command_count)); diff --git a/servers/rendering/rendering_device_graph.h b/servers/rendering/rendering_device_graph.h index 3bc63bb297..a96382e0cc 100644 --- a/servers/rendering/rendering_device_graph.h +++ b/servers/rendering/rendering_device_graph.h @@ -184,6 +184,20 @@ public: } }; + struct CommandBufferPool { + // Provided by RenderingDevice. + RDD::CommandPoolID pool; + + // Created internally by RenderingDeviceGraph. + LocalVector<RDD::CommandBufferID> buffers; + LocalVector<RDD::SemaphoreID> semaphores; + uint32_t buffers_used = 0; + }; + + struct WorkaroundsState { + bool draw_list_found = false; + }; + private: struct InstructionList { LocalVector<uint8_t> data; @@ -560,6 +574,7 @@ private: }; RDD *driver = nullptr; + RenderingContextDriver::Device device; int64_t tracking_frame = 0; LocalVector<uint8_t> command_data; LocalVector<uint32_t> command_data_offsets; @@ -582,6 +597,7 @@ private: bool command_synchronization_pending = false; BarrierGroup barrier_group; bool driver_honors_barriers = false; + WorkaroundsState workarounds_state; TightLocalVector<Frame> frames; uint32_t frame = 0; @@ -608,7 +624,7 @@ private: void _run_draw_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size); void _run_secondary_command_buffer_task(const SecondaryCommandBuffer *p_secondary); void _wait_for_secondary_command_buffer_tasks(); - void _run_render_commands(RDD::CommandBufferID p_command_buffer, int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level); + void _run_render_commands(int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool, int32_t &r_current_label_index, int32_t &r_current_label_level); void _run_label_command_change(RDD::CommandBufferID p_command_buffer, int32_t p_new_label_index, int32_t p_new_level, bool p_ignore_previous_value, bool p_use_label_for_empty, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level); void _boost_priority_for_render_commands(RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, uint32_t &r_boosted_priority); void _group_barriers_for_render_commands(RDD::CommandBufferID p_command_buffer, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, bool p_full_memory_barrier); @@ -619,7 +635,7 @@ private: public: RenderingDeviceGraph(); ~RenderingDeviceGraph(); - void initialize(RDD *p_driver, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame); + void initialize(RDD *p_driver, RenderingContextDriver::Device p_device, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame); void finalize(); void begin(); void add_buffer_clear(RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_offset, uint32_t p_size); @@ -664,7 +680,7 @@ public: void add_synchronization(); void begin_label(const String &p_label_name, const Color &p_color); void end_label(); - void end(RDD::CommandBufferID p_command_buffer, bool p_reorder_commands, bool p_full_barriers); + void end(bool p_reorder_commands, bool p_full_barriers, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool); static ResourceTracker *resource_tracker_create(); static void resource_tracker_free(ResourceTracker *tracker); }; diff --git a/servers/rendering/rendering_light_culler.cpp b/servers/rendering/rendering_light_culler.cpp index 0889898f0b..8dc2d85bdf 100644 --- a/servers/rendering/rendering_light_culler.cpp +++ b/servers/rendering/rendering_light_culler.cpp @@ -279,9 +279,11 @@ bool RenderingLightCuller::add_light_camera_planes_directional(LightCullPlanes & // Create a third point from the light direction. Vector3 pt2 = pt0 - p_light_source.dir; - // Create plane from 3 points. - Plane p(pt0, pt1, pt2); - r_cull_planes.add_cull_plane(p); + if (!_is_colinear_tri(pt0, pt1, pt2)) { + // Create plane from 3 points. + Plane p(pt0, pt1, pt2); + r_cull_planes.add_cull_plane(p); + } } // Last to 0 edge. @@ -295,9 +297,11 @@ bool RenderingLightCuller::add_light_camera_planes_directional(LightCullPlanes & // Create a third point from the light direction. Vector3 pt2 = pt0 - p_light_source.dir; - // Create plane from 3 points. - Plane p(pt0, pt1, pt2); - r_cull_planes.add_cull_plane(p); + if (!_is_colinear_tri(pt0, pt1, pt2)) { + // Create plane from 3 points. + Plane p(pt0, pt1, pt2); + r_cull_planes.add_cull_plane(p); + } } #ifdef LIGHT_CULLER_DEBUG_LOGGING diff --git a/servers/rendering/rendering_light_culler.h b/servers/rendering/rendering_light_culler.h index 0bf975430b..b0437d2310 100644 --- a/servers/rendering/rendering_light_culler.h +++ b/servers/rendering/rendering_light_culler.h @@ -181,14 +181,14 @@ private: } // Prevent divide by zero. - if (lc > 0.00001f) { + if (lc > 0.001f) { // If the summed length of the smaller two // sides is close to the length of the longest side, // the points are colinear, and the triangle is near degenerate. float ld = ((la + lb) - lc) / lc; // ld will be close to zero for colinear tris. - return ld < 0.00001f; + return ld < 0.001f; } // Don't create planes from tiny triangles, diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 7e5ccee0e3..51ff009eaf 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -69,8 +69,6 @@ void RenderingServerDefault::request_frame_drawn_callback(const Callable &p_call } void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { - changes = 0; - RSG::rasterizer->begin_frame(frame_step); TIMESTAMP_BEGIN() @@ -102,19 +100,11 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { RSG::canvas->update_visibility_notifiers(); RSG::scene->update_visibility_notifiers(); - while (frame_drawn_callbacks.front()) { - Callable c = frame_drawn_callbacks.front()->get(); - Variant result; - Callable::CallError ce; - c.callp(nullptr, 0, result, ce); - if (ce.error != Callable::CallError::CALL_OK) { - String err = Variant::get_callable_error_text(c, nullptr, 0, ce); - ERR_PRINT("Error calling frame drawn function: " + err); - } - - frame_drawn_callbacks.pop_front(); + if (create_thread) { + callable_mp(this, &RenderingServerDefault::_run_post_draw_steps).call_deferred(); + } else { + _run_post_draw_steps(); } - RS::get_singleton()->emit_signal(SNAME("frame_post_draw")); if (RSG::utilities->get_captured_timestamps_count()) { Vector<FrameProfileArea> new_profile; @@ -194,6 +184,23 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { RSG::utilities->update_memory_info(); } +void RenderingServerDefault::_run_post_draw_steps() { + while (frame_drawn_callbacks.front()) { + Callable c = frame_drawn_callbacks.front()->get(); + Variant result; + Callable::CallError ce; + c.callp(nullptr, 0, result, ce); + if (ce.error != Callable::CallError::CALL_OK) { + String err = Variant::get_callable_error_text(c, nullptr, 0, ce); + ERR_PRINT("Error calling frame drawn function: " + err); + } + + frame_drawn_callbacks.pop_front(); + } + + emit_signal(SNAME("frame_post_draw")); +} + double RenderingServerDefault::get_frame_setup_time_cpu() const { return frame_setup_time; } @@ -203,7 +210,25 @@ bool RenderingServerDefault::has_changed() const { } void RenderingServerDefault::_init() { + RSG::threaded = create_thread; + + RSG::canvas = memnew(RendererCanvasCull); + RSG::viewport = memnew(RendererViewport); + RendererSceneCull *sr = memnew(RendererSceneCull); + RSG::camera_attributes = memnew(RendererCameraAttributes); + RSG::scene = sr; + RSG::rasterizer = RendererCompositor::create(); + RSG::utilities = RSG::rasterizer->get_utilities(); RSG::rasterizer->initialize(); + RSG::light_storage = RSG::rasterizer->get_light_storage(); + RSG::material_storage = RSG::rasterizer->get_material_storage(); + RSG::mesh_storage = RSG::rasterizer->get_mesh_storage(); + RSG::particles_storage = RSG::rasterizer->get_particles_storage(); + RSG::texture_storage = RSG::rasterizer->get_texture_storage(); + RSG::gi = RSG::rasterizer->get_gi(); + RSG::fog = RSG::rasterizer->get_fog(); + RSG::canvas_render = RSG::rasterizer->get_canvas(); + sr->set_scene_render(RSG::rasterizer->get_scene()); } void RenderingServerDefault::_finish() { @@ -212,26 +237,38 @@ void RenderingServerDefault::_finish() { } RSG::canvas->finalize(); + memdelete(RSG::canvas); RSG::rasterizer->finalize(); + memdelete(RSG::viewport); + memdelete(RSG::rasterizer); + memdelete(RSG::scene); + memdelete(RSG::camera_attributes); } void RenderingServerDefault::init() { if (create_thread) { print_verbose("RenderingServerWrapMT: Starting render thread"); DisplayServer::get_singleton()->release_rendering_thread(); - server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &RenderingServerDefault::_thread_loop), true); + WorkerThreadPool::TaskID tid = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &RenderingServerDefault::_thread_loop), true); + command_queue.set_pump_task_id(tid); + command_queue.push(this, &RenderingServerDefault::_assign_mt_ids, tid); + command_queue.push_and_sync(this, &RenderingServerDefault::_init); + DEV_ASSERT(server_task_id == tid); } else { + server_thread = Thread::MAIN_ID; _init(); } } void RenderingServerDefault::finish() { if (create_thread) { + command_queue.push(this, &RenderingServerDefault::_finish); command_queue.push(this, &RenderingServerDefault::_thread_exit); if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) { WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id); server_task_id = WorkerThreadPool::INVALID_TASK_ID; } + server_thread = Thread::MAIN_ID; } else { _finish(); } @@ -268,17 +305,12 @@ Vector<RenderingServer::FrameProfileArea> RenderingServerDefault::get_frame_prof /* TESTING */ -void RenderingServerDefault::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) { - redraw_request(); - RSG::rasterizer->set_boot_image(p_image, p_color, p_scale, p_use_filter); -} - Color RenderingServerDefault::get_default_clear_color() { return RSG::texture_storage->get_default_clear_color(); } void RenderingServerDefault::set_default_clear_color(const Color &p_color) { - RSG::viewport->set_default_clear_color(p_color); + RSG::texture_storage->set_default_clear_color(p_color); } #ifndef DISABLE_DEPRECATED @@ -327,29 +359,23 @@ Size2i RenderingServerDefault::get_maximum_viewport_size() const { } } -void RenderingServerDefault::_thread_exit() { - exit = true; +void RenderingServerDefault::_assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id) { + server_thread = Thread::get_caller_id(); + server_task_id = p_pump_task_id; } -void RenderingServerDefault::_thread_draw(bool p_swap_buffers, double frame_step) { - _draw(p_swap_buffers, frame_step); +void RenderingServerDefault::_thread_exit() { + exit = true; } void RenderingServerDefault::_thread_loop() { - server_thread = Thread::get_caller_id(); - DisplayServer::get_singleton()->gl_window_make_current(DisplayServer::MAIN_WINDOW_ID); // Move GL to this thread. - _init(); - command_queue.set_pump_task_id(server_task_id); while (!exit) { WorkerThreadPool::get_singleton()->yield(); command_queue.flush_all(); } - command_queue.flush_all(); - - _finish(); DisplayServer::get_singleton()->release_rendering_thread(); } @@ -366,7 +392,9 @@ void RenderingServerDefault::set_physics_interpolation_enabled(bool p_enabled) { /* EVENT QUEUING */ void RenderingServerDefault::sync() { - if (!create_thread) { + if (create_thread) { + command_queue.sync(); + } else { command_queue.flush_all(); // Flush all pending from other threads. } } @@ -375,8 +403,9 @@ void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) { ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Manually triggering the draw function from the RenderingServer can only be done on the main thread. Call this function from the main thread or use call_deferred()."); // Needs to be done before changes is reset to 0, to not force the editor to redraw. RS::get_singleton()->emit_signal(SNAME("frame_pre_draw")); + changes = 0; if (create_thread) { - command_queue.push(this, &RenderingServerDefault::_thread_draw, p_swap_buffers, frame_step); + command_queue.push(this, &RenderingServerDefault::_draw, p_swap_buffers, frame_step); } else { _draw(p_swap_buffers, frame_step); } @@ -390,36 +419,7 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) { RenderingServer::init(); create_thread = p_create_thread; - if (!create_thread) { - server_thread = Thread::MAIN_ID; - } - - RSG::threaded = create_thread; - - RSG::canvas = memnew(RendererCanvasCull); - RSG::viewport = memnew(RendererViewport); - RendererSceneCull *sr = memnew(RendererSceneCull); - RSG::camera_attributes = memnew(RendererCameraAttributes); - RSG::scene = sr; - RSG::rasterizer = RendererCompositor::create(); - RSG::utilities = RSG::rasterizer->get_utilities(); - RSG::light_storage = RSG::rasterizer->get_light_storage(); - RSG::material_storage = RSG::rasterizer->get_material_storage(); - RSG::mesh_storage = RSG::rasterizer->get_mesh_storage(); - RSG::particles_storage = RSG::rasterizer->get_particles_storage(); - RSG::texture_storage = RSG::rasterizer->get_texture_storage(); - RSG::gi = RSG::rasterizer->get_gi(); - RSG::fog = RSG::rasterizer->get_fog(); - RSG::canvas_render = RSG::rasterizer->get_canvas(); - sr->set_scene_render(RSG::rasterizer->get_scene()); - - frame_profile_frame = 0; } RenderingServerDefault::~RenderingServerDefault() { - memdelete(RSG::canvas); - memdelete(RSG::viewport); - memdelete(RSG::rasterizer); - memdelete(RSG::scene); - memdelete(RSG::camera_attributes); } diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index e0049e3fa4..164ec3cc09 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -63,7 +63,7 @@ class RenderingServerDefault : public RenderingServer { static void _changes_changed() {} - uint64_t frame_profile_frame; + uint64_t frame_profile_frame = 0; Vector<FrameProfileArea> frame_profile; double frame_setup_time = 0; @@ -76,18 +76,17 @@ class RenderingServerDefault : public RenderingServer { mutable CommandQueueMT command_queue; - void _thread_loop(); - - Thread::ID server_thread = Thread::UNASSIGNED_ID; + Thread::ID server_thread = Thread::MAIN_ID; WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID; bool exit = false; bool create_thread = false; - void _thread_draw(bool p_swap_buffers, double frame_step); - + void _assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id); void _thread_exit(); + void _thread_loop(); void _draw(bool p_swap_buffers, double frame_step); + void _run_post_draw_steps(); void _init(); void _finish(); @@ -672,6 +671,7 @@ public: FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID) FUNC2(viewport_set_vrs_mode, RID, ViewportVRSMode) + FUNC2(viewport_set_vrs_update_mode, RID, ViewportVRSUpdateMode) FUNC2(viewport_set_vrs_texture, RID, RID) /* COMPOSITOR EFFECT */ @@ -885,9 +885,9 @@ public: FUNC6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool) FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool) - FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float) - FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &) - FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) + FUNC5(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool) + FUNC4(canvas_item_add_rect, RID, const Rect2 &, const Color &, bool) + FUNC5(canvas_item_add_circle, RID, const Point2 &, float, const Color &, bool) FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool) FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool) FUNC8(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float, float) @@ -997,9 +997,22 @@ public: FUNC1(global_shader_parameters_load_settings, bool) FUNC0(global_shader_parameters_clear) + /* COMPOSITOR */ + #undef server_name #undef ServerName +#define ServerName RendererCompositor +#define server_name RSG::rasterizer + + FUNC4S(set_boot_image, const Ref<Image> &, const Color &, bool, bool) + /* STATUS INFORMATION */ + +#undef server_name +#undef ServerName + + /* UTILITIES */ + #define ServerName RendererUtilities #define server_name RSG::utilities FUNC0RC(String, get_video_adapter_name) @@ -1055,7 +1068,7 @@ public: virtual void call_on_render_thread(const Callable &p_callable) override { if (Thread::get_caller_id() == server_thread) { command_queue.flush_if_pending(); - _call_on_render_thread(p_callable); + p_callable.call(); } else { command_queue.push(this, &RenderingServerDefault::_call_on_render_thread, p_callable); } @@ -1065,7 +1078,6 @@ public: virtual double get_frame_setup_time_cpu() const override; - virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override; virtual Color get_default_clear_color() override; virtual void set_default_clear_color(const Color &p_color) override; diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 2b49d42f9e..a4ee33ecc0 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -362,7 +362,7 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str } header += _constr(fnode->arguments[i].is_const); if (fnode->arguments[i].type == SL::TYPE_STRUCT) { - header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name); + header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].struct_name) + " " + _mkid(fnode->arguments[i].name); } else { header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name); } @@ -479,8 +479,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene struct_code += _mkid(pnode->vstructs[i].name); struct_code += " "; struct_code += "{\n"; - for (int j = 0; j < st->members.size(); j++) { - SL::MemberNode *m = st->members[j]; + for (SL::MemberNode *m : st->members) { if (m->datatype == SL::TYPE_STRUCT) { struct_code += _mkid(m->struct_name); } else { @@ -744,7 +743,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene gcode += _constr(true); gcode += _prestr(cnode.precision, ShaderLanguage::is_float_type(cnode.type)); if (cnode.type == SL::TYPE_STRUCT) { - gcode += _mkid(cnode.type_str); + gcode += _mkid(cnode.struct_name); } else { gcode += _typestr(cnode.type); } @@ -807,10 +806,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene code += _mktab(p_level - 1) + "{\n"; } - for (int i = 0; i < bnode->statements.size(); i++) { - String scode = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + int i = 0; + for (List<ShaderLanguage::Node *>::ConstIterator itr = bnode->statements.begin(); itr != bnode->statements.end(); ++itr, ++i) { + String scode = _dump_node_code(*itr, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - if (bnode->statements[i]->type == SL::Node::NODE_TYPE_CONTROL_FLOW || bnode->single_statement) { + if ((*itr)->type == SL::Node::NODE_TYPE_CONTROL_FLOW || bnode->single_statement) { code += scode; //use directly if (bnode->use_comma_between_statements && i + 1 < bnode->statements.size()) { code += ","; diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 99b3f54379..1a4c8ea742 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -1389,7 +1389,7 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea *r_data_type = function->arguments[i].type; } if (r_struct_name) { - *r_struct_name = function->arguments[i].type_str; + *r_struct_name = function->arguments[i].struct_name; } if (r_array_size) { *r_array_size = function->arguments[i].array_size; @@ -1442,7 +1442,7 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea *r_array_size = shader->constants[p_identifier].array_size; } if (r_struct_name) { - *r_struct_name = shader->constants[p_identifier].type_str; + *r_struct_name = shader->constants[p_identifier].struct_name; } if (r_constant_value) { if (shader->constants[p_identifier].initializer && shader->constants[p_identifier].initializer->values.size() == 1) { @@ -3432,7 +3432,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI } String func_arg_name; if (pfunc->arguments[j].type == TYPE_STRUCT) { - func_arg_name = pfunc->arguments[j].type_str; + func_arg_name = pfunc->arguments[j].struct_name; } else { func_arg_name = get_datatype_name(pfunc->arguments[j].type); } @@ -3455,10 +3455,10 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI for (int j = 0; j < args.size(); j++) { if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::NODE_TYPE_CONSTANT && args3[j] == 0 && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) { //all good, but it needs implicit conversion later - } else if (args[j] != pfunc->arguments[j].type || (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str) || args3[j] != pfunc->arguments[j].array_size) { + } else if (args[j] != pfunc->arguments[j].type || (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].struct_name) || args3[j] != pfunc->arguments[j].array_size) { String func_arg_name; if (pfunc->arguments[j].type == TYPE_STRUCT) { - func_arg_name = pfunc->arguments[j].type_str; + func_arg_name = pfunc->arguments[j].struct_name; } else { func_arg_name = get_datatype_name(pfunc->arguments[j].type); } @@ -4076,6 +4076,8 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform case ShaderLanguage::TYPE_BOOL: if (p_uniform.array_size > 0) { pi.type = Variant::PACKED_INT32_ARRAY; + pi.hint = PROPERTY_HINT_TYPE_STRING; + pi.hint_string = itos(Variant::INT) + "/" + itos(PROPERTY_HINT_FLAGS) + ":" + RTR("On"); } else { pi.type = Variant::BOOL; } @@ -4083,6 +4085,8 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform case ShaderLanguage::TYPE_BVEC2: if (p_uniform.array_size > 0) { pi.type = Variant::PACKED_INT32_ARRAY; + pi.hint = PROPERTY_HINT_TYPE_STRING; + pi.hint_string = itos(Variant::INT) + "/" + itos(PROPERTY_HINT_FLAGS) + ":x,y"; } else { pi.type = Variant::INT; pi.hint = PROPERTY_HINT_FLAGS; @@ -4092,6 +4096,8 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform case ShaderLanguage::TYPE_BVEC3: if (p_uniform.array_size > 0) { pi.type = Variant::PACKED_INT32_ARRAY; + pi.hint = PROPERTY_HINT_TYPE_STRING; + pi.hint_string = itos(Variant::INT) + "/" + itos(PROPERTY_HINT_FLAGS) + ":x,y,z"; } else { pi.type = Variant::INT; pi.hint = PROPERTY_HINT_FLAGS; @@ -4101,6 +4107,8 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform case ShaderLanguage::TYPE_BVEC4: if (p_uniform.array_size > 0) { pi.type = Variant::PACKED_INT32_ARRAY; + pi.hint = PROPERTY_HINT_TYPE_STRING; + pi.hint_string = itos(Variant::INT) + "/" + itos(PROPERTY_HINT_FLAGS) + ":x,y,z,w"; } else { pi.type = Variant::INT; pi.hint = PROPERTY_HINT_FLAGS; @@ -4111,11 +4119,16 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform case ShaderLanguage::TYPE_INT: { if (p_uniform.array_size > 0) { pi.type = Variant::PACKED_INT32_ARRAY; + // TODO: Handle range and encoding for for unsigned values. } else { pi.type = Variant::INT; + pi.hint = PROPERTY_HINT_RANGE; if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { - pi.hint = PROPERTY_HINT_RANGE; pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]); + } else if (p_uniform.type == ShaderLanguage::TYPE_UINT) { + pi.hint_string = "0," + itos(UINT32_MAX); + } else { + pi.hint_string = itos(INT32_MIN) + "," + itos(INT32_MAX); } } } break; @@ -4123,6 +4136,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform case ShaderLanguage::TYPE_IVEC2: { if (p_uniform.array_size > 0) { pi.type = Variant::PACKED_INT32_ARRAY; + // TODO: Handle vector pairs? } else { pi.type = Variant::VECTOR2I; } @@ -4131,6 +4145,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform case ShaderLanguage::TYPE_IVEC3: { if (p_uniform.array_size > 0) { pi.type = Variant::PACKED_INT32_ARRAY; + // TODO: Handle vector pairs? } else { pi.type = Variant::VECTOR3I; } @@ -4139,6 +4154,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform case ShaderLanguage::TYPE_IVEC4: { if (p_uniform.array_size > 0) { pi.type = Variant::PACKED_INT32_ARRAY; + // TODO: Handle vector pairs? } else { pi.type = Variant::VECTOR4I; } @@ -5201,11 +5217,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons funcname->name = name; func->arguments.push_back(funcname); - for (int i = 0; i < pstruct->members.size(); i++) { + for (List<ShaderLanguage::MemberNode *>::Element *E = pstruct->members.front(); E; E = E->next()) { Node *nexpr; - if (pstruct->members[i]->array_size != 0) { - nexpr = _parse_array_constructor(p_block, p_function_info, pstruct->members[i]->get_datatype(), pstruct->members[i]->struct_name, pstruct->members[i]->array_size); + if (E->get()->array_size != 0) { + nexpr = _parse_array_constructor(p_block, p_function_info, E->get()->get_datatype(), E->get()->struct_name, E->get()->array_size); if (!nexpr) { return nullptr; } @@ -5214,12 +5230,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (!nexpr) { return nullptr; } - if (!_compare_datatypes_in_nodes(pstruct->members[i], nexpr)) { + if (!_compare_datatypes_in_nodes(E->get(), nexpr)) { return nullptr; } } - if (i + 1 < pstruct->members.size()) { + if (E->next()) { tk = _get_token(); if (tk.type != TK_COMMA) { _set_expected_error(","); @@ -7469,8 +7485,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun continue; } else { HashSet<int> constants; - for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates. - ControlFlowNode *flow = static_cast<ControlFlowNode *>(switch_block->statements[i]); + for (ShaderLanguage::Node *statement : switch_block->statements) { // Checks for duplicates. + ControlFlowNode *flow = static_cast<ControlFlowNode *>(statement); if (flow) { if (flow->flow_op == FLOW_OP_CASE) { if (flow->expressions[0]->type == Node::NODE_TYPE_CONSTANT) { @@ -9212,7 +9228,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f ShaderNode::Constant constant; constant.name = name; constant.type = is_struct ? TYPE_STRUCT : type; - constant.type_str = struct_name; + constant.struct_name = struct_name; constant.precision = precision; constant.initializer = nullptr; constant.array_size = array_size; @@ -9391,7 +9407,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f expr->datatype = constant.type; - expr->struct_name = constant.type_str; + expr->struct_name = constant.struct_name; expr->array_size = constant.array_size; @@ -9732,7 +9748,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f FunctionNode::Argument arg; arg.type = param_type; arg.name = param_name; - arg.type_str = param_struct_name; + arg.struct_name = param_struct_name; arg.precision = param_precision; arg.qualifier = param_qualifier; arg.tex_argument_check = false; @@ -9846,9 +9862,9 @@ Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOper Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op) { bool found = false; - for (int i = p_block->statements.size() - 1; i >= 0; i--) { - if (p_block->statements[i]->type == Node::NODE_TYPE_CONTROL_FLOW) { - ControlFlowNode *flow = static_cast<ControlFlowNode *>(p_block->statements[i]); + for (List<ShaderLanguage::Node *>::Element *E = p_block->statements.back(); E; E = E->prev()) { + if (E->get()->type == Node::NODE_TYPE_CONTROL_FLOW) { + ControlFlowNode *flow = static_cast<ControlFlowNode *>(E->get()); if (flow->flow_op == p_op) { found = true; break; @@ -9858,8 +9874,8 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat break; } } - } else if (p_block->statements[i]->type == Node::NODE_TYPE_BLOCK) { - BlockNode *block = static_cast<BlockNode *>(p_block->statements[i]); + } else if (E->get()->type == Node::NODE_TYPE_BLOCK) { + BlockNode *block = static_cast<BlockNode *>(E->get()); if (_find_last_flow_op_in_block(block, p_op) == OK) { found = true; break; @@ -10151,8 +10167,8 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ case COMPLETION_STRUCT: { if (shader->structs.has(completion_struct)) { StructNode *node = shader->structs[completion_struct].shader_struct; - for (int i = 0; i < node->members.size(); i++) { - ScriptLanguage::CodeCompletionOption option(node->members[i]->name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER); + for (ShaderLanguage::MemberNode *member : node->members) { + ScriptLanguage::CodeCompletionOption option(member->name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER); r_options->push_back(option); } } @@ -10355,7 +10371,11 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ if (shader->vfunctions[i].name == completion_function) { String calltip; - calltip += get_datatype_name(shader->vfunctions[i].function->return_type); + if (shader->vfunctions[i].function->return_type == TYPE_STRUCT) { + calltip += String(shader->vfunctions[i].function->return_struct_name); + } else { + calltip += get_datatype_name(shader->vfunctions[i].function->return_type); + } if (shader->vfunctions[i].function->return_array_size > 0) { calltip += "["; @@ -10390,7 +10410,11 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } } - calltip += get_datatype_name(shader->vfunctions[i].function->arguments[j].type); + if (shader->vfunctions[i].function->arguments[j].type == TYPE_STRUCT) { + calltip += String(shader->vfunctions[i].function->arguments[j].struct_name); + } else { + calltip += get_datatype_name(shader->vfunctions[i].function->arguments[j].type); + } calltip += " "; calltip += shader->vfunctions[i].function->arguments[j].name; diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 816a202b50..38f304ff31 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -583,7 +583,7 @@ public: ArgumentQualifier qualifier; StringName name; DataType type; - StringName type_str; + StringName struct_name; DataPrecision precision; //for passing textures as arguments bool tex_argument_check; @@ -618,7 +618,7 @@ public: struct Constant { StringName name; DataType type; - StringName type_str; + StringName struct_name; DataPrecision precision; ConstantNode *initializer = nullptr; int array_size; diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index b2fa0ea9d2..ab9cf666ec 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -496,7 +496,7 @@ ShaderTypes::ShaderTypes() { shader_types_list.push_back("sky"); shader_types_list.push_back("fog"); - for (int i = 0; i < shader_types_list.size(); i++) { - shader_types.insert(shader_types_list[i]); + for (const String &type : shader_types_list) { + shader_types.insert(type); } } diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h index cf37fbfb4a..72c4dd305b 100644 --- a/servers/rendering/storage/texture_storage.h +++ b/servers/rendering/storage/texture_storage.h @@ -169,6 +169,8 @@ public: virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) = 0; virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const = 0; + virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) = 0; + virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const = 0; virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) = 0; virtual RID render_target_get_vrs_texture(RID p_render_target) const = 0; diff --git a/servers/rendering/storage/variant_converters.h b/servers/rendering/storage/variant_converters.h index 7dbdb0f517..cee663e878 100644 --- a/servers/rendering/storage/variant_converters.h +++ b/servers/rendering/storage/variant_converters.h @@ -239,7 +239,8 @@ inline bool is_convertible_array(Variant::Type type) { return type == Variant::ARRAY || type == Variant::PACKED_VECTOR2_ARRAY || type == Variant::PACKED_VECTOR3_ARRAY || - type == Variant::PACKED_COLOR_ARRAY; + type == Variant::PACKED_COLOR_ARRAY || + type == Variant::PACKED_VECTOR4_ARRAY; } template <typename, typename = void> diff --git a/servers/rendering_server.compat.inc b/servers/rendering_server.compat.inc index 0cef3c906c..99f2de9a9a 100644 --- a/servers/rendering_server.compat.inc +++ b/servers/rendering_server.compat.inc @@ -34,8 +34,23 @@ void RenderingServer::_environment_set_fog_bind_compat_84792(RID p_env, bool p_e environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect, RS::EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL); } +void RenderingServer::_canvas_item_add_multiline_bind_compat_84523(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) { + canvas_item_add_multiline(p_item, p_points, p_colors, p_width, false); +} + +void RenderingServer::_canvas_item_add_rect_bind_compat_84523(RID p_item, const Rect2 &p_rect, const Color &p_color) { + canvas_item_add_rect(p_item, p_rect, p_color, false); +} + +void RenderingServer::_canvas_item_add_circle_bind_compat_84523(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) { + canvas_item_add_circle(p_item, p_pos, p_radius, p_color, false); +} + void RenderingServer::_bind_compatibility_methods() { ClassDB::bind_compatibility_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect"), &RenderingServer::_environment_set_fog_bind_compat_84792); + ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width"), &RenderingServer::_canvas_item_add_multiline_bind_compat_84523, DEFVAL(-1.0)); + ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::_canvas_item_add_rect_bind_compat_84523); + ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::_canvas_item_add_circle_bind_compat_84523); } #endif diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 60e8f18c19..7637d4e7da 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2229,6 +2229,7 @@ void RenderingServer::_bind_methods() { BIND_CONSTANT(MAX_GLOW_LEVELS); BIND_CONSTANT(MAX_CURSORS); BIND_CONSTANT(MAX_2D_DIRECTIONAL_LIGHTS); + BIND_CONSTANT(MAX_MESH_SURFACES); /* TEXTURE */ @@ -2824,6 +2825,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_gpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_gpu); ClassDB::bind_method(D_METHOD("viewport_set_vrs_mode", "viewport", "mode"), &RenderingServer::viewport_set_vrs_mode); + ClassDB::bind_method(D_METHOD("viewport_set_vrs_update_mode", "viewport", "mode"), &RenderingServer::viewport_set_vrs_update_mode); ClassDB::bind_method(D_METHOD("viewport_set_vrs_texture", "viewport", "texture"), &RenderingServer::viewport_set_vrs_texture); BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_BILINEAR); @@ -2832,7 +2834,7 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_MAX); BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED); - BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); // Then goes to disabled); must be manually updated. + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); // Then goes to disabled, must be manually updated. BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); // Default BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE); BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS); @@ -2914,6 +2916,11 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(VIEWPORT_VRS_XR); BIND_ENUM_CONSTANT(VIEWPORT_VRS_MAX); + BIND_ENUM_CONSTANT(VIEWPORT_VRS_UPDATE_DISABLED); + BIND_ENUM_CONSTANT(VIEWPORT_VRS_UPDATE_ONCE); // Then goes to disabled, must be manually updated. + BIND_ENUM_CONSTANT(VIEWPORT_VRS_UPDATE_ALWAYS); + BIND_ENUM_CONSTANT(VIEWPORT_VRS_UPDATE_MAX); + /* SKY API */ ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create); @@ -3223,9 +3230,9 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &RenderingServer::canvas_item_add_line, DEFVAL(-1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(-1.0), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width"), &RenderingServer::canvas_item_add_multiline, DEFVAL(-1.0)); - ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect); - ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle); + ClassDB::bind_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_multiline, DEFVAL(-1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color", "antialiased"), &RenderingServer::canvas_item_add_rect, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color", "antialiased"), &RenderingServer::canvas_item_add_circle, DEFVAL(false)); ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range", "scale"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0), DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("canvas_item_add_lcd_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate"), &RenderingServer::canvas_item_add_lcd_texture_rect_region); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 240d82c90b..e15dba4353 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -99,6 +99,10 @@ protected: #ifndef DISABLE_DEPRECATED void _environment_set_fog_bind_compat_84792(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect); + void _canvas_item_add_multiline_bind_compat_84523(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0); + void _canvas_item_add_rect_bind_compat_84523(RID p_item, const Rect2 &p_rect, const Color &p_color); + void _canvas_item_add_circle_bind_compat_84523(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); + static void _bind_compatibility_methods(); #endif @@ -1056,7 +1060,15 @@ public: VIEWPORT_VRS_MAX, }; + enum ViewportVRSUpdateMode { + VIEWPORT_VRS_UPDATE_DISABLED, + VIEWPORT_VRS_UPDATE_ONCE, + VIEWPORT_VRS_UPDATE_ALWAYS, + VIEWPORT_VRS_UPDATE_MAX, + }; + virtual void viewport_set_vrs_mode(RID p_viewport, ViewportVRSMode p_mode) = 0; + virtual void viewport_set_vrs_update_mode(RID p_viewport, ViewportVRSUpdateMode p_mode) = 0; virtual void viewport_set_vrs_texture(RID p_viewport, RID p_texture) = 0; /* SKY API */ @@ -1457,9 +1469,9 @@ public: virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false) = 0; virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false) = 0; - virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0) = 0; - virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0; - virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0; + virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false) = 0; + virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased = false) = 0; + virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased = false) = 0; virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0; virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0; virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0) = 0; @@ -1815,6 +1827,7 @@ VARIANT_ENUM_CAST(RenderingServer::ViewportOcclusionCullingBuildQuality); VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize); VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale); VARIANT_ENUM_CAST(RenderingServer::ViewportVRSMode); +VARIANT_ENUM_CAST(RenderingServer::ViewportVRSUpdateMode); VARIANT_ENUM_CAST(RenderingServer::SkyMode); VARIANT_ENUM_CAST(RenderingServer::CompositorEffectCallbackType); VARIANT_ENUM_CAST(RenderingServer::CompositorEffectFlags); diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index 8f9797805f..c13f5db5e9 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -332,6 +332,7 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(_strip_diacritics, "string"); GDVIRTUAL_BIND(_is_valid_identifier, "string"); + GDVIRTUAL_BIND(_is_valid_letter, "unicode"); GDVIRTUAL_BIND(_string_get_word_breaks, "string", "language", "chars_per_line"); GDVIRTUAL_BIND(_string_get_character_breaks, "string", "language"); @@ -1492,6 +1493,14 @@ bool TextServerExtension::is_valid_identifier(const String &p_string) const { return TextServer::is_valid_identifier(p_string); } +bool TextServerExtension::is_valid_letter(char32_t p_unicode) const { + bool ret; + if (GDVIRTUAL_CALL(_is_valid_letter, p_unicode, ret)) { + return ret; + } + return TextServer::is_valid_letter(p_unicode); +} + String TextServerExtension::strip_diacritics(const String &p_string) const { String ret; if (GDVIRTUAL_CALL(_strip_diacritics, p_string, ret)) { diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index f447f0f5bd..d5cd1f753e 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -563,6 +563,8 @@ public: virtual bool is_valid_identifier(const String &p_string) const override; GDVIRTUAL1RC(bool, _is_valid_identifier, const String &); + virtual bool is_valid_letter(char32_t p_unicode) const override; + GDVIRTUAL1RC(bool, _is_valid_letter, char32_t); virtual String string_to_upper(const String &p_string, const String &p_language = "") const override; virtual String string_to_lower(const String &p_string, const String &p_language = "") const override; diff --git a/servers/text_server.cpp b/servers/text_server.cpp index 562f2df411..127c674f0c 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -490,6 +490,7 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("strip_diacritics", "string"), &TextServer::strip_diacritics); ClassDB::bind_method(D_METHOD("is_valid_identifier", "string"), &TextServer::is_valid_identifier); + ClassDB::bind_method(D_METHOD("is_valid_letter", "unicode"), &TextServer::is_valid_letter); ClassDB::bind_method(D_METHOD("string_to_upper", "string", "language"), &TextServer::string_to_upper, DEFVAL("")); ClassDB::bind_method(D_METHOD("string_to_lower", "string", "language"), &TextServer::string_to_lower, DEFVAL("")); @@ -2182,6 +2183,10 @@ bool TextServer::is_valid_identifier(const String &p_string) const { return true; } +bool TextServer::is_valid_letter(char32_t p_unicode) const { + return is_unicode_letter(p_unicode); +} + TextServer::TextServer() { _init_diacritics_map(); } diff --git a/servers/text_server.h b/servers/text_server.h index 775dbb5508..5835b36ec4 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -547,6 +547,7 @@ public: virtual String strip_diacritics(const String &p_string) const; virtual bool is_valid_identifier(const String &p_string) const; + virtual bool is_valid_letter(char32_t p_unicode) const; // Other string operations. virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0; diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp index 9ced28fd52..26f315a454 100644 --- a/servers/xr/xr_interface.cpp +++ b/servers/xr/xr_interface.cpp @@ -132,13 +132,7 @@ void XRInterface::set_primary(bool p_primary) { XRInterface::XRInterface() {} -XRInterface::~XRInterface() { - if (vrs.vrs_texture.is_valid()) { - ERR_FAIL_NULL(RenderingServer::get_singleton()); - RS::get_singleton()->free(vrs.vrs_texture); - vrs.vrs_texture = RID(); - } -} +XRInterface::~XRInterface() {} // query if this interface supports this play area mode bool XRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) { @@ -176,80 +170,7 @@ int XRInterface::get_camera_feed_id() { } RID XRInterface::get_vrs_texture() { - // Default logic will return a standard VRS image based on our target size and default projections. - // Note that this only gets called if VRS is supported on the hardware. - - int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH); - int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT); - int view_count = get_view_count(); - Size2 target_size = get_render_target_size(); - real_t aspect = target_size.x / target_size.y; // is this y/x ? - Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_width), round(0.5 + target_size.y / texel_height)); - real_t radius = vrs_size.length() * 0.5; - Size2 vrs_sizei = vrs_size; - - if (vrs.size != vrs_sizei) { - const uint8_t densities[] = { - 0, // 1x1 - 1, // 1x2 - // 2, // 1x4 - not supported - // 3, // 1x8 - not supported - // 4, // 2x1 - 5, // 2x2 - 6, // 2x4 - // 9, // 4x2 - 10, // 4x4 - }; - - // out with the old - if (vrs.vrs_texture.is_valid()) { - RS::get_singleton()->free(vrs.vrs_texture); - vrs.vrs_texture = RID(); - } - - // in with the new - Vector<Ref<Image>> images; - vrs.size = vrs_sizei; - - for (int i = 0; i < view_count && i < 2; i++) { - PackedByteArray data; - data.resize(vrs_sizei.x * vrs_sizei.y); - uint8_t *data_ptr = data.ptrw(); - - // Our near and far don't matter much for what we're doing here, but there are some interfaces that will remember this as the near and far and may fail as a result... - Projection cm = get_projection_for_view(i, aspect, 0.1, 1000.0); - Vector3 center = cm.xform(Vector3(0.0, 0.0, 999.0)); - - Vector2i view_center; - view_center.x = int(vrs_size.x * (center.x + 1.0) * 0.5); - view_center.y = int(vrs_size.y * (center.y + 1.0) * 0.5); - - int d = 0; - for (int y = 0; y < vrs_sizei.y; y++) { - for (int x = 0; x < vrs_sizei.x; x++) { - Vector2 offset = Vector2(x - view_center.x, y - view_center.y); - offset.y *= aspect; - real_t distance = offset.length(); - int idx = round(5.0 * distance / radius); - if (idx > 4) { - idx = 4; - } - uint8_t density = densities[idx]; - - data_ptr[d++] = density; - } - } - images.push_back(Image::create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_R8, data)); - } - - if (images.size() == 1) { - vrs.vrs_texture = RS::get_singleton()->texture_2d_create(images[0]); - } else { - vrs.vrs_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TEXTURE_LAYERED_2D_ARRAY); - } - } - - return vrs.vrs_texture; + return RID(); } /** these are optional, so we want dummies **/ diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h index 809800d8b9..7beec219bb 100644 --- a/servers/xr/xr_interface.h +++ b/servers/xr/xr_interface.h @@ -34,6 +34,7 @@ #include "core/math/projection.h" #include "core/os/thread_safe.h" #include "servers/xr_server.h" +#include "xr_vrs.h" // forward declaration struct BlitToScreen; @@ -133,7 +134,6 @@ public: // These methods are called from the rendering thread. virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */ virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */ - virtual RID get_vrs_texture(); /* obtain VRS texture */ virtual RID get_color_texture(); /* obtain color output texture (if applicable) */ virtual RID get_depth_texture(); /* obtain depth output texture (if applicable, used for reprojection) */ virtual RID get_velocity_texture(); /* obtain velocity output texture (if applicable, used for spacewarp) */ @@ -149,19 +149,16 @@ public: virtual bool start_passthrough() { return false; } virtual void stop_passthrough() {} - /** environment blend mode. */ + /** environment blend mode **/ virtual Array get_supported_environment_blend_modes(); virtual XRInterface::EnvironmentBlendMode get_environment_blend_mode() const { return XR_ENV_BLEND_MODE_OPAQUE; } virtual bool set_environment_blend_mode(EnvironmentBlendMode mode) { return false; } + /** VRS **/ + virtual RID get_vrs_texture(); /* obtain VRS texture */ + XRInterface(); ~XRInterface(); - -private: - struct VRSData { - RID vrs_texture; - Size2i size; - } vrs; }; VARIANT_ENUM_CAST(XRInterface::Capabilities); diff --git a/servers/xr/xr_vrs.cpp b/servers/xr/xr_vrs.cpp new file mode 100644 index 0000000000..9d1e2f2068 --- /dev/null +++ b/servers/xr/xr_vrs.cpp @@ -0,0 +1,151 @@ +/**************************************************************************/ +/* xr_vrs.cpp */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ + +#include "xr_vrs.h" + +#include "servers/rendering/renderer_scene_render.h" +#include "servers/rendering_server.h" + +void XRVRS::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_vrs_min_radius"), &XRVRS::get_vrs_min_radius); + ClassDB::bind_method(D_METHOD("set_vrs_min_radius", "radius"), &XRVRS::set_vrs_min_radius); + + ClassDB::bind_method(D_METHOD("get_vrs_strength"), &XRVRS::get_vrs_strength); + ClassDB::bind_method(D_METHOD("set_vrs_strength", "strength"), &XRVRS::set_vrs_strength); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_min_radius", PROPERTY_HINT_RANGE, "1.0,100.0,1.0"), "set_vrs_min_radius", "get_vrs_min_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_strength", PROPERTY_HINT_RANGE, "0.1,10.0,0.1"), "set_vrs_strength", "get_vrs_strength"); + + ClassDB::bind_method(D_METHOD("make_vrs_texture", "target_size", "eye_foci"), &XRVRS::make_vrs_texture); +} + +XRVRS::~XRVRS() { + if (vrs_texture.is_valid()) { + ERR_FAIL_NULL(RS::get_singleton()); + RS::get_singleton()->free(vrs_texture); + vrs_texture = RID(); + } +} + +float XRVRS::get_vrs_min_radius() const { + return vrs_min_radius; +} + +void XRVRS::set_vrs_min_radius(float p_vrs_min_radius) { + if (p_vrs_min_radius < 1.0) { + WARN_PRINT_ONCE("VRS minimum radius can not be set below 1.0"); + vrs_min_radius = 1.0; + } else if (p_vrs_min_radius > 100.0) { + WARN_PRINT_ONCE("VRS minimum radius can not be set above 100.0"); + vrs_min_radius = 100.0; + } else { + vrs_min_radius = p_vrs_min_radius; + vrs_dirty = true; + } +} + +float XRVRS::get_vrs_strength() const { + return vrs_strength; +} + +void XRVRS::set_vrs_strength(float p_vrs_strength) { + if (p_vrs_strength < 0.1) { + WARN_PRINT_ONCE("VRS strength can not be set below 0.1"); + vrs_strength = 0.1; + } else if (p_vrs_strength > 10.0) { + WARN_PRINT_ONCE("VRS strength can not be set above 10.0"); + vrs_strength = 10.0; + } else { + vrs_strength = p_vrs_strength; + vrs_dirty = true; + } +} + +RID XRVRS::make_vrs_texture(const Size2 &p_target_size, const PackedVector2Array &p_eye_foci) { + ERR_FAIL_COND_V(p_eye_foci.is_empty(), RID()); + + int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH); + int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT); + + Size2 vrs_size = Size2(0.5 + p_target_size.x / texel_width, 0.5 + p_target_size.y / texel_height).round(); + float max_radius = 0.5 * MIN(vrs_size.x, vrs_size.y); // Maximum radius that fits inside of our image + float min_radius = vrs_min_radius * max_radius / 100.0; // Minimum radius as a percentage of our size + real_t outer_radius = MAX(1.0, (max_radius - min_radius) / vrs_strength); + Size2 vrs_sizei = vrs_size; + + // Our density map is now unified, with a value of (0.0, 0.0) meaning a 1x1 texel size and (1.0, 1.0) an max texel size. + // For our standard VRS extension on Vulkan this means a maximum of 8x8. + // For the density map extension this scales depending on the max texel size. + + if (target_size != vrs_sizei || eye_foci != p_eye_foci || vrs_dirty) { + // Out with the old. + if (vrs_texture.is_valid()) { + RS::get_singleton()->free(vrs_texture); + vrs_texture = RID(); + } + + // In with the new. + Vector<Ref<Image>> images; + target_size = vrs_sizei; + eye_foci = p_eye_foci; + + for (int i = 0; i < eye_foci.size() && i < RendererSceneRender::MAX_RENDER_VIEWS; i++) { + PackedByteArray data; + data.resize(vrs_sizei.x * vrs_sizei.y * 2); + uint8_t *data_ptr = data.ptrw(); + + Vector2i view_center; + view_center.x = int(vrs_size.x * (eye_foci[i].x + 1.0) * 0.5); + view_center.y = int(vrs_size.y * (eye_foci[i].y + 1.0) * 0.5); + + int d = 0; + for (int y = 0; y < vrs_sizei.y; y++) { + for (int x = 0; x < vrs_sizei.x; x++) { + Vector2 offset = Vector2(x - view_center.x, y - view_center.y); + real_t density = 255.0 * MAX(0.0, (Math::abs(offset.x) - min_radius) / outer_radius); + data_ptr[d++] = MIN(255, density); + density = 255.0 * MAX(0.0, (Math::abs(offset.y) - min_radius) / outer_radius); + data_ptr[d++] = MIN(255, density); + } + } + images.push_back(Image::create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_RG8, data)); + } + + if (images.size() == 1) { + vrs_texture = RS::get_singleton()->texture_2d_create(images[0]); + } else { + vrs_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TEXTURE_LAYERED_2D_ARRAY); + } + + vrs_dirty = false; + } + + return vrs_texture; +} diff --git a/servers/xr/xr_vrs.h b/servers/xr/xr_vrs.h new file mode 100644 index 0000000000..35dfe55620 --- /dev/null +++ b/servers/xr/xr_vrs.h @@ -0,0 +1,67 @@ +/**************************************************************************/ +/* xr_vrs.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 XR_VRS_H +#define XR_VRS_H + +#include "core/object/class_db.h" +#include "core/object/object.h" +#include "core/templates/rid.h" +#include "core/variant/variant.h" + +/* This is a helper class for generating stereoscopic VRS images */ + +class XRVRS : public Object { + GDCLASS(XRVRS, Object); + +private: + float vrs_min_radius = 20.0; + float vrs_strength = 1.0; + bool vrs_dirty = true; + + RID vrs_texture; + Size2i target_size; + PackedVector2Array eye_foci; + +protected: + static void _bind_methods(); + +public: + ~XRVRS(); + + float get_vrs_min_radius() const; + void set_vrs_min_radius(float p_vrs_min_radius); + float get_vrs_strength() const; + void set_vrs_strength(float p_vrs_strength); + + RID make_vrs_texture(const Size2 &p_target_size, const PackedVector2Array &p_eye_foci); +}; + +#endif // XR_VRS_H |