diff --git a/core/templates/command_queue_mt.h b/core/templates/command_queue_mt.h index 2ad5d1229d63..9f9b77d9d045 100644 --- a/core/templates/command_queue_mt.h +++ b/core/templates/command_queue_mt.h @@ -388,6 +388,8 @@ class CommandQueueMT { } while (sync_head != sync_head_goal); // Can't use lower-than because of wraparound. } + void _no_op() {} + public: void lock(); void unlock(); @@ -409,10 +411,15 @@ public: _flush(); } } + void flush_all() { _flush(); } + void sync() { + push_and_sync(this, &CommandQueueMT::_no_op); + } + void wait_and_flush() { ERR_FAIL_COND(pump_task_id == WorkerThreadPool::INVALID_TASK_ID); WorkerThreadPool::get_singleton()->wait_for_task_completion(pump_task_id); @@ -420,7 +427,9 @@ public: } void set_pump_task_id(WorkerThreadPool::TaskID p_task_id) { + lock(); pump_task_id = p_task_id; + unlock(); } CommandQueueMT(); diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 767a394ce52c..6e7d4a67337e 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -395,10 +395,13 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display glBindFramebuffer(GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); if (p_first) { - Size2i win_size = DisplayServer::get_singleton()->window_get_size(); if (p_screen_rect.position != Vector2() || p_screen_rect.size != rt->size) { // Viewport doesn't cover entire window so clear window to black before blitting. - glViewport(0, 0, win_size.width, win_size.height); + // Querying the actual window size from the DisplayServer would deadlock in separate render thread mode, + // so let's set the biggest viewport the implementation supports, to be sure the window is fully covered. + GLsizei max_vp[2] = {}; + glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_vp); + glViewport(0, 0, max_vp[0], max_vp[1]); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); } diff --git a/servers/physics_server_2d_wrap_mt.cpp b/servers/physics_server_2d_wrap_mt.cpp index 4548bb91cbdf..8e9f7aa8fc9d 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() { +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_exit() { exit = true; } -void PhysicsServer2DWrapMT::thread_step(real_t p_delta) { - physics_server_2d->step(p_delta); - step_sem.post(); -} - -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 5e2b3b408669..f0c36a906f82 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 f8f60281a78c..95b71217c46d 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() { +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_exit() { exit = true; } -void PhysicsServer3DWrapMT::thread_step(real_t p_delta) { - physics_server_3d->step(p_delta); - step_sem.post(); -} - -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 22f3ee0e4555..0909c46b55c9 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/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index e739ffa535ee..884f8adb8c4e 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -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) { @@ -1521,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 8bdce04c506a..b36fc7f57ff6 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -303,7 +303,6 @@ public: 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_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 7e5ccee0e39b..51ff009eaf5d 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 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 RenderingServerDefault::get_frame_prof /* TESTING */ -void RenderingServerDefault::set_boot_image(const Ref &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::_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_exit() { exit = true; } -void RenderingServerDefault::_thread_draw(bool p_swap_buffers, double frame_step) { - _draw(p_swap_buffers, frame_step); -} - 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 bb2f3d94ce9c..d0b6bc492d47 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 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(); @@ -998,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 &, 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) @@ -1056,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); } @@ -1066,7 +1078,6 @@ public: virtual double get_frame_setup_time_cpu() const override; - virtual void set_boot_image(const Ref &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;