Page MenuHome

Sculpt Mode Performance
Needs Triage, NormalPublicTO DO

Authored By
Pablo Dobarro (pablodp606)
Sep 25 2020, 8:08 PM
"Love" token, awarded by Rubens91."Love" token, awarded by Schamph."Love" token, awarded by Stig."Love" token, awarded by Branskugel."Love" token, awarded by silex."Heartbreak" token, awarded by Sych."Love" token, awarded by amalbubble."Burninate" token, awarded by cgeugene."Love" token, awarded by TimBrown."Love" token, awarded by Copperplate."Baby Tequila" token, awarded by unwave."Love" token, awarded by MrMargaretScratcher."Love" token, awarded by Shimoon."Burninate" token, awarded by SHEIKH."Love" token, awarded by AngelNavarro."100" token, awarded by thinkinmonkey."Love" token, awarded by ZohaibAli."Love" token, awarded by ZackMercury."Love" token, awarded by Kickflipkid687."Love" token, awarded by kouza."Love" token, awarded by Biaru."100" token, awarded by CAEL."100" token, awarded by g.ndre."Love" token, awarded by gritche."Yellow Medal" token, awarded by franMarz."100" token, awarded by roman13."Burninate" token, awarded by Dir-Surya."Love" token, awarded by vladimirzb."Love" token, awarded by jmztn."Like" token, awarded by IPv6."100" token, awarded by belich."Love" token, awarded by Anubis."Love" token, awarded by ThomasJohann."Love" token, awarded by vr_sebas."Burninate" token, awarded by mindinsomnia."Party Time" token, awarded by n-pigeon."Mountain of Wealth" token, awarded by zeauro."Burninate" token, awarded by dlc17."Burninate" token, awarded by Ravenman13."Love" token, awarded by wo262."Evil Spooky Haunted Tree" token, awarded by lopoIsaac."100" token, awarded by MetinSeven."Love" token, awarded by v01tech."Hungry Hippo" token, awarded by AnityEx."Love" token, awarded by hitrpr."Love" token, awarded by Alrob."Love" token, awarded by chironamo."Mountain of Wealth" token, awarded by ace_dragon."Love" token, awarded by russ1642."Burninate" token, awarded by slowburn."Love" token, awarded by andruxa696."Love" token, awarded by gilberto_rodrigues."Mountain of Wealth" token, awarded by psy-fi."Love" token, awarded by dbystedt."100" token, awarded by Brandon777."Burninate" token, awarded by Zino."100" token, awarded by julperado."100" token, awarded by Frozen_Death_Knight.


Status: Prototype implemented in D8983 with all optimizations included for Meshes, but only for some tools and features. Needs to be split into multiple patches and implement all remaining features.


Commissioner: @Daniel Bystedt (dbystedt)
Project leader: @Pablo Dobarro (pablodp606)
Project members: -


Big picture: Improve the performance of Sculpt Mode brushes and tools.

Use cases:

  • Edit geometry surface detail in high poly meshes without performance issues

Remove all unnecessary calculations and updates from the PBVH when an editing operation is active, making all the Sculpt Mode code work only with the relevant vertices per brush step. The PBVH should only be used to get the affected area by the stroke as fast as possible.

Engineer plan:

  • Get the PBVH code ready to have much smaller leaf node sizes
  • Store draw buffers in intermediate nodes to reduce the size of the leaf nodes of the PBVH.
  • Make proxies, bounding box and normal updates optional per tool and per symmetry options.
  • Do fast bounding box recalculations by updating the bounding boxes when deforming and propagating them from children to parents nodes to the root of the tree.
  • Implement optional fast normal updates (single loop) for brushes that require them.
  • Replace per node undo with a per vertex undo, which will also be used to get the original data during the stroke.
  • Remove BMesh based dyntopo (to be replaced with a better implementation).
  • Remove all loops over nodes from the code that runs when a stroke is active.
  • Configure the optimal settings of the scheduler per tool.
  • Make special tools (Pose, Boundary, Elastic Deform) not use the PBVH for getting the affected area. Cache the affected area of these tools once their data is initialized.
Work plan

Milestone 1 - optional name
Optimize PBVH queries and drawing
Time estimate: 2 - 3 weeks

Milestone 2 - optional name
Rewrite task scheduling and per vertex updates.
Time estimate: 3 - 4 weeks

Relevant links:

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes


That difference is HUGE!

I'm hyped about this, can't wait to see it land in Blender.

@Sergey Sharybin (sergey) @Brecht Van Lommel (brecht) I'm going to start making patches for master to try to get to milestone 1 as soon as possible. These are the most easy to make changes (they don't require refactor of a lot of code) and we can get quite some performance once they are done.
The idea for Milestone 1 is to reduce the size of the leaf nodes as much as possible. In order to do that, we need to solve two problems:

  • Move the batches to the middle of the tree (already done in the prototype)
  • Propagate the update flags (normals, bounding boxes, redraw, proxies...) from the leaf nodes to the root node to have faster partial updates.

We currently have a lot of places were we traverse the entire tree just to get to the leaf nodes and then we loop over the leaf nodes to check if they have a flag enabled (we do this multiple times per stroke step). When reducing the leaf nodes, this issue becomes a huge problem, even with the draw buffers in intermediate nodes as traversing the entire tree just to update the normals of a leaf node with 100 vertices is not great.
The first patches I'm going to make are going to be related to solving this issue. The performance improvement is not going to be noticeable until later (when reducing the size of the leafs), but I think this should be the first step.

For the leaf nodes, how much smaller are we talking about? The dyntopo code had a pretty significant performance degradation from ->leaf_limit being left at 100. Like Pablo said, this is due to traversing the entire tree in order to get anything done (there are other performance degradations tied to multiple per-vertex uses of GHash, but leaf_limit being 100 was pretty significant in itself).

BTW, remember that splitting your memory into small chunks can be death to cache coherency. Here are a few relevant papers I found with a quick Google search:

@Joseph Eagar (joeedh) Hi! That is what I'm working on in this patch.
We still don't know how small we can make the leaf nodes, but in order to do experiments with that (and fix some of the current performance issues), we first need to remove from the code all functions that traverse the entire tree to find a leaf node and do the updates (and there are a lot of those), and be able to store the draw buffers at any level in the tree.

For this project I was only considering meshes and Multires, and I was focusing more on having fast strokes with small radius (see instead of making brushes that displace a big number of vertices faster. I would say that we want leaf nodes to be as small as possible to be able to discard as many vertices and have more localized updates, but we need to find a good balance.