mirror of
https://github.com/godotengine/godot.git
synced 2024-12-27 11:24:59 +08:00
Merge pull request #100257 from darksylinc/matias-minimize-leak
Keep processing Graphics if there are pending operations
This commit is contained in:
commit
23afda44e4
@ -4441,15 +4441,20 @@ bool Main::iteration() {
|
||||
|
||||
RenderingServer::get_singleton()->sync(); //sync if still drawing from previous frames.
|
||||
|
||||
if ((DisplayServer::get_singleton()->can_any_window_draw() || DisplayServer::get_singleton()->has_additional_outputs()) &&
|
||||
RenderingServer::get_singleton()->is_render_loop_enabled()) {
|
||||
const bool has_pending_resources_for_processing = RD::get_singleton() && RD::get_singleton()->has_pending_resources_for_processing();
|
||||
bool wants_present = (DisplayServer::get_singleton()->can_any_window_draw() ||
|
||||
DisplayServer::get_singleton()->has_additional_outputs()) &&
|
||||
RenderingServer::get_singleton()->is_render_loop_enabled();
|
||||
|
||||
if (wants_present || has_pending_resources_for_processing) {
|
||||
wants_present |= force_redraw_requested;
|
||||
if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
|
||||
if (RenderingServer::get_singleton()->has_changed()) {
|
||||
RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands
|
||||
RenderingServer::get_singleton()->draw(wants_present, scaled_step); // flush visual commands
|
||||
Engine::get_singleton()->increment_frames_drawn();
|
||||
}
|
||||
} else {
|
||||
RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands
|
||||
RenderingServer::get_singleton()->draw(wants_present, scaled_step); // flush visual commands
|
||||
Engine::get_singleton()->increment_frames_drawn();
|
||||
force_redraw_requested = false;
|
||||
}
|
||||
|
@ -90,8 +90,8 @@ public:
|
||||
|
||||
void gl_end_frame(bool p_swap_buffers) override {}
|
||||
|
||||
void end_frame(bool p_swap_buffers) override {
|
||||
if (p_swap_buffers) {
|
||||
void end_frame(bool p_present) override {
|
||||
if (p_present) {
|
||||
DisplayServer::get_singleton()->swap_buffers();
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ public:
|
||||
virtual void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) = 0;
|
||||
|
||||
virtual void gl_end_frame(bool p_swap_buffers) = 0;
|
||||
virtual void end_frame(bool p_swap_buffers) = 0;
|
||||
virtual void end_frame(bool p_present) = 0;
|
||||
virtual void finalize() = 0;
|
||||
virtual uint64_t get_frame_number() const = 0;
|
||||
virtual double get_frame_delta_time() const = 0;
|
||||
|
@ -112,10 +112,8 @@ void RendererCompositorRD::begin_frame(double frame_step) {
|
||||
scene->set_time(time, frame_step);
|
||||
}
|
||||
|
||||
void RendererCompositorRD::end_frame(bool p_swap_buffers) {
|
||||
if (p_swap_buffers) {
|
||||
RD::get_singleton()->swap_buffers();
|
||||
}
|
||||
void RendererCompositorRD::end_frame(bool p_present) {
|
||||
RD::get_singleton()->swap_buffers(p_present);
|
||||
}
|
||||
|
||||
void RendererCompositorRD::initialize() {
|
||||
@ -267,7 +265,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
|
||||
|
||||
RD::get_singleton()->draw_list_end();
|
||||
|
||||
RD::get_singleton()->swap_buffers();
|
||||
RD::get_singleton()->swap_buffers(true);
|
||||
|
||||
texture_storage->texture_free(texture);
|
||||
RD::get_singleton()->free(sampler);
|
||||
|
@ -128,7 +128,7 @@ public:
|
||||
void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount);
|
||||
|
||||
void gl_end_frame(bool p_swap_buffers) {}
|
||||
void end_frame(bool p_swap_buffers);
|
||||
void end_frame(bool p_present);
|
||||
void finalize();
|
||||
|
||||
_ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; }
|
||||
|
@ -6029,6 +6029,8 @@ void RenderingDevice::_free_internal(RID p_id) {
|
||||
ERR_PRINT("Attempted to free invalid ID: " + itos(p_id.get_id()));
|
||||
#endif
|
||||
}
|
||||
|
||||
frames_pending_resources_for_processing = uint32_t(frames.size());
|
||||
}
|
||||
|
||||
// The full list of resources that can be named is in the VkObjectType enum.
|
||||
@ -6131,11 +6133,11 @@ String RenderingDevice::get_device_pipeline_cache_uuid() const {
|
||||
return driver->get_pipeline_cache_uuid();
|
||||
}
|
||||
|
||||
void RenderingDevice::swap_buffers() {
|
||||
void RenderingDevice::swap_buffers(bool p_present) {
|
||||
ERR_RENDER_THREAD_GUARD();
|
||||
|
||||
_end_frame();
|
||||
_execute_frame(true);
|
||||
_execute_frame(p_present);
|
||||
|
||||
// Advance to the next frame and begin recording again.
|
||||
frame = (frame + 1) % frames.size();
|
||||
@ -6238,6 +6240,10 @@ void RenderingDevice::_free_pending_resources(int p_frame) {
|
||||
|
||||
frames[p_frame].buffers_to_dispose_of.pop_front();
|
||||
}
|
||||
|
||||
if (frames_pending_resources_for_processing > 0u) {
|
||||
--frames_pending_resources_for_processing;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t RenderingDevice::get_frame_delay() const {
|
||||
|
@ -1469,6 +1469,17 @@ private:
|
||||
TightLocalVector<Frame> frames;
|
||||
uint64_t frames_drawn = 0;
|
||||
|
||||
// Whenever logic/physics request a graphics operation (not just deleting a resource) that requires
|
||||
// us to flush all graphics commands, we must set frames_pending_resources_for_processing = frames.size().
|
||||
// This is important for when the user requested for the logic loop to still be updated while
|
||||
// graphics should not (e.g. headless Multiplayer servers, minimized windows that need to still
|
||||
// process something on the background).
|
||||
uint32_t frames_pending_resources_for_processing = 0u;
|
||||
|
||||
public:
|
||||
bool has_pending_resources_for_processing() const { return frames_pending_resources_for_processing != 0u; }
|
||||
|
||||
private:
|
||||
void _free_pending_resources(int p_frame);
|
||||
|
||||
uint64_t texture_memory = 0;
|
||||
@ -1520,7 +1531,7 @@ public:
|
||||
|
||||
uint64_t limit_get(Limit p_limit) const;
|
||||
|
||||
void swap_buffers();
|
||||
void swap_buffers(bool p_present);
|
||||
|
||||
uint32_t get_frame_delay() const;
|
||||
|
||||
|
@ -406,15 +406,15 @@ void RenderingServerDefault::sync() {
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
|
||||
void RenderingServerDefault::draw(bool p_present, 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::_draw, p_swap_buffers, frame_step);
|
||||
command_queue.push(this, &RenderingServerDefault::_draw, p_present, frame_step);
|
||||
} else {
|
||||
_draw(p_swap_buffers, frame_step);
|
||||
_draw(p_present, frame_step);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1124,7 +1124,7 @@ public:
|
||||
|
||||
virtual void request_frame_drawn_callback(const Callable &p_callable) override;
|
||||
|
||||
virtual void draw(bool p_swap_buffers, double frame_step) override;
|
||||
virtual void draw(bool p_present, double frame_step) override;
|
||||
virtual void sync() override;
|
||||
virtual bool has_changed() const override;
|
||||
virtual void init() override;
|
||||
|
Loading…
Reference in New Issue
Block a user