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

Creating physics shapes is extremely slow #54

Closed
Zylann opened this issue Aug 25, 2019 · 11 comments
Closed

Creating physics shapes is extremely slow #54

Zylann opened this issue Aug 25, 2019 · 11 comments

Comments

@Zylann
Copy link
Owner

Zylann commented Aug 25, 2019

To put things in context, this module relies on creating a lot of unique meshes at runtime (in the hundreds). Most of it is done inside threads, but a small part is done on the main thread at a limited pace to prevent game freezing. Unfortunately, with physics turned on, Godot-related overhead is murdering that phase's performance, making the game really slow to react to dynamically loading and changing terrain (would still happen if it was done in a thread though because it's just too slow).

Creating a collision mesh is 20 times slower than creating the visual mesh. Optimizing this is important even for single edits, as they aren't as snappy as they can be.

This graph says it all, for a SINGLE 32x32x32 voxel block:

Debug build
image

Release_Tools build:
image

Debug takes 80 ms, release takes 8 ms, but overall the relative timings remain the same. There is room to at least double the speed of this.

Copying from #48:
Creating the physics mesh is litterally asking VisualServer for the vertices, which further destroys framerate not only because it triggers again the wait for the render thread, but also because it might pull the data back from the graphics card. I hope I'm wrong about the latter...
Those vertices are generated for unique voxel meshes so the cache in Mesh is also useless. But more importantly, since they are in RAM already (since I generate them), there is no point using VisualServer for anything physics-related.

Also Godot builds a BVH when TriangleMesh is created, which is completely useless when Bullet is used anyways. It basically takes almost HALF the time doing this.

One way to get around the wasted BVH would be to use set_faces() ourselves rather than using create_trimesh_shape().

@Zylann
Copy link
Owner Author

Zylann commented Aug 25, 2019

After optimizing:
image

twice as fast now. It's all on Bullet :p

@Zylann
Copy link
Owner Author

Zylann commented Aug 25, 2019

Should be fixed by d4ed637

@Zylann Zylann closed this as completed Aug 25, 2019
@TokisanGames
Copy link
Contributor

TokisanGames commented Aug 26, 2019

This is great, good work! Definitely feels snappier. However, it's crashing.

Blocky VT/heightmap is good.

Blocky VT/custom stream is good.

Everytime I try to run smooth VoxelTerrain/heightmap (your demo or mine):

Constructing VoxelDataLoader
View distance changed from 8 blocks to 16
Constructing VoxelMeshUpdater
ERROR: VectorWriteProxy<class Variant>::operator []: FATAL: Index p_index=0 out of size (((Vector<T> *)(this))->_cowdata.size()=0)
   At: C:\GD\godot\core/vector.h:49
CrashHandlerException: Program crashed
Dumping the backtrace. Please include this when reporting the bug on https://github.com/godotengine/godot/issues
[0] Array::operator[] (C:\GD\godot\core\array.cpp:75)
[1] Array::operator[] (C:\GD\godot\core\array.cpp:75)
[2] create_concave_polygon_shape (C:\GD\godot\modules\voxel\terrain\voxel_block.cpp:11)
[3] VoxelBlock::set_mesh (C:\GD\godot\modules\voxel\terrain\voxel_block.cpp:85)
[4] VoxelTerrain::_process (C:\GD\godot\modules\voxel\terrain\voxel_terrain.cpp:1060)
[5] VoxelTerrain::_notificationv (C:\GD\godot\modules\voxel\terrain\voxel_terrain.h:20)
[6] Object::notification (C:\GD\godot\core\object.cpp:933)
[7] SceneTree::_notify_group_pause (C:\GD\godot\scene\main\scene_tree.cpp:946)
[8] SceneTree::idle (C:\GD\godot\scene\main\scene_tree.cpp:515)
[9] Main::iteration (C:\GD\godot\main\main.cpp:1917)
[10] OS_Windows::run (C:\GD\godot\platform\windows\os_windows.cpp:3010)
[11] widechar_main (C:\GD\godot\platform\windows\godot_windows.cpp:162)
[12] _main (C:\GD\godot\platform\windows\godot_windows.cpp:186)
[13] main (C:\GD\godot\platform\windows\godot_windows.cpp:196)
[14] __scrt_common_main_seh (d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)
[15] BaseThreadInitThunk
-- END OF BACKTRACE --

VLT/noise almost always works fine. During the first session, it crashed after only the second or third creation. On my second session, I regenerated terrain probably 50 times and it didn't crash. On a third session with many terrain generations and hundreds of balls and collisions. It slowed my framerate, but wouldn't crash again.

Construct VoxelLodTerrain
Constructing VoxelDataLoader
Constructing VoxelMeshUpdater
Dropped 16 blocks from thread
Dropped 16 blocks from thread
Dropped 71 blocks from thread
Dropped 6 blocks from thread
Dropped 13 blocks from thread
Dropped 1 blocks from thread
Dropped 4 blocks from thread
Construct VoxelLodTerrain
Constructing VoxelDataLoader
Constructing VoxelMeshUpdater
Destroy VoxelLodTerrain
Destroying VoxelDataLoader
Destroying VoxelMeshUpdater
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
ERROR: Node not found: ../VoxelTerrain.
   At: scene\main\node.cpp:1369
ERROR: Node not found: ../VoxelTerrain.
   At: scene\main\node.cpp:1369
ERROR: Node not found: ../VoxelTerrain.
   At: scene\main\node.cpp:1369
ERROR: Node not found: ../VoxelTerrain.
   At: scene\main\node.cpp:1369
ERROR: Node not found: ../VoxelTerrain.
   At: scene\main\node.cpp:1369
ERROR: Node not found: ../VoxelTerrain.
   At: scene\main\node.cpp:1369
ERROR: Node not found: ../VoxelTerrain.
   At: scene\main\node.cpp:1369
Construct VoxelLodTerrain
Constructing VoxelDataLoader
Constructing VoxelMeshUpdater
Destroy VoxelLodTerrain
Destroying VoxelDataLoader
Destroying VoxelMeshUpdater
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
CrashHandlerException: Program crashed
Dumping the backtrace. Please include this when reporting the bug on https://github.com/godotengine/godot/issues
[0] BulletPhysicsDirectBodyState::get_contact_collider_id (C:\GD\godot\modules\bullet\rigid_body_bullet.cpp:178)
[1] BulletPhysicsDirectBodyState::get_contact_collider_id (C:\GD\godot\modules\bullet\rigid_body_bullet.cpp:178)
[2] RigidBody::_direct_state_changed (C:\GD\godot\scene\3d\physics_body.cpp:488)
[3] MethodBind1<RigidBody,Object *>::call (C:\GD\godot\core\method_bind.gen.inc:867)
[4] Object::call (C:\GD\godot\core\object.cpp:921)
[5] RigidBodyBullet::dispatch_callbacks (C:\GD\godot\modules\bullet\rigid_body_bullet.cpp:375)
[6] onBulletPreTickCallback (C:\GD\godot\modules\bullet\space_bullet.cpp:538)
[7] btDiscreteDynamicsWorld::internalSingleStepSimulation (C:\GD\godot\thirdparty\bullet\BulletDynamics\Dynamics\btDiscreteDynamicsWorld.cpp:462)
[8] btSoftRigidDynamicsWorld::internalSingleStepSimulation (C:\GD\godot\thirdparty\bullet\BulletSoftBody\btSoftRigidDynamicsWorld.cpp:91)
[9] btDiscreteDynamicsWorld::stepSimulation (C:\GD\godot\thirdparty\bullet\BulletDynamics\Dynamics\btDiscreteDynamicsWorld.cpp:435)
[10] BulletPhysicsServer::step (C:\GD\godot\modules\bullet\bullet_physics_server.cpp:1567)
[11] Main::iteration (C:\GD\godot\main\main.cpp:1903)
[12] OS_Windows::run (C:\GD\godot\platform\windows\os_windows.cpp:3010)
[13] widechar_main (C:\GD\godot\platform\windows\godot_windows.cpp:162)
[14] _main (C:\GD\godot\platform\windows\godot_windows.cpp:186)
[15] main (C:\GD\godot\platform\windows\godot_windows.cpp:196)
[16] __scrt_common_main_seh (d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)
[17] BaseThreadInitThunk
-- END OF BACKTRACE --


@TokisanGames
Copy link
Contributor

Debugging:

_process: collidable_surface (set_mesh: surface_arrays) has _p/refcount/count=2, array size=0

_process: surface is not valid {_p=0x0000...fffffef { refcount={count=???} array={...}}} on either variable

image

@TokisanGames
Copy link
Contributor

Adding a surface_arrays check to VoxelBlock:set_mesh (66) like this:
if (mesh.is_valid() && !surface_arrays.empty()) {

prevents it from crashing, however, now the terrain won't load on either your demo or mine.

@Zylann
Copy link
Owner Author

Zylann commented Aug 26, 2019

Yeah sorry I think I omitted smooth surfaces in the VoxelTerrain one.

@Zylann
Copy link
Owner Author

Zylann commented Aug 26, 2019

You can try with 7a7f5f6
I don't know what the bullet crash is, maybe a bug that existed before?

@TokisanGames
Copy link
Contributor

TokisanGames commented Aug 26, 2019

Smooth terrain looks good now, thank you.

Yeah I was just going to dismiss the physics crash, but it just happened again. And pushing it hard I was able to repeat it once more. It likely existed before, and is probably an engine bug. But I can't do it on command yet.

Also, while abusing the system, I was able to get a different type of crash from deleting and recreating the terrain while it was still loading. Though I've done this hundreds of times without issue, this one instance crashed:

Construct VoxelLodTerrain
Constructing VoxelDataLoader
Constructing VoxelMeshUpdater
Destroy VoxelLodTerrain
Destroying VoxelDataLoader
Destroying VoxelMeshUpdater
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Destroying VoxelMap
Dropped 16 blocks from thread
Dropped 24 blocks from thread
Received a block loading drop while we were still expecting it: lod0 (78, 10, 65)
Received a block loading drop while we were still expecting it: lod0 (78, 9, 65)
Received a block loading drop while we were still expecting it: lod0 (78, 10, 66)
Received a block loading drop while we were still expecting it: lod0 (78, 9, 66)
ERROR: VoxelBlockThreadManager<struct VoxelDataLoader::InputBlockData,struct VoxelDataLoader::OutputBlockData>::push_block_requests: FATAL: Condition ' *index < 0 || *index >= job.shared_input.blocks.size() ' is true.
   At: C:\GD\godot\modules\voxel\terrain\block_thread_manager.h:346
CrashHandlerException: Program crashed
Dumping the backtrace. Please include this when reporting the bug on https://github.com/godotengine/godot/issues
[0] VoxelBlockThreadManager<VoxelDataLoader::InputBlockData,VoxelDataLoader::OutputBlockData>::push_block_requests (C:\GD\godot\modules\voxel\terrain\block_thread_manager.h:346)
[1] VoxelBlockThreadManager<VoxelDataLoader::InputBlockData,VoxelDataLoader::OutputBlockData>::push_block_requests (C:\GD\godot\modules\voxel\terrain\block_thread_manager.h:346)
[2] VoxelBlockThreadManager<VoxelDataLoader::InputBlockData,VoxelDataLoader::OutputBlockData>::push (C:\GD\godot\modules\voxel\terrain\block_thread_manager.h:215)
[3] VoxelLodTerrain::_process (C:\GD\godot\modules\voxel\terrain\voxel_lod_terrain.cpp:703)
[4] VoxelLodTerrain::_notificationv (C:\GD\godot\modules\voxel\terrain\voxel_lod_terrain.h:19)
[5] Object::notification (C:\GD\godot\core\object.cpp:933)
[6] SceneTree::_notify_group_pause (C:\GD\godot\scene\main\scene_tree.cpp:946)
[7] SceneTree::idle (C:\GD\godot\scene\main\scene_tree.cpp:515)
[8] Main::iteration (C:\GD\godot\main\main.cpp:1917)
[9] OS_Windows::run (C:\GD\godot\platform\windows\os_windows.cpp:3010)
[10] widechar_main (C:\GD\godot\platform\windows\godot_windows.cpp:162)
[11] _main (C:\GD\godot\platform\windows\godot_windows.cpp:186)
[12] main (C:\GD\godot\platform\windows\godot_windows.cpp:196)
[13] __scrt_common_main_seh (d:\agent\_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)
[14] BaseThreadInitThunk
-- END OF BACKTRACE --

Overall, I won't worry about it unless you see something obvious or until I can reproduce on command.

@Zylann
Copy link
Owner Author

Zylann commented Aug 26, 2019

Looks like I was right to put a bound check here, otherwise the STL didn't do it at all and could end up in heap corruption (which would make it even harder to identify).

If you get more crashes like this, can you please open a new issue? Like I did with #52, just listing stack traces to progressively narrow down the origin.

@TokisanGames
Copy link
Contributor

Ok

@Zylann
Copy link
Owner Author

Zylann commented Aug 27, 2019

I think I found the cause of the crash db398a9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants