godot icon indicating copy to clipboard operation
godot copied to clipboard

Buggy Behavior when using TileSetAtlasSource with a Thread

Open Nexusbeeyst opened this issue 5 months ago • 4 comments

Tested versions

Reproducible in 4.4.1stable, 4.5beta1

System information

Godot v4.4.1.stable - Windows 11 (build 22631) - Multi-window, 2 monitors - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3060 (NVIDIA; 32.0.15.6094) - AMD Ryzen 7 5800X 8-Core Processor (16 threads)

Issue description

Using create_tile on TileSetAtlasSource can cause unpredictable errors and crashes. These do not occur on the main thread.

Steps to reproduce

This code attached to a node will trigger crashes, and occasionally these errors:

  <C++ Source>  servers/rendering/renderer_rd/storage_rd/texture_storage.cpp:615 @ canvas_texture_set_channel()
  <C++ Error>   Method/function failed. Returning: false
  <C++ Source>  core/object/object.cpp:1490 @ is_connected()
  <C++ Error>   Condition "!p_callable.is_valid()" is true. Returning: ERR_INVALID_PARAMETER
  <C++ Source>  core/object/object.cpp:1418 @ connect()

Although icon.svg is used as an example, using larger textures such as 512x512 to fill in tiles this way can cause these types of errors (where x and y are not consistent in value or frequency): E 0:00:00:703 get_tile_texture_region: TileSetAtlasSource has no tile at (x, y). <C++ Error> Condition "!tiles.has(p_atlas_coords)" is true. Returning: Rect2i() <C++ Source> scene/resources/2d/tile_set.cpp:5303 @ get_tile_texture_region()

extends Node2D

var thread: Thread = Thread.new()

func _ready() -> void:
	thread.start(create_tiles)

func create_tiles():
	var new_tileset_atlas_source: TileSetAtlasSource
	for i in range(64):
		new_tileset_atlas_source = TileSetAtlasSource.new()
		new_tileset_atlas_source.texture = preload("res://icon.svg")
		for x in 8:
			for y in 8:
				new_tileset_atlas_source.create_tile(Vector2i(x, y))

Minimal reproduction project (MRP)

mrp_1.zip

Nexusbeeyst avatar Jun 28 '25 02:06 Nexusbeeyst

Please provide an MRP to make this easier to test and fix:

  • A small Godot project which reproduces the issue, with no unnecessary files included. Be sure to not include the .godot folder in the archive (but keep project.godot).
  • Having an MRP is very important for contributors to be able to reproduce the bug in the same way that you are experiencing it. When testing a potential fix for the issue, contributors will use the MRP to validate that the fix is working as intended.
  • Drag and drop a ZIP archive to upload it (max 10 MB). Do not select another field until the project is done uploading.
  • Note for C# users: If your issue is not C#-specific, please upload a minimal reproduction project written in GDScript. This will make it easier for contributors to reproduce the issue locally as not everyone has a .NET setup available.

AThousandShips avatar Jun 30 '25 08:06 AThousandShips

MRP provided.

Nexusbeeyst avatar Jun 30 '25 22:06 Nexusbeeyst

I believe I am also encountering this issue, but in my case I am using ResourceLoader.LoadThreadedRequest (and waiting for the status to be loaded) to load scenes contained tilemaps built in the editor. It is intermittitent in my case but when it does I see the following error:

E 0:00:04:790 get_tile_texture_region: TileSetAtlasSource has no tile at (1, 1). <C++ Error> Condition "!tiles.has(p_atlas_coords)" is true. Returning: Rect2i() <C++ Source> scene/resources/2d/tile_set.cpp:5303 @ get_tile_texture_region()

E 0:00:04:791 canvas_texture_set_channel: Parameter "ct" is null. <C++ Source> servers/rendering/renderer_rd/storage_rd/texture_storage.cpp:615 @ canvas_texture_set_channel()

This is in 4.4.1.stable.mono

grampabacon avatar Sep 13 '25 12:09 grampabacon

Can somewhat reproduce (not sure about the exact errors) on: Godot v4.6.dev (25203e24c) - Windows 11 (build 26100) - Multi-window, 2 monitors - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 4080 SUPER (NVIDIA; 32.0.15.8180) - AMD Ryzen 7 7800X3D 8-Core Processor (16 threads) - 63.11 GiB memory

The MRP always crashes, when running the project, with many different Debugger logs and backtraces, here is what I got (the backtrace is only the unique part to make it more readable, the common part of the backtrace is at the end of the comment):

1

Errors

None

Backtrace

[1] Ref<Texture2D>::operator==(Ref<Texture2D> const&) const (./core/object/ref_counted.h:109)
[2] CanvasTexture::set_diffuse_texture(Ref<Texture2D> const&) (scene/main/canvas_item.cpp:1788)
[3] TileSetAtlasSource::_update_padded_texture() (scene/resources/2d/tile_set.cpp:5725)

2

Errors

Image

Backtrace

[1] unsigned int HashMapHasherDefault::hash<int>(int const&) (./core/templates/hashfuncs.h:179)
[2] HashMap<int, TileData*, HashMapHasherDefault, HashMapComparatorDefault<int, void>, DefaultTypedAllocator<HashMapElement<int, TileData*> > >::_hash(int const&) (./core/templates/hash_map.h:86)
[3] HashMap<int, TileData*, HashMapHasherDefault, HashMapComparatorDefault<int, void>, DefaultTypedAllocator<HashMapElement<int, TileData*> > >::insert(int const&, TileData* const&, bool) (./core/templates/hash_map.h:572)
[4] HashMap<int, TileData*, HashMapHasherDefault, HashMapComparatorDefault<int, void>, DefaultTypedAllocator<HashMapElement<int, TileData*> > >::HashMap(HashMap<int, TileData*, HashMapHasherDefault, HashMapComparatorDefault<int, void>, DefaultTypedAllocator<HashMapElement<int, TileData*> > > const&) (./core/templates/hash_map.h:593)
[5] TileSetAtlasSource::TileAlternativesData::TileAlternativesData(TileSetAtlasSource::TileAlternativesData const&) (scene/resources/2d/tile_set.h:637)
[6] KeyValue<Vector2i, TileSetAtlasSource::TileAlternativesData>::KeyValue(KeyValue<Vector2i, TileSetAtlasSource::TileAlternativesData> const&) (./core/templates/pair.h:71)
[7] TileSetAtlasSource::_create_padded_image_texture(Ref<Texture2D> const&) (scene/resources/2d/tile_set.cpp:5640)
[8] TileSetAtlasSource::_update_padded_texture() (scene/resources/2d/tile_set.cpp:5724)

3

Errors

Image

Backtrace

Same as 2

4

Errors

Image

Backtrace

Only happened once and I didn't copy the backtrace

5

Errors

Image

Backtrace

[1] HashMap<Vector2i, TileSetAtlasSource::TileAlternativesData, HashMapHasherDefault, HashMapComparatorDefault<Vector2i, void>, DefaultTypedAllocator<HashMapElement<Vector2i, TileSetAtlasSource::TileAlternativesData> > >::operator[](Vector2i const&) const (./core/templates/hash_map.h:554)
[2] TileSetAtlasSource::get_tile_texture_region(Vector2i, int) const (scene/resources/2d/tile_set.cpp:5285)
[3] TileSetAtlasSource::_create_padded_image_texture(Ref<Texture2D> const&) (scene/resources/2d/tile_set.cpp:5643)
[4] TileSetAtlasSource::_update_padded_texture() (scene/resources/2d/tile_set.cpp:5724)

6 (with varying amount had up to 352 errors)

Errors

Image Image

Backtrace

[1] Vector2i::operator==(Vector2i const&) const (./core/math/vector2i.h:232)
[2] HashMapComparatorDefault<Vector2i, void>::compare(Vector2i const&, Vector2i const&) (./core/templates/hashfuncs.h:303)
[3] HashMap<Vector2i, TileSetAtlasSource::TileAlternativesData, HashMapHasherDefault, HashMapComparatorDefault<Vector2i, void>, DefaultTypedAllocator<HashMapElement<Vector2i, TileSetAtlasSource::TileAlternativesData> > >::_lookup_idx_unchecked(Vector2i const&, unsigned int, unsigned int&) const (./core/templates/hash_map.h:130)
[4] HashMap<Vector2i, TileSetAtlasSource::TileAlternativesData, HashMapHasherDefault, HashMapComparatorDefault<Vector2i, void>, DefaultTypedAllocator<HashMapElement<Vector2i, TileSetAtlasSource::TileAlternativesData> > >::_lookup_idx(Vector2i const&, unsigned int&) const (./core/templates/hash_map.h:111)
[5] HashMap<Vector2i, TileSetAtlasSource::TileAlternativesData, HashMapHasherDefault, HashMapComparatorDefault<Vector2i, void>, DefaultTypedAllocator<HashMapElement<Vector2i, TileSetAtlasSource::TileAlternativesData> > >::has(Vector2i const&) const (./core/templates/hash_map.h:322)
[6] TileSetAtlasSource::get_tile_texture_region(Vector2i, int) const (scene/resources/2d/tile_set.cpp:5284)
[7] TileSetAtlasSource::_create_padded_image_texture(Ref<Texture2D> const&) (scene/resources/2d/tile_set.cpp:5643)
[8] TileSetAtlasSource::_update_padded_texture() (scene/resources/2d/tile_set.cpp:5724)

Common backtrace part:

================================================================
CrashHandlerException: Program crashed with signal 11
Engine version: Godot Engine v4.6.dev.custom_build (25203e24c403afdba4370249204b83cb830e4809)
Dumping the backtrace. Please include this when reporting the bug on: https://github.com/godotengine/godot/issues
[4] void call_with_variant_args_helper<TileSetAtlasSource>(TileSetAtlasSource*, void (TileSetAtlasSource::*)(), Variant const**, Callable::CallError&, IndexSequence<>) (./core/variant/binder_common.h:224)
[5] void call_with_variant_args<TileSetAtlasSource>(TileSetAtlasSource*, void (TileSetAtlasSource::*)(), Variant const**, int, Callable::CallError&) (./core/variant/binder_common.h:338)
[6] CallableCustomMethodPointer<TileSetAtlasSource, void>::call(Variant const**, int, Variant&, Callable::CallError&) const (./core/object/callable_method_pointer.h:103)
[7] Callable::callp(Variant const**, int, Variant&, Callable::CallError&) const (core/variant/callable.cpp:57)
[8] CallQueue::_call_function(Callable const&, Variant const*, int, bool) (core/object/message_queue.cpp:220)
[9] CallQueue::flush() (core/object/message_queue.cpp:268)
[10] SceneTree::physics_process(double) (scene/main/scene_tree.cpp:647)
[11] Main::iteration() (main/main.cpp:4831)
[12] OS_Windows::run() (platform/windows/os_windows.cpp:2346)
[13] widechar_main(int, wchar_t**) (platform/windows/godot_windows.cpp:99)
[14] _main() (platform/windows/godot_windows.cpp:126)
[15] main (platform/windows/godot_windows.cpp:145)
[16] ShimMainCRTStartup (platform/windows/cpu_feature_validation.c:74)
-- END OF C++ BACKTRACE --
================================================================

TheDying0fLight avatar Dec 02 '25 21:12 TheDying0fLight