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

Fix lagging TileSet view for large TileSets in Editor #84963

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Al-p-i
Copy link

@Al-p-i Al-p-i commented Nov 16, 2023

The TileSet panel is lagging on big TileSets since on every draw cycle the whole grid re-draws the rectangles.
For TileSets of size > 100x100 the TileSet panel becomes unusable.

Relevant discussion:
#72405 (comment)

This PR replaces the grid made of rectangles (quadratic of the size of TileSet) with grid made of lines (linear) within Atlas view.

This optimisation solves the lag.

Profiling before the fix shows that drawing and removing rectangles eats up all the CPU.
Screenshot 2023-11-13 at 00 51 55

Profiling after the fix shows that the grid drawing only takes 1.7% of the CPU time:
Screenshot 2023-11-16 at 00 06 59

Replace grid made of rectangles (quadratic of the size of TileSet) with grid made of lines (linear)
@akien-mga
Copy link
Member

Would be worth testing with both OpenGL (native and ANGLE) and Vulkan (Metal) to make sure it's an optimization for both. Drawing lines in OpenGL can have horrendous performance on some hardware.

See #84591 for context.

@groud
Copy link
Member

groud commented Nov 16, 2023

Thanks for the contribution!

This PR replaces the grid made of rectangles (quadratic of the size of TileSet) with grid made of lines (linear) within Atlas view.

I believe this is not the right solution. The problem arises when you have a separation value higher than 0, and a texture region size bigger than the tile size. This is often the case for isometric/hexagonal tile shapes. In such a case, each tile has a texture region clearly separated from the others, making it a rectangle around the tile, not really a "grid". So this solution cannot be used.

I think drawing a rect should not use that much CPU, and the problem is likely elsewhere. However I guess some drivers might be bad at drawing rects anyway, so we might use the another solution: we could use an ArrayMesh instead.

You can have a look to how it's done in tile_set.cpp, as there's a tile_lines_mesh variable that is used to draw the tile shapes in the grid.

@YuriSizov YuriSizov added this to the 4.3 milestone Nov 16, 2023
@Al-p-i
Copy link
Author

Al-p-i commented Nov 16, 2023

Thanks for the contribution!

This PR replaces the grid made of rectangles (quadratic of the size of TileSet) with grid made of lines (linear) within Atlas view.

I believe this is not the right solution. The problem arises when you have a separation value higher than 0, and a texture region size bigger than the tile size. This is often the case for isometric/hexagonal tile shapes. In such a case, each tile has a texture region clearly separated from the others, making it a rectangle around the tile, not really a "grid". So this solution cannot be used.

I think drawing a rect should not use that much CPU, and the problem is likely elsewhere. However I guess some drivers might be bad at drawing rects anyway, so we might use the another solution: we could use an ArrayMesh instead.

You can have a look to how it's done in tile_set.cpp, as there's a tile_lines_mesh variable that is used to draw the tile shapes in the grid.

Thank you for the context!
Let me look at the ArrayMesh

I think drawing a rect should not use that much CPU, and the problem is likely elsewhere.

I'd bet drawing rectangles was not the problem too.
But 2 facts show that it actually is at least on my setup:

  • the profile above shows that _draw_base_tiles_texture_grid was the chokepoint before the fix, it's not anymore after
  • disabling this grid or applying my patch fixes the lagging for me from absolutely unusable to flying

I was testing on MacBook pro m1 with Vulkan, and I can test on iMac on Intel.
For context: the time slot that I am profiling in both cases is when I am dragging a mouse over the TileSet window.

@groud
Copy link
Member

groud commented Nov 16, 2023

I'd bet drawing rectangles was not the problem too.
But 2 facts show that it actually is at least on my setup:
the profile above shows that _draw_base_tiles_texture_grid was the chokepoint before the fix, it's not anymore after
disabling this grid or applying my patch fixes the lagging for me from absolutely unusable to flying

Oh no, I agree that drawing rectangles was indeed the problem. By "elsewhere", I meant more, like, in a lower level of the code (either the rendering servers or the graphics drivers). Basically that means that fixing the problem here will solve the TileMap editor being slow, but we'll still have an underlying problem of draw_rect being slow anyway.

But yeah, any workaround will work for now, and I believe ArrayMesh should work.

@sunnyholyd
Copy link

hi guys, Could you please let me know when we can expect this issue to be resolved?

@Al-p-i
Copy link
Author

Al-p-i commented Dec 2, 2023

hi guys, Could you please let me know when we can expect this issue to be resolved?

Hi, I'll be looking at it shortly
But im terms of release - it is marked for 4.3 right now

@t4y
Copy link

t4y commented May 24, 2024

Any progress on this? Maybe this could help: copying and adapting the following from _draw_base_tiles_shape_grid() I found the tileset editor view to be significantly more responsive on a large tileset, going from barely usable to slightly sluggish. Unfortunately I don't understand the code enough to know if it addresses the issues @groud mentioned for the line drawing approach.

index 039213e545..c3f1b34ccd 100644
--- a/editor/plugins/tiles/tile_atlas_view.cpp
+++ b/editor/plugins/tiles/tile_atlas_view.cpp
@@ -337,7 +337,10 @@ void TileAtlasView::_draw_base_tiles_texture_grid() {
 					}
 				} else {
 					// Draw the grid.
-					base_tiles_texture_grid->draw_rect(Rect2i(origin, texture_region_size), Color(0.7, 0.7, 0.7, 0.1), false);
+					Transform2D tile_xform;
+					tile_xform.set_origin(Rect2(origin, texture_region_size).get_center());
+					tile_xform.set_scale(texture_region_size);
+					tile_set->draw_tile_shape(base_tiles_texture_grid, tile_xform, Color(0.7, 0.7, 0.7, 0.1));
 				}
 			}
 		}

t4y added a commit to t4y/godot that referenced this pull request Jun 4, 2024
As reported in godotengine#72405 and godotengine#84963 the tileset editor becomes unusable
when editing large tileset atlases due to repeated calls to `draw_rect`
to draw the tile grid.

This commit is a workaround which replaces `CanvasItem::draw_rect`
calls with `TileSet::draw_tile_shape` which does not seem to display
the same performance issues.
@KoBeWi KoBeWi modified the milestones: 4.3, 4.4 Jul 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants