Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to sync frame delta after draw #48555

Merged
merged 1 commit into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@
[b]Note:[/b] Delta smoothing is only attempted when [member display/window/vsync/use_vsync] is switched on, as it does not work well without V-Sync.
It may take several seconds at a stable frame rate before the smoothing is initially activated. It will only be active on machines where performance is adequate to render frames at the refresh rate.
</member>
<member name="application/run/delta_sync_after_draw" type="bool" setter="" getter="" default="false">
[b]Experimental.[/b] Shifts the measurement of delta time for each frame to just after the drawing has taken place. This may lead to more consistent deltas and a reduction in frame stutters.
</member>
<member name="application/run/disable_stderr" type="bool" setter="" getter="" default="false">
If [code]true[/code], disables printing to standard error. If [code]true[/code], this also hides error and warning messages printed by [method @GDScript.push_error] and [method @GDScript.push_warning]. See also [member application/run/disable_stdout].
Changes to this setting will only be applied upon restarting the application.
Expand Down Expand Up @@ -1059,19 +1062,19 @@
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.physics_jitter_fix] instead.
</member>
<member name="rendering/2d/opengl/batching_send_null" type="int" setter="" getter="" default="0">
[b]Experimental[/b] Calls [code]glBufferData[/code] with NULL data prior to uploading batching data. This may not be necessary but can be used for safety.
[b]Experimental.[/b] Calls [code]glBufferData[/code] with NULL data prior to uploading batching data. This may not be necessary but can be used for safety.
[b]Note:[/b] Use with care. You are advised to leave this as default for exports. A non-default setting that works better on your machine may adversely affect performance for end users.
</member>
<member name="rendering/2d/opengl/batching_stream" type="int" setter="" getter="" default="0">
[b]Experimental[/b] If set to on, uses the [code]GL_STREAM_DRAW[/code] flag for batching buffer uploads. If off, uses the [code]GL_DYNAMIC_DRAW[/code] flag.
[b]Experimental.[/b] If set to on, uses the [code]GL_STREAM_DRAW[/code] flag for batching buffer uploads. If off, uses the [code]GL_DYNAMIC_DRAW[/code] flag.
[b]Note:[/b] Use with care. You are advised to leave this as default for exports. A non-default setting that works better on your machine may adversely affect performance for end users.
</member>
<member name="rendering/2d/opengl/legacy_orphan_buffers" type="int" setter="" getter="" default="0">
[b]Experimental[/b] If set to on, this applies buffer orphaning - [code]glBufferData[/code] is called with NULL data and the full buffer size prior to uploading new data. This can be important to avoid stalling on some hardware.
[b]Experimental.[/b] If set to on, this applies buffer orphaning - [code]glBufferData[/code] is called with NULL data and the full buffer size prior to uploading new data. This can be important to avoid stalling on some hardware.
[b]Note:[/b] Use with care. You are advised to leave this as default for exports. A non-default setting that works better on your machine may adversely affect performance for end users.
</member>
<member name="rendering/2d/opengl/legacy_stream" type="int" setter="" getter="" default="0">
[b]Experimental[/b] If set to on, uses the [code]GL_STREAM_DRAW[/code] flag for legacy buffer uploads. If off, uses the [code]GL_DYNAMIC_DRAW[/code] flag.
[b]Experimental.[/b] If set to on, uses the [code]GL_STREAM_DRAW[/code] flag for legacy buffer uploads. If off, uses the [code]GL_DYNAMIC_DRAW[/code] flag.
[b]Note:[/b] Use with care. You are advised to leave this as default for exports. A non-default setting that works better on your machine may adversely affect performance for end users.
</member>
<member name="rendering/2d/options/ninepatch_mode" type="int" setter="" getter="" default="1">
Expand All @@ -1097,7 +1100,7 @@
When batching is on, this regularly prints a frame diagnosis log. Note that this will degrade performance.
</member>
<member name="rendering/batching/debug/flash_batching" type="bool" setter="" getter="" default="false">
[b]Experimental[/b] For regression testing against the old renderer. If this is switched on, and [code]use_batching[/code] is set, the renderer will swap alternately between using the old renderer, and the batched renderer, on each frame. This makes it easy to identify visual differences. Performance will be degraded.
[b]Experimental.[/b] For regression testing against the old renderer. If this is switched on, and [code]use_batching[/code] is set, the renderer will swap alternately between using the old renderer, and the batched renderer, on each frame. This makes it easy to identify visual differences. Performance will be degraded.
</member>
<member name="rendering/batching/lights/max_join_items" type="int" setter="" getter="" default="32">
Lights have the potential to prevent joining items, and break many of the performance benefits of batching. This setting enables some complex logic to allow joining items if their lighting is similar, and overlap tests pass. This can significantly improve performance in some games. Set to 0 to switch off. With large values the cost of overlap tests may lead to diminishing returns.
Expand Down
27 changes: 27 additions & 0 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ static String locale;
static bool show_help = false;
static bool auto_quit = false;
static OS::ProcessID allow_focus_steal_pid = 0;
static bool delta_sync_after_draw = false;
#ifdef TOOLS_ENABLED
static bool auto_build_solutions = false;
#endif
Expand Down Expand Up @@ -1204,6 +1205,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(GLOBAL_DEF("application/run/low_processor_mode_sleep_usec", 6900)); // Roughly 144 FPS
ProjectSettings::get_singleton()->set_custom_property_info("application/run/low_processor_mode_sleep_usec", PropertyInfo(Variant::INT, "application/run/low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "0,33200,1,or_greater")); // No negative numbers

delta_sync_after_draw = GLOBAL_DEF("application/run/delta_sync_after_draw", false);
GLOBAL_DEF("application/run/delta_smoothing", true);
if (!delta_smoothing_override) {
OS::get_singleton()->set_delta_smoothing(GLOBAL_GET("application/run/delta_smoothing"));
Expand Down Expand Up @@ -2044,13 +2046,31 @@ bool Main::is_iterating() {
static uint64_t physics_process_max = 0;
static uint64_t idle_process_max = 0;

#ifndef TOOLS_ENABLED
static uint64_t frame_delta_sync_time = 0;
#endif

bool Main::iteration() {
//for now do not error on this
//ERR_FAIL_COND_V(iterating, false);

iterating++;

#ifdef TOOLS_ENABLED
uint64_t ticks = OS::get_singleton()->get_ticks_usec();
#else
// we can either sync the delta from here, or later in the iteration
uint64_t ticks_at_start = OS::get_singleton()->get_ticks_usec();
uint64_t ticks_difference = ticks_at_start - frame_delta_sync_time;

// if we are syncing at start or if frame_delta_sync_time is being initialized
// or a large gap has happened between the last delta_sync_time and now
if (!delta_sync_after_draw || (ticks_difference > 100000)) {
frame_delta_sync_time = ticks_at_start;
}
uint64_t ticks = frame_delta_sync_time;
#endif

Engine::get_singleton()->_frame_ticks = ticks;
main_timer_sync.set_cpu_ticks_usec(ticks);
main_timer_sync.set_fixed_fps(fixed_fps);
Expand Down Expand Up @@ -2138,6 +2158,13 @@ bool Main::iteration() {
}
}

#ifndef TOOLS_ENABLED
// we can choose to sync delta from here, just after the draw
if (delta_sync_after_draw) {
frame_delta_sync_time = OS::get_singleton()->get_ticks_usec();
}
#endif

idle_process_ticks = OS::get_singleton()->get_ticks_usec() - idle_begin;
idle_process_max = MAX(idle_process_ticks, idle_process_max);
uint64_t frame_time = OS::get_singleton()->get_ticks_usec() - ticks;
Expand Down