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

Physics Interpolation - add helper warnings #60531

Merged
merged 1 commit into from
Apr 28, 2022
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
4 changes: 4 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,10 @@
<member name="debug/settings/gdscript/max_call_stack" type="int" setter="" getter="" default="1024">
Maximum call stack allowed for debugging GDScript.
</member>
<member name="debug/settings/physics_interpolation/enable_warnings" type="bool" setter="" getter="" default="true">
If [code]true[/code], enables warnings which can help pinpoint where nodes are being incorrectly updated, which will result in incorrect interpolation and visual glitches.
When a node is being interpolated, it is essential that the transform is set during [method Node._physics_process] (during a physics tick) rather than [method Node._process] (during a frame).
</member>
<member name="debug/settings/profiler/max_functions" type="int" setter="" getter="" default="16384">
Maximum amount of functions per frame allowed when profiling.
</member>
Expand Down
2 changes: 2 additions & 0 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1224,6 +1224,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF("debug/settings/stdout/print_fps", false);
GLOBAL_DEF("debug/settings/stdout/verbose_stdout", false);

GLOBAL_DEF("debug/settings/physics_interpolation/enable_warnings", true);

if (!OS::get_singleton()->_verbose_stdout) { // Not manually overridden.
OS::get_singleton()->_verbose_stdout = GLOBAL_GET("debug/settings/stdout/verbose_stdout");
}
Expand Down
32 changes: 32 additions & 0 deletions servers/visual/rasterizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#include "core/os/os.h"
#include "core/print_string.h"

#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TOOLS_ENABLED assumes DEBUG_ENABLED so you don't need to check the latter.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That being said if you prefer to have both to make the intent extremely clear, that's fine too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I remember this coming up before. I'm slightly in favour of keeping both as you say to make the intent clear, because to a reader it is not obvious that TOOLS_ENABLED implies DEBUG_ENABLED (and this could conceivably change in future).

#include "core/project_settings.h"
#endif

Rasterizer *(*Rasterizer::_create_func)() = nullptr;

Rasterizer *Rasterizer::create() {
Expand Down Expand Up @@ -350,6 +354,16 @@ void RasterizerStorage::multimesh_instance_set_transform(RID p_multimesh, int p_
ptr[11] = t.origin.z;

_multimesh_add_to_interpolation_lists(p_multimesh, *mmi);

#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
if (!Engine::get_singleton()->is_in_physics_frame()) {
static int32_t warn_count = 0;
warn_count++;
if (((warn_count % 2048) == 0) && GLOBAL_GET("debug/settings/physics_interpolation/enable_warnings")) {
WARN_PRINT("Interpolated MultiMesh transform should usually be set during physics process (possibly benign).");
}
}
#endif
return;
}
}
Expand Down Expand Up @@ -498,6 +512,15 @@ void RasterizerStorage::multimesh_set_as_bulk_array_interpolated(RID p_multimesh
mmi->_data_prev = p_array_prev;
mmi->_data_curr = p_array;
_multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
if (!Engine::get_singleton()->is_in_physics_frame()) {
static int32_t warn_count = 0;
warn_count++;
if (((warn_count % 2048) == 0) && GLOBAL_GET("debug/settings/physics_interpolation/enable_warnings")) {
WARN_PRINT("Interpolated MultiMesh transform should usually be set during physics process (possibly benign).");
}
}
#endif
}
}

Expand All @@ -507,6 +530,15 @@ void RasterizerStorage::multimesh_set_as_bulk_array(RID p_multimesh, const PoolV
if (mmi->interpolated) {
mmi->_data_curr = p_array;
_multimesh_add_to_interpolation_lists(p_multimesh, *mmi);
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
if (!Engine::get_singleton()->is_in_physics_frame()) {
static int32_t warn_count = 0;
warn_count++;
if (((warn_count % 2048) == 0) && GLOBAL_GET("debug/settings/physics_interpolation/enable_warnings")) {
WARN_PRINT("Interpolated MultiMesh transform should usually be set during physics process (possibly benign).");
}
}
#endif
return;
}
}
Expand Down
84 changes: 77 additions & 7 deletions servers/visual/visual_server_scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,37 @@ void VisualServerScene::camera_set_transform(RID p_camera, const Transform &p_tr

camera->transform = p_transform.orthonormalized();

if (_interpolation_data.interpolation_enabled && camera->interpolated) {
if (!camera->on_interpolate_transform_list) {
_interpolation_data.camera_transform_update_list_curr->push_back(p_camera);
camera->on_interpolate_transform_list = true;
}
if (_interpolation_data.interpolation_enabled) {
if (camera->interpolated) {
if (!camera->on_interpolate_transform_list) {
_interpolation_data.camera_transform_update_list_curr->push_back(p_camera);
camera->on_interpolate_transform_list = true;
}

// decide on the interpolation method .. slerp if possible
camera->interpolation_method = TransformInterpolator::find_method(camera->transform_prev.basis, camera->transform.basis);

// decide on the interpolation method .. slerp if possible
camera->interpolation_method = TransformInterpolator::find_method(camera->transform_prev.basis, camera->transform.basis);
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
if (!Engine::get_singleton()->is_in_physics_frame()) {
// Effectively a WARN_PRINT_ONCE but after a certain number of occurrences.
static int32_t warn_count = -256;
if ((warn_count == 0) && GLOBAL_GET("debug/settings/physics_interpolation/enable_warnings")) {
WARN_PRINT("Interpolated Camera transform should usually be set during physics process (possibly benign).");
}
warn_count++;
}
#endif
} else {
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
if (Engine::get_singleton()->is_in_physics_frame()) {
static int32_t warn_count = -256;
if ((warn_count == 0) && GLOBAL_GET("debug/settings/physics_interpolation/enable_warnings")) {
WARN_PRINT("Non-interpolated Camera transform should not usually be set during physics process (possibly benign).");
}
warn_count++;
}
#endif
}
}
}

Expand Down Expand Up @@ -808,6 +831,30 @@ void VisualServerScene::instance_set_transform(RID p_instance, const Transform &
#endif
instance->transform = p_transform;
_instance_queue_update(instance, true);

#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
if ((_interpolation_data.interpolation_enabled && !instance->interpolated) && (Engine::get_singleton()->is_in_physics_frame())) {
static int32_t warn_count = 0;
warn_count++;
if (((warn_count % 2048) == 0) && GLOBAL_GET("debug/settings/physics_interpolation/enable_warnings")) {
String node_name;
ObjectID id = instance->object_id;
if (id != 0) {
if (ObjectDB::get_instance(id)) {
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(id));
if (node) {
node_name = "\"" + node->get_name() + "\"";
} else {
node_name = "\"unknown\"";
}
}
}

WARN_PRINT("Non-interpolated Instance " + node_name + " transform should usually not be set during physics process (possibly benign).");
}
}
#endif

return;
}

Expand Down Expand Up @@ -861,6 +908,29 @@ void VisualServerScene::instance_set_transform(RID p_instance, const Transform &
}

_instance_queue_update(instance, true);

#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
if (!Engine::get_singleton()->is_in_physics_frame()) {
static int32_t warn_count = 0;
warn_count++;
if (((warn_count % 2048) == 0) && GLOBAL_GET("debug/settings/physics_interpolation/enable_warnings")) {
String node_name;
ObjectID id = instance->object_id;
if (id != 0) {
if (ObjectDB::get_instance(id)) {
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(id));
if (node) {
node_name = "\"" + node->get_name() + "\"";
} else {
node_name = "\"unknown\"";
}
}
}

WARN_PRINT("Interpolated Instance " + node_name + " transform should usually be set during physics process (possibly benign).");
}
}
#endif
}

void VisualServerScene::InterpolationData::notify_free_camera(RID p_rid, Camera &r_camera) {
Expand Down