pencil icon indicating copy to clipboard operation
pencil copied to clipboard

Canvas performance roadmap

Open MrStevns opened this issue 1 year ago • 2 comments

I'll use this issue for keeping tab on my ongoing work in improving painting performance.

The list of changes I have on my roadmap:

  • [x] #1761 Only update the dirty portion of the canvas First step to improve the painting performance on the canvas would be to introduce a blitter and only update what's dirty. The PaintEvent already has this, we just need to use it.

  • [x] #1776 Introduce a tile buffer for stroke painting rather than using mBufferImg which relies on allocating a new image when the bounds needs to be updated. By introducing a tiled surface, we can draw and update only what's a dirty within for example a 64x64 tile. This would be used for when drawing on the canvas only, as it's still faster to draw a single pixmap for playing and as a cache.

  • [x] #1789 Optimize performance of the camera painter by blitting only what's changed rather than redrawing everything

  • [ ] Optimize performance for playback by only blitting the bounds of the image. Optimize painting for only updating the specified region under playback, right now we always assume the view has been changed and therefore updates everything. This can have major impact on performance on a larger working area, because it needs to update the size of the window, even though only a third of the window could be dirty.

  • [ ] Move onion skin painting out of the preLayerPixmap cache. Currently the onion skinning is drawn on the PreLayerPixmap in the CanvasPainter, which means that it's being cleared too often. The onion skin only exists on the current layer right now, so we could move it to a separate pixmap, that is only cleared when modifying the current frame.

  • [ ] Align the transformation setup between Bitmap and Vector. Right now our vector strokes are drawn in local coordinates, where our bitmap strokes are mapped to the canvas transform. This causes us to have to switch between the matrixes in the painter. This change will require some work in all the tools and then adjusting the logic in the canvas painter. I don't expect this change to have impact on performance but it should make our lives easier when working on new tools as well as fixing bugs. It's frustrating right not knowing when it's relevant to use and it results in bugs...

Note to self: The reason for the transformation misalignment is that the vector strokes can be remapped correctly when applying the stroke, where as the bitmap stroke has to be mapped to the correct coordinate system in order to place it correctly on the canvas. It's likely that we won't be able to align because of that.

MrStevns avatar Apr 23 '23 11:04 MrStevns

Hey @MrStevns thanks for this fabulous roadmap! This is what I have been thinking for years but still not able to finish.

Just a little reminder, please ensure that you run the profiler after you make changes. When working on performance things, programmers sometimes make assumptions about the bottleneck by just looking at code, but it may not have a significant impact on performance.

For the stroke painting mBufferImg issue, I was thinking to make a buffer image which the size is slightly bigger than the current viewable area of the canvas, to avoid the frequent image copy and allocations.

Anyway, I look forward to your improvements!

chchwy avatar Apr 24 '23 04:04 chchwy

Just a little reminder, please ensure that you run the profiler after you make changes. When working on performance things, programmers sometimes make assumptions about the bottleneck by just looking at code, but it may not have a significant impact on performance.

So far i've been using the time profiler in Instruments for Mac OS, for discovering and verifying my changes, so that should be covered 😄 For more precise profiling it could make sense to gather some data using hayai (that was also used for the bucket tool performance PR). To avoid having these regressions, we could even include some tests in the project that compares previous and current results, so we are made aware of when we make changes that have major impact on performance.

For the stroke painting mBufferImg issue, I was thinking to make a buffer image which the size is slightly bigger than the current viewable area of the canvas, to avoid the frequent image copy and allocations.

I too considered making that change but having worked with a tiled surface via the mypaint branch i've been experimenting with, I think there are more possibilities going that way. This will also benefit our rasterized vector strokes. I already have a branch with it working and the results are promising, but it could still make sense to compare that against having a big BitmapImage which is pre-allocated.

MrStevns avatar Apr 24 '23 05:04 MrStevns