Summary: | Huge brush tip images unnecessarily slow down Krita on every start of the stroke | ||
---|---|---|---|
Product: | [Applications] krita | Reporter: | Tiar <tamtamy.tymona> |
Component: | Brush engines | Assignee: | Dmitry Kazakov <dimula73> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | dimula73, halla |
Priority: | NOR | ||
Version: | git master (please specify the git hash!) | ||
Target Milestone: | --- | ||
Platform: | Mint (Ubuntu based) | ||
OS: | Linux | ||
Latest Commit: | https://invent.kde.org/graphics/krita/commit/323805d23cb950d5f7d6bb67fadf6c4b8e2194b4 | Version Fixed In: | |
Sentry Crash Report: |
Description
Tiar
2021-05-07 13:03:18 UTC
In the beginning of the stroke we do <n-cpu-cores> copies of the brush. I guess KisBrush::clone() does not preserve image pyramid. To allow pyramid preservation we need to implement proper copy-on-write for it with QSharedDataPointer. Weird -- here I get two copies of the image pyramid, but I have an 8 core computer. Sister bug report about patterns: bug 437950. Confirmed by other people, for example here: https://krita-artists.org/t/story-experiment-verdict-after-brush-recreation-in-krita-4-4-3/22797/17 (the thread is a bit fragmented but the outcome was this bug report). Git commit 016cca213259e0be610c3bed2b91337dd2697ab2 by Dmitry Kazakov. Committed on 28/09/2021 at 11:41. Pushed by dkazakov into branch 'master'. Fix too many copies of KisQImagePyramid on every start of the stroke We should generate the pyramid only once, before making <numcpu> clones. Otherwise, it can delay the stroke quite a bit on bigger brushes. M +4 -0 libs/brush/kis_auto_brush.cpp M +2 -1 libs/brush/kis_auto_brush.h M +7 -0 libs/brush/kis_brush.cpp M +8 -0 libs/brush/kis_brush.h M +6 -0 libs/brush/kis_brushes_pipe.h M +5 -0 libs/brush/kis_imagepipe_brush.cpp M +1 -0 libs/brush/kis_imagepipe_brush.h M +2 -0 plugins/paintops/defaultpaintops/brush/kis_brushop.cpp M +10 -3 plugins/paintops/libpaintop/kis_brush_based_paintop.cpp https://invent.kde.org/graphics/krita/commit/016cca213259e0be610c3bed2b91337dd2697ab2 Git commit e7d22031dabb8785f3dbeb37a8c3e14f551db9dc by Dmitry Kazakov. Committed on 29/09/2021 at 10:56. Pushed by dkazakov into branch 'master'. Fix delays on the stroke start when the brush is too big This patch implements two things: 1) Makes sure that KisBrushBasedPaintOpSettings::m_savedBrush is actually passed by into the stroke (with cloning of course). Cloning of brushes is cheap due to lazy copying mechanism of QImage. 2) Implements a special manager class (KisPresetShadowUpdater) that regenerates brush'es heavy data structures (such as brush outline and image pyramid) in background (with a 1500 ms delay after the brush change). It means that the brush on the server will always store the correct data cached. When the user starts the stroke, this data is just cloned and passed to the stroke without extra recalculation (which may take up to 1000 ms for heavy brush tips). ** POSSIBLE REGRESSIONS ** 1) It may happen that the brush outline will be outdated after some of the brush settings are changed. 2) It may happen that the changes in the brush settings will not be visible in the actual stroke right aftert that. I haven't seen these regressions in real life, but, theoretically, they can happen. M +0 -1 libs/brush/CMakeLists.txt D +0 -50 libs/brush/KisSharedQImagePyramid.cpp D +0 -49 libs/brush/KisSharedQImagePyramid.h M +14 -3 libs/brush/kis_auto_brush.cpp M +3 -0 libs/brush/kis_auto_brush.h M +53 -36 libs/brush/kis_brush.cpp M +8 -5 libs/brush/kis_brush.h M +1 -1 libs/brush/kis_gbr_brush.cpp M +29 -2 libs/brush/kis_imagepipe_brush.cpp M +4 -1 libs/brush/kis_imagepipe_brush.h M +1 -1 libs/brush/kis_text_brush.cpp M +4 -3 libs/brush/tests/kis_gbr_brush_test.cpp M +1 -1 libs/brush/tests/kis_imagepipe_brush_test.cpp A +85 -0 libs/global/KisLazySharedCacheStorage.h [License: GPL(v2.0+)] M +12 -1 libs/image/brushengine/kis_paintop_preset.cpp M +17 -2 libs/image/brushengine/kis_paintop_preset.h M +10 -0 libs/image/brushengine/kis_paintop_settings.cpp M +5 -0 libs/image/brushengine/kis_paintop_settings.h M +1 -0 libs/ui/CMakeLists.txt A +121 -0 libs/ui/KisPresetShadowUpdater.cpp [License: GPL(v2.0+)] A +32 -0 libs/ui/KisPresetShadowUpdater.h [License: GPL(v2.0+)] M +6 -1 libs/ui/kis_canvas_resource_provider.cpp M +2 -0 libs/ui/kis_canvas_resource_provider.h M +22 -2 plugins/paintops/libpaintop/kis_brush_based_paintop_settings.cpp M +3 -0 plugins/paintops/libpaintop/kis_brush_based_paintop_settings.h https://invent.kde.org/graphics/krita/commit/e7d22031dabb8785f3dbeb37a8c3e14f551db9dc Okay, the brush is still valid when you create a masking brush with 3000px cache. This brush doesn't seem to be cached anywhere and constructing it in the beginnin g of the stroke is expensive :( Git commit a094d19e7147db6204ea54eef4467c1592c3fb55 by Dmitry Kazakov. Committed on 30/09/2021 at 11:12. Pushed by dkazakov into branch 'master'. Implement a cache for masked brushes by KisPresetShadowUpdater Masked brushes are initialized in two steps: 1) KisPresetShadowUpdater calls KisPaintOpPreset::coldInitInForeground() to create the cache of the masking preset in the GUI thread (to be able to fetch resources needed by the masking preset) 2) KisPresetShadowUpdater calls KisPaintOpPreset::coldInitInBackground() to regenerate caches of the masking preset, like outline and pyramid. M +44 -7 libs/image/brushengine/kis_paintop_preset.cpp M +6 -0 libs/image/brushengine/kis_paintop_preset.h M +12 -8 libs/ui/KisPresetShadowUpdater.cpp https://invent.kde.org/graphics/krita/commit/a094d19e7147db6204ea54eef4467c1592c3fb55 Git commit 6839165795970fa27afa77001b015cdd3fd4a43a by Dmitry Kazakov. Committed on 30/09/2021 at 12:17. Pushed by dkazakov into branch 'krita/5.0'. Fix too many copies of KisQImagePyramid on every start of the stroke We should generate the pyramid only once, before making <numcpu> clones. Otherwise, it can delay the stroke quite a bit on bigger brushes. M +4 -0 libs/brush/kis_auto_brush.cpp M +2 -1 libs/brush/kis_auto_brush.h M +7 -0 libs/brush/kis_brush.cpp M +8 -0 libs/brush/kis_brush.h M +6 -0 libs/brush/kis_brushes_pipe.h M +5 -0 libs/brush/kis_imagepipe_brush.cpp M +1 -0 libs/brush/kis_imagepipe_brush.h M +2 -0 plugins/paintops/defaultpaintops/brush/kis_brushop.cpp M +10 -3 plugins/paintops/libpaintop/kis_brush_based_paintop.cpp https://invent.kde.org/graphics/krita/commit/6839165795970fa27afa77001b015cdd3fd4a43a Git commit ab3365ff76bdd5dfbc9e83e22b108531ae0041c2 by Dmitry Kazakov. Committed on 30/09/2021 at 12:17. Pushed by dkazakov into branch 'krita/5.0'. Fix delays on the stroke start when the brush is too big This patch implements two things: 1) Makes sure that KisBrushBasedPaintOpSettings::m_savedBrush is actually passed by into the stroke (with cloning of course). Cloning of brushes is cheap due to lazy copying mechanism of QImage. 2) Implements a special manager class (KisPresetShadowUpdater) that regenerates brush'es heavy data structures (such as brush outline and image pyramid) in background (with a 1500 ms delay after the brush change). It means that the brush on the server will always store the correct data cached. When the user starts the stroke, this data is just cloned and passed to the stroke without extra recalculation (which may take up to 1000 ms for heavy brush tips). ** POSSIBLE REGRESSIONS ** 1) It may happen that the brush outline will be outdated after some of the brush settings are changed. 2) It may happen that the changes in the brush settings will not be visible in the actual stroke right aftert that. I haven't seen these regressions in real life, but, theoretically, they can happen. M +0 -1 libs/brush/CMakeLists.txt D +0 -50 libs/brush/KisSharedQImagePyramid.cpp D +0 -49 libs/brush/KisSharedQImagePyramid.h M +14 -3 libs/brush/kis_auto_brush.cpp M +3 -0 libs/brush/kis_auto_brush.h M +53 -36 libs/brush/kis_brush.cpp M +8 -5 libs/brush/kis_brush.h M +1 -1 libs/brush/kis_gbr_brush.cpp M +29 -2 libs/brush/kis_imagepipe_brush.cpp M +4 -1 libs/brush/kis_imagepipe_brush.h M +1 -1 libs/brush/kis_text_brush.cpp M +4 -3 libs/brush/tests/kis_gbr_brush_test.cpp M +1 -1 libs/brush/tests/kis_imagepipe_brush_test.cpp A +85 -0 libs/global/KisLazySharedCacheStorage.h [License: GPL(v2.0+)] M +12 -1 libs/image/brushengine/kis_paintop_preset.cpp M +17 -2 libs/image/brushengine/kis_paintop_preset.h M +10 -0 libs/image/brushengine/kis_paintop_settings.cpp M +5 -0 libs/image/brushengine/kis_paintop_settings.h M +1 -0 libs/ui/CMakeLists.txt A +121 -0 libs/ui/KisPresetShadowUpdater.cpp [License: GPL(v2.0+)] A +32 -0 libs/ui/KisPresetShadowUpdater.h [License: GPL(v2.0+)] M +6 -1 libs/ui/kis_canvas_resource_provider.cpp M +2 -0 libs/ui/kis_canvas_resource_provider.h M +22 -2 plugins/paintops/libpaintop/kis_brush_based_paintop_settings.cpp M +3 -0 plugins/paintops/libpaintop/kis_brush_based_paintop_settings.h https://invent.kde.org/graphics/krita/commit/ab3365ff76bdd5dfbc9e83e22b108531ae0041c2 Git commit 323805d23cb950d5f7d6bb67fadf6c4b8e2194b4 by Dmitry Kazakov. Committed on 30/09/2021 at 12:17. Pushed by dkazakov into branch 'krita/5.0'. Implement a cache for masked brushes by KisPresetShadowUpdater Masked brushes are initialized in two steps: 1) KisPresetShadowUpdater calls KisPaintOpPreset::coldInitInForeground() to create the cache of the masking preset in the GUI thread (to be able to fetch resources needed by the masking preset) 2) KisPresetShadowUpdater calls KisPaintOpPreset::coldInitInBackground() to regenerate caches of the masking preset, like outline and pyramid. M +44 -7 libs/image/brushengine/kis_paintop_preset.cpp M +6 -0 libs/image/brushengine/kis_paintop_preset.h M +12 -8 libs/ui/KisPresetShadowUpdater.cpp https://invent.kde.org/graphics/krita/commit/323805d23cb950d5f7d6bb67fadf6c4b8e2194b4 |