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

Fatal error (Index p_index = 0 is out of bounds) when closing the game #341

Open
bialpio opened this issue Mar 24, 2024 · 5 comments
Open

Comments

@bialpio
Copy link

bialpio commented Mar 24, 2024

Terrain3D version

v0.9.1-beta

System information

Godot v4.2.1.stable - Windows 10.0.22631 - Vulkan (Forward+) - dedicated AMD Radeon RX 7900 XT (Advanced Micro Devices, Inc.; 31.0.24019.1006) - AMD Ryzen 9 7900 12-Core Processor (24 Threads)

Is the issue reproducable in the demo?

No

Issue description

When closing the scene preview of a scene that contains only a Camera and Terrain3D node, the Godot console shows:

ERROR: FATAL: Index p_index = 0 is out of bounds (shapes.size() = 0).
   at: get_shape (servers/physics_3d/godot_collision_object_3d.h:124)

I have manually compiled the Terrain3D and was able to grab the stack trace in WinDbg:

0:000> k
 # Child-SP          RetAddr               Call Site
00 000000bb`cfffea60 00007ff6`331deb71     Godot_v4_2_1_stable_win64!ZN6embree13TaskScheduler12startThreadsEv+0x256f185
01 000000bb`cfffeac0 00007ffa`e3ace50a     Godot_v4_2_1_stable_win64!ZN6embree13TaskScheduler12startThreadsEv+0x23da2f1
02 000000bb`cfffeaf0 00007ffa`e3bc6b26     libterrain_windows_debug_x86_64!godot::internal::_call_native_mb_ret<godot::RID,godot::RID const *,__int64 *>+0x7a [F:\Projekty\GodotProjects\Terrain3D\godot-cpp\include\godot_cpp\core\engine_ptrcall.hpp @ 62] 
03 000000bb`cfffeb50 00007ffa`e394033e     libterrain_windows_debug_x86_64!godot::PhysicsServer3D::body_get_shape+0x1a6 [F:\Projekty\GodotProjects\Terrain3D\godot-cpp\gen\src\classes\physics_server3d.cpp @ 477] 
04 000000bb`cfffebe0 00007ffa`e393d733     libterrain_windows_debug_x86_64!Terrain3D::_destroy_collision+0x17e [F:\Projekty\GodotProjects\Terrain3D\src\terrain_3d.cpp @ 477] 
05 000000bb`cfffee10 00007ffa`e3946e70     libterrain_windows_debug_x86_64!Terrain3D::_clear+0x4f3 [F:\Projekty\GodotProjects\Terrain3D\src\terrain_3d.cpp @ 248] 
06 000000bb`cfffef70 00007ffa`e3938ed0     libterrain_windows_debug_x86_64!Terrain3D::_notification+0x530 [F:\Projekty\GodotProjects\Terrain3D\src\terrain_3d.cpp @ 1095] 
07 000000bb`cffff2e0 00007ff6`33f5c91f     libterrain_windows_debug_x86_64!Terrain3D::notification_bind+0x50 [F:\Projekty\GodotProjects\Terrain3D\src\terrain_3d.h @ 25] 
08 000000bb`cffff320 00007ff6`3232331d     Godot_v4_2_1_stable_win64!ZN6embree13TaskScheduler12startThreadsEv+0x315809f
09 000000bb`cffff360 00007ff6`323231c0     Godot_v4_2_1_stable_win64!ZN6embree13TaskScheduler12startThreadsEv+0x151ea9d
0a 000000bb`cffff470 00007ff6`323231c0     Godot_v4_2_1_stable_win64!ZN6embree13TaskScheduler12startThreadsEv+0x151e940
0b 000000bb`cffff580 00007ff6`32324112     Godot_v4_2_1_stable_win64!ZN6embree13TaskScheduler12startThreadsEv+0x151e940
0c 000000bb`cffff690 00007ff6`323799ea     Godot_v4_2_1_stable_win64!ZN6embree13TaskScheduler12startThreadsEv+0x151f892
0d 000000bb`cffff6f0 00007ff6`305b74c4     Godot_v4_2_1_stable_win64!ZN6embree13TaskScheduler12startThreadsEv+0x157516a
0e 000000bb`cffff750 00007ff6`34bd56c3     Godot_v4_2_1_stable_win64+0x874c4
0f 000000bb`cffffc20 00007ff6`305312ee     Godot_v4_2_1_stable_win64!ZN6embree13TaskScheduler12startThreadsEv+0x3dd0e43
10 000000bb`cffffc70 00007ff6`305313e6     Godot_v4_2_1_stable_win64+0x12ee
11 000000bb`cffffcc0 00007ffb`9f85257d     Godot_v4_2_1_stable_win64+0x13e6
12 000000bb`cffffcf0 00007ffb`a03eaa58     KERNEL32!BaseThreadInitThunk+0x1d
13 000000bb`cffffd20 00000000`00000000     ntdll!RtlUserThreadStart+0x28

With this and looking at Godot's servers/physics_3d/godot_collision_object_3d.h:124, it looks like Terrain3D::_destroy_collision() should check the body shape count before calling into body_get_shape(_static_body, 0) here.

To confirm, I have added extra information at terrain_3d.cpp:475:
LOG(INFO, "Freeing physics body, shape count ", PhysicsServer3D::get_singleton()->body_get_shape_count(_static_body));

With that change, I see the logs contain the following:
Terrain3D::_destroy_collision: Freeing physics body, shape count 0

I have attached the log without my custom changes. I can try to grab more information if required.

Logs

 bialp  D:  Programy  Godot_v4.2.1-stable_win64.exe  .\Godot_v4.2.1-stable_win64_console.exe --terrain3d-debug=DEBUG --path F:/Projekty/GodotProjects/CodeGenesis --position "1344,720" res://Game.tscn
Godot Engine v4.2.1.stable.official.b09f793f5 - https://godotengine.org
Vulkan API 1.3.277 - Forward+ - Using Vulkan Device #0: AMD - AMD Radeon RX 7900 XT

ERROR: Attempt to register extension class 'Terrain3D', which appears to be already registered.
   at: (core/extension/gdextension.cpp:386)
ERROR: Attempt to register extension class 'Terrain3DMaterial', which appears to be already registered.
   at: (core/extension/gdextension.cpp:386)
ERROR: Attempt to register extension class 'Terrain3DStorage', which appears to be already registered.
   at: (core/extension/gdextension.cpp:386)
ERROR: Attempt to register extension class 'Terrain3DTexture', which appears to be already registered.
   at: (core/extension/gdextension.cpp:386)
ERROR: Attempt to register extension class 'Terrain3DTextureList', which appears to be already register.
   at: (core/extension/gdextension.cpp:386)
ERROR: Attempt to register extension class 'Terrain3DEditor', which appears to be already registered.
   at: (core/extension/gdextension.cpp:386)
Terrain3D::_clear: Clearing the terrain
Terrain3D::_initialize: Checking material, storage, texture_list, signal, and mesh initialization
Terrain3D::_initialize: Creating blank material
Terrain3D::_initialize: Creating blank texture list
Terrain3D::_initialize: Connecting texture_list.textures_changed to _material->_update_texture_arrays()
Terrain3D::_initialize: Connecting region_size_changed signal to _material->_set_region_size()
Terrain3D::_initialize: Connecting regions_changed signal to _material->_update_regions()
Terrain3D::_initialize: Connecting height_maps_changed signal to update_aabbs()
Terrain3D::set_material: Setting material
Terrain3DMaterial::~Terrain3DMaterial: Destroying material
Terrain3D::_clear: Clearing the terrain
Terrain3D::_initialize: Checking material, storage, texture_list, signal, and mesh initialization
Terrain3D::_initialize: Connecting texture_list.textures_changed to _material->_update_texture_arrays()
Terrain3D::_initialize: Connecting region_size_changed signal to _material->_set_region_size()
Terrain3D::_initialize: Connecting regions_changed signal to _material->_update_regions()
Terrain3D::set_texture_list: Setting texture list
Terrain3D::_clear: Clearing the terrain
Terrain3D::_initialize: Checking material, storage, texture_list, signal, and mesh initialization
Terrain3D::_initialize: Connecting texture_list.textures_changed to _material->_update_texture_arrays()
Terrain3D::_notification: NOTIFICATION_ENTER_WORLD
Terrain3D::_notification: NOTIFICATION_ENTER_TREE
Terrain3D::_initialize: Checking material, storage, texture_list, signal, and mesh initialization
Terrain3DMaterial::initialize: Initializing material
Terrain3DMaterial::_preload_shaders: Loaded shader insert: uniforms
Terrain3DMaterial::_preload_shaders: Loaded shader insert: TEXTURE_SAMPLERS_LINEAR
Terrain3DMaterial::_preload_shaders: Loaded shader insert: TEXTURE_SAMPLERS_NEAREST
Terrain3DMaterial::_preload_shaders: Loaded shader insert: world_noise
Terrain3DMaterial::_preload_shaders: Loaded shader insert: WORLD_NOISE1
Terrain3DMaterial::_preload_shaders: Loaded shader insert: WORLD_NOISE2
Terrain3DMaterial::_preload_shaders: Loaded shader insert: auto_shader
Terrain3DMaterial::_preload_shaders: Loaded shader insert: AUTO_SHADER_UNIFORMS
Terrain3DMaterial::_preload_shaders: Loaded shader insert: AUTO_SHADER_TEXTURE_ID
Terrain3DMaterial::_preload_shaders: Loaded shader insert: TEXTURE_ID
Terrain3DMaterial::_preload_shaders: Loaded shader insert: dual_scaling
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DUAL_SCALING_UNIFORMS
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DUAL_SCALING_VERTEX
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DUAL_SCALING_BASE
Terrain3DMaterial::_preload_shaders: Loaded shader insert: UNI_SCALING_BASE
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DUAL_SCALING_OVERLAY
Terrain3DMaterial::_preload_shaders: Loaded shader insert: debug_views
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DEBUG_CHECKERED
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DEBUG_GREY
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DEBUG_HEIGHTMAP
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DEBUG_COLORMAP
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DEBUG_ROUGHMAP
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DEBUG_CONTROL_TEXTURE
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DEBUG_CONTROL_BLEND
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DEBUG_AUTOSHADER
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DEBUG_TEXTURE_HEIGHT
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DEBUG_TEXTURE_NORMAL
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DEBUG_TEXTURE_ROUGHNESS
Terrain3DMaterial::_preload_shaders: Loaded shader insert: DEBUG_VERTEX_GRID
Terrain3DMaterial::_preload_shaders: Loaded shader insert: editor_functions
Terrain3DMaterial::_preload_shaders: Loaded shader insert: EDITOR_NAVIGATION
Terrain3DMaterial::_preload_shaders: Loaded shader insert: main
Terrain3DMaterial::_set_region_size: Setting region size in material: 1024
Terrain3DMaterial::initialize: Mat RID: RID(4114578669577), _shader RID: RID(4118873636876)
Terrain3DMaterial::_update_shader: Updating shader
Terrain3DMaterial::_generate_shader_code: Generating default shader code
Terrain3DMaterial::_update_shader: Material rid: RID(4114578669577), shader rid: RID(4118873636876)
Terrain3DMaterial::_update_shader: _active_params: [&"_region_size", &"_region_texel_size", &"_mesh_ver]
Terrain3DUtil::print_dict: Printing Dictionary: _shader_params
Terrain3DUtil::print_dict: Key: _mouse_layer, Value: 2147483648
Terrain3DUtil::print_dict: Key: blend_sharpness, Value: <null>
Terrain3DUtil::print_dict: Key: height_blending, Value: <null>
Terrain3DUtil::print_dict: Key: macro_variation1, Value: <null>
Terrain3DUtil::print_dict: Key: macro_variation2, Value: <null>
Terrain3DUtil::print_dict: Key: noise1_angle, Value: <null>
Terrain3DUtil::print_dict: Key: noise1_offset, Value: <null>
Terrain3DUtil::print_dict: Key: noise1_scale, Value: <null>
Terrain3DUtil::print_dict: Key: noise2_scale, Value: <null>
Terrain3DUtil::print_dict: Key: noise3_scale, Value: <null>
Terrain3DUtil::print_dict: Key: noise_texture, Value: <NoiseTexture2D#-9223372009977674545>
Terrain3DMaterial::set_mesh_vertex_spacing: Setting mesh vertex spacing in material: 1
Terrain3DMaterial::_update_regions: Updating region maps in shader
Terrain3DMaterial::_update_regions: Height map RID: RID(0)
Terrain3DMaterial::_update_regions: Control map RID: RID(0)
Terrain3DMaterial::_update_regions: Color map RID: RID(0)
Terrain3DMaterial::_update_regions: _region_map.size(): 256
Terrain3DMaterial::_update_regions: Region map
Terrain3DMaterial::_update_regions: Region_offsets size: 0 []
Terrain3DMaterial::_generate_region_blend_map: Regenerating (512, 512) region blend map
Terrain3DGeneratedTex::create: RenderingServer creating Texture2D
Terrain3DUtil::dump_gen: Generated blend_map RID: RID(4252017623075), dirty: false, image: <Image#-9223>
Terrain3DTextureList::update_list: Reconnecting texture signals
Terrain3DMaterial::_update_texture_arrays: Updating texture arrays in shader
Terrain3D::_setup_mouse_picking: Setting up mouse picker and get_intersection viewport, camera & screend
Terrain3D::set_mouse_layer: Setting mouse layer: 32 (2147483648) on terrain mesh, material, mouse camerd
Terrain3D::set_render_layers: Setting terrain render layers to: 2147483649
Terrain3DMaterial::set_shader_param: Setting shader parameter: _mouse_layer
Terrain3D::_build: Building the terrain meshes
Terrain3DGeoClipMap::generate: Generating meshes of size: 48 levels: 7
Terrain3DGeoClipMap::_create_mesh: Creating mesh via the Rendering server
Terrain3DGeoClipMap::_create_mesh: Setting custom aabb: (0, 0, 0), (49, 0.1, 49)
Terrain3DGeoClipMap::_create_mesh: Creating mesh via the Rendering server
Terrain3DGeoClipMap::_create_mesh: Setting custom aabb: (-96, 0, -96), (193, 0.1, 193)
Terrain3DGeoClipMap::_create_mesh: Creating mesh via the Rendering server
Terrain3DGeoClipMap::_create_mesh: Setting custom aabb: (-97.5, 0, -97.5), (194.5, 0.1, 194.5)
Terrain3DGeoClipMap::_create_mesh: Creating mesh via the Rendering server
Terrain3DGeoClipMap::_create_mesh: Setting custom aabb: (-97.5, 0, -97.5), (194.5, 0.1, 194.5)
Terrain3DGeoClipMap::_create_mesh: Creating mesh via the Rendering server
Terrain3DGeoClipMap::_create_mesh: Setting custom aabb: (-97.5, 0, -97.5), (291.5, 0.1, 291.5)
Terrain3D::_build: Creating mesh instances
Terrain3D::_build_collision: Building collision with physics server
Terrain3D::_update_collision: Collision creation time: 0 ms
Terrain3D::_notification: NOTIFICATION_READY
Terrain3D::_initialize: Checking material, storage, texture_list, signal, and mesh initialization
Terrain3D::__process: camera is null, getting the current one
Terrain3D::_grab_camera: Connecting to the in-game viewport camera
Terrain3D::_notification: NOTIFICATION_EXIT_TREE
Terrain3D::_clear: Clearing the terrain
Terrain3D::_destroy_collision: Freeing physics body
ERROR: FATAL: Index p_index = 0 is out of bounds (shapes.size() = 0).
   at: get_shape (servers/physics_3d/godot_collision_object_3d.h:124)
@TokisanGames
Copy link
Owner

Thanks for the detailed report.

v0.9.1-beta

Is this reproducible in a nightly build from main in your project?

Is the issue reproducible in the demo?
No

I'm curious why this is only in your project. It doesn't happen for you in the demo? And it doesn't happen for me. This needs further exploration as to what conditions you've created in your project to trigger these errors.

When closing the scene preview of a scene that contains only a Camera and Terrain3D node, the Godot console shows:

What is a scene preview and how are you creating it?

Does this scene contain any scripts attached to those nodes? Are the Camera3D and Terrain3D attached to a parent Node3D or what structure? What other nodes are in the scene?

In this scene preview, does it quit automatically via your script or manually?

With this and looking at Godot's servers/physics_3d/godot_collision_object_3d.h:124, it looks like Terrain3D::_destroy_collision() should check the body shape count before calling into body_get_shape(_static_body, 0) here.

There is already a check in this section to make sure the staticbody that contains the shape is valid. What's more concerning is why you don't have a collision shape. If you have collision enabled, the shape should exist to be destroyed. If you don't, the staticbody will be null and it won't try to destroy it.

ERROR: Attempt to register extension class 'Terrain3D', which appears to be already registered.
at: (core/extension/gdextension.cpp:386)
ERROR: Attempt to register extension class 'Terrain3DMaterial', which appears to be already registered.
at: (core/extension/gdextension.cpp:386)
ERROR: Attempt to register extension class 'Terrain3DStorage', which appears to be already registered.
at: (core/extension/gdextension.cpp:386)
ERROR: Attempt to register extension class 'Terrain3DTexture', which appears to be already registered.
at: (core/extension/gdextension.cpp:386)
ERROR: Attempt to register extension class 'Terrain3DTextureList', which appears to be already register.
at: (core/extension/gdextension.cpp:386)
ERROR: Attempt to register extension class 'Terrain3DEditor', which appears to be already registered.
at: (core/extension/gdextension.cpp:386)

I don't get this on the demo or in my project. Do you have two copies of Terrain3D under addons in different folders? Whatever is causing this might be the problem. I presume that you don't get this in the demo project?

Terrain3D::_build_collision: Building collision with physics server
Terrain3D::_update_collision: Collision creation time: 0 ms
Terrain3D::_notification: NOTIFICATION_READY
Terrain3D::_initialize: Checking material, storage, texture_list, signal, and mesh initialization
Terrain3D::__process: camera is null, getting the current one
Terrain3D::_grab_camera: Connecting to the in-game viewport camera
Terrain3D::_notification: NOTIFICATION_EXIT_TREE
Terrain3D::_clear: Clearing the terrain
Terrain3D::_destroy_collision: Freeing physics body
ERROR: FATAL: Index p_index = 0 is out of bounds (shapes.size() = 0).
at: get_shape (servers/physics_3d/godot_collision_object_3d.h:124)

How much time is elapsing between build collision / READY and EXIT_TREE? Are they instant, within the same frame caused by a script quitting? Or are there multiple frames rendered at least in between?

@bialpio
Copy link
Author

bialpio commented Mar 27, 2024

Replying with some easier-to-get answers to your questions. :)

What is a scene preview and how are you creating it?

It may be my wrong use of terminology, I'm just using F6 to preview the current scene.

Does this scene contain any scripts attached to those nodes? Are the Camera3D and Terrain3D attached to a parent Node3D or what structure? What other nodes are in the scene?

The scene contains:

  • Node3D, let's call it A.
  • Camera3D, let's call it B. It is a child of A.
  • Terrain3D, let's call it C. It is a child of A. Terrain Storage was saved as a *.res file - this was the only thing that I had to do in order for the warnings on this node to disappear.

I have attached the smallest project that reproduces the issue. TerrainRepro.zip

In this scene preview, does it quit automatically via your script or manually?

I'm closing the preview by clicking the X button of the window.

I don't get this on the demo or in my project. Do you have two copies of Terrain3D under addons in different folders? Whatever is causing this might be the problem. I presume that you don't get this in the demo project?

You're right, it was my bad - I was making copies of the addons folder (in order to rapidly switch between the Terrain3D that I downloaded from github and the one I built myself) thinking that it's a specially named folder from Godot's perspective. The repro project that I attached should not have this problem.

How much time is elapsing between build collision / READY and EXIT_TREE? Are they instant, within the same frame caused by a script quitting? Or are there multiple frames rendered at least in between?

I assume there's multiple frames in between. When the scene is loaded, the log reaches the Terrain3D::_grab_camera: Connecting to the in-game viewport camera line. The subsequent line (NOTIFICATION_EXIT_TREE) only shows up when I close the preview window.

@bialpio
Copy link
Author

bialpio commented Mar 27, 2024

I think I may know what the problem is. Terrain3D::_update_collision() will not reach line 446 if there are no regions on the Terrain3D, therefore, when destroying collisions, there are no available shapes added to the _static_body. I'm not sure if this is the right diagnosis though - in _update_collisions(), we add one shape per region, but in _destroy_collisions(), we're only freeing the shape that is at index 0 - shouldn't that code enumerate over all shapes added to the _static_body?

@bialpio
Copy link
Author

bialpio commented Mar 27, 2024

I have tried with my own custom build yet again. The changes I've made:

  • Just prior to line 446, I have added a LOG(DEBUG, "Adding shape to _static_body, region index ", i);.
  • I kept the LOG(INFO, "Freeing physics body, shape count ", PhysicsServer3D::get_singleton()->body_get_shape_count(_static_body)); that I have added previously at line 475.

The log excerpt is:

Terrain3D::_build: Creating mesh instances
Terrain3D::_build_collision: Building collision with physics server
Terrain3D::_update_collision: Collision creation time: 0 ms
Terrain3D::_notification: NOTIFICATION_READY
Terrain3D::_initialize: Checking material, storage, texture_list, signal, and mesh initialization
Terrain3D::__process: camera is null, getting the current one
Terrain3D::_grab_camera: Connecting to the in-game viewport camera
Terrain3D::_notification: NOTIFICATION_EXIT_TREE
Terrain3D::_clear: Clearing the terrain
Terrain3D::_destroy_collision: Freeing physics body, shape count 0
ERROR: FATAL: Index p_index = 0 is out of bounds (shapes.size() = 0).
   at: get_shape (servers/physics_3d/godot_collision_object_3d.h:124)

Notably, my newly added log is not present, presumably because there are no regions on the Terrain3D.

@TokisanGames
Copy link
Owner

I see. If there are no regions, the static body is still created but no shapes are made, so it should not assume there is a region to destroy. We'll need to make sure #278 fixes this.

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

No branches or pull requests

2 participants