Page MenuHome

Paint: Stroke step queue
Needs ReviewPublic

Authored by Pablo Dobarro (pablodp606) on Wed, Sep 4, 5:34 PM.
Tags
None
Subscribers
None
Tokens
"Love" token, awarded by johnsyed."Love" token, awarded by franMarz."Burninate" token, awarded by craig_jones."Like" token, awarded by Zino."Like" token, awarded by amonpaike."Like" token, awarded by billreynish.

Details

Summary

This patch adds a queue that stores brush step samples to process them at a constant rate. This avoids sending too many updates to the paint modes locking the brush preview and the UI during a stroke and affecting performance.
I disabled some stroke methods for using the step queue. They work fine, but I'm not sure if that is the best UX.
Before:

After:

Diff Detail

Repository
rB Blender
Branch
paint-step-queue (branched from master)
Build Status
Buildable 4770
Build 4770: arc lint + arc unit

Event Timeline

The risk with this change is that if redrawing / updating is slow and painting a single step is relatively fast, then completing the stroke can become quite slow.

For example if you quickly draw a long stroke with small brush radius, on a high res image or high poly mesh.

I think that could be mitigated by something like this:

  • max_time = max(STROKE_UPDATE_DELTA, redraw_time * factor)
  • redraw_time estimated as time elapsed since the last paint_step_sample_update
  • factor equals 1 or something not too far from it
Pablo Dobarro (pablodp606) updated this revision to Diff 17835.
  • Add STROKE_TIME_SCALE_FACTOR

@Brecht Van Lommel (brecht) I'm not sure if I implement your proposal correctly but I don't notice much difference changing the time factor
I think that even if this patch makes paint modes a bit slower, most people are going to prefer this behavior over blocking the cursor and UI just to gain a few milliseconds when a stroke is lagging. We can always add it as an option for the paint modes as it can easily be disabled.

I don't think it needs to be an option, with an automatic solution it should be fine.

The case I'm thinking of is not for a few milliseconds. For example:

  • paint_step_sample_update() takes 1/60s
  • redrawing, depsgraph update, ... takes 1/6s
  • draw stroke with 100 steps

Previously it would do about 5 redraws and complete that stroke in about 5/6 + 100/60 = 2.5s. Without the mitigation, the new code would do 100 redraws and take about 100/6 + 100/60 = 18.3s.

@Brecht Van Lommel (brecht) So you think we need something more than controlling the maximum time using the time from the last update iteration? Maybe we should ensure a fixed minimum amount of updates per redraw?