• 2D
  • Performance issues with custom 2D drawing

I have a CanvasItem node above my Tilemap which I use for debugging my navigation system.

The CanvasItem has an overridden _Draw() function, which is only called once after the navigation nodes have been setup. This puts a layer of graphics (circles and lines) over my Tilemap, so I can see that the nodes have been configured correctly. This function is understandably slow as it has to iterate over my entire navigation array.

I have put a GD.Print(“Draw called”; at the beginning of the _Draw() function to confirm that it is only ever called once.

But after this function is called, the game slows down, extremely slowly as if it is redrawing the node map each time. The documentation suggests that the draw is only called to generate the image, and a cached version is used thereafter, which should be just a fast texture blit...

What have I missed?

Maybe there is an infinite loop, or something similar? To help figure out what is going on, I'd add a print statement to the end of the draw function so you can make sure the code is going through the entire execution.

Bare in mind that a print call can also slow down the script significantly if it's called a lot.

@SIsilicon28 said: Bare in mind that a print call can also slow down the script significantly if it's called a lot.

Indeed, I only added the print because I experienced The slowdown which I hypothesised was due to the _Draw() function being called repeatedly...

@TwistedTwigleg said: Maybe there is an infinite loop, or something similar? To help figure out what is going on, I'd add a print statement to the end of the draw function so you can make sure the code is going through the entire execution.

I’ve placed GD.Print()’s strategical around the drawing code to confirm that the _Draw() function is only ever called once, and is definitely not getting stuck in a loop.

My only guess now is that the 2D drawing functions are done by the GPU (using OpenVG?), and the GPU isn’t generating a Bitmap buffer, but actually making those 2D drawing calls every frame?

Who can I ask to confirm this?

-Edit- I had a spare 10min, so have looked at the source code, and it does indeed look like the 2D drawing operations are added to the GPU command queue (in the visual_server), which explains why they are so slow.

Yeah, I only really need this overlay for debugging... so it’s not critical... but if I need to do a custom 2D drawing in future I’ll will see about doing something like this! ??

9 days later

Godot doesn't batch 2D draw calls yet, so polygons and custom drawing functions may be slower than expected. Full batching support may be implemented sometime in the future.

Godot 3.2.2 will feature 2D batching, but for rectangles only (sprites, tiles, fonts). Still, it should give a noticeable performance increase in most projects.

a year later

I'm having a similar problem. Performance hit is considerable. Using version 3.3.2. Here's the setup: - Node2D is parented to Viewport. - Viewport is used in a viewport texture on the main scene. - I have a _draw() function in Node2D that draws several thousand rectangles using draw_rect()

I'd like to call _draw() in Node2D, and consequently update the texture, when refresh is needed. But is seems my only options are to draw every frame or only once. Or am I missing something here?

Looks like it doesn't matter if I call Node2D's update() function every frame or only sporadically. The performance hit is as if it's called every frame . Even if _draw() function doesn't get called. This is annoying.

It seems that Viewport calls the shots here. And there are only two options there - update always or update once. Can this be set up so that update happens on demand when I explicitly call it?

5 days later

Note that custom drawing was sped up significantly in Godot 4.0, thanks to Vulkan and general 2D drawing optimizations.

@xyz How often do you need to update the texture? Do you need to update it during gameplay (i.e. is stutter when updating a problem)?

@Calinou said: @xyz How often do you need to update the texture? Do you need to update it during gameplay (i.e. is stutter when updating a problem)?

I need to update it during gameplay but not necessarily every frame. If I understood the viewport update options correctly, it's not possible to trigger its update from a script on demand. So it boils down to updating it every frame. I could live with stutter caused by a sporadic update. But redrawing it every frame results in unacceptably low fps.

Do you perhaps know how/when the custom draw calls are executed under the hood in 4.0 and how it relates to viewport update options?

Having an option to manually trigger viewport redraw would be really useful in general.

Do you perhaps know how/when the custom draw calls are executed under the hood in 4.0 and how it relates to viewport update options?

I haven't worked on that code, so I don't know.

Having an option to manually trigger viewport redraw would be really useful in general.

This was requested in a proposal, but nobody knows how much work needs to be done to implement it. Either way, it wouldn't resolve your particular problem as line drawing is an operation that needs to be redone every frame somehow – unless you capture viewport data and save it to an image that you load in a TextureRect.

I'm not drawing lines here. It's about shaded rects. The problem was initially posted in other thread but I continued here as it already touched the viewport update topic. Anyway I solved the problem by using instanced quads. This is lightning fast and it can be just left alone to update every frame. But it did require extra management because quads do not wrap in viewports while custom drawn rects apparently do. Which was ideal for my needs.