Page MenuHome

Sculpt: Limit viewport redraws to 30fps
Needs ReviewPublic

Authored by Pablo Dobarro (pablodp606) on Jan 19 2020, 12:24 AM.
Tags
None
Tokens
"Love" token, awarded by brilliant_ape."100" token, awarded by shader."Love" token, awarded by tiagoffcruz."Love" token, awarded by Brandon777."Love" token, awarded by Tetone."Love" token, awarded by MetinSeven."Love" token, awarded by andruxa696."Love" token, awarded by RodDavis."Love" token, awarded by xrg."Love" token, awarded by wilBr."Love" token, awarded by Alrob."Like" token, awarded by Frozen_Death_Knight.

Details

Summary

The profiling information in https://developer.blender.org/T72943#848210 shows that viewport redraws take a lot of time between brush samples, making the brush lag in high poly meshes.
By limiting the redraws to 30fps, we are potentially processing more brush samples without getting the threads interrupted by a viewport redraw, increasing performance.
I some test @Ray molenkamp (LazyDodo) did, this patch increases the performance from 40 fps up to 100 fps.

Diff Detail

Repository
rB Blender
Branch
sculpt-limit-redraws (branched from master)
Build Status
Buildable 6323
Build 6323: arc lint + arc unit

Event Timeline

By limiting the redraws to 30fps, we are potentially processing more brush samples without getting the threads interrupted by a viewport redraw, increasing performance.
I some test @Ray molenkamp (LazyDodo) (LazyDodo) did, this patch increases the performance from 40 fps up to 100 fps.

To be clear, when you say 100 fps, do you mean 100 brush samples per second rather than frames per second? Or what are you measuring exactly?

This sort of solves the opposite problem of D5676. Sometimes the brush samples are slower, sometimes the drawing is slower, and they need to be balanced for smooth interaction.

By limiting the redraws to 30fps, we are potentially processing more brush samples without getting the threads interrupted by a viewport redraw, increasing performance.
I some test @Ray molenkamp (LazyDodo) (LazyDodo) did, this patch increases the performance from 40 fps up to 100 fps.

To be clear, when you say 100 fps, do you mean 100 brush samples per second rather than frames per second? Or what are you measuring exactly?

It's a meaningless measurement really, it Just the fps counter using fraps but it's hard to quantify laggyness during sculpting

however due to the changed mesh data not being uploaded every single frame that's being drawn (which was a significant contribution of the main thread stalling) there's more time to actually chew through though the ghost queue of input events and get a less lagggy sculpting response.

That being said, someone should probably verify that when we end a stroke, a redraw is being done to make sure the final mesh data makes it to the gpu.

This sort of solves the opposite problem of D5676. Sometimes the brush samples are slower, sometimes the drawing is slower, and they need to be balanced for smooth interaction.

the drawing is fine, actually with this patch we actually drawing more often, it's the hundreds of vertex buffers that get uploaded in preparation for the redraw it that is killing (some of) the perf here, I'm not overly comfortable with opengl but with cuda i found that there's a fixed startup cost of doing a data transfer, and doing a single large transfer is generally faster than 10 small transfers , perhaps something to try/play with ?

@Ray molenkamp (LazyDodo) All viewports are tagged to redraw at the end of each stroke in sculpt_flush_update_done, so it should be fine

From what I understand, with this patch it will limit both mesh buffer updates and 3D viewport redraws to 30 FPS. It may be that it is redrawing the entire window (with cached framebuffer) at a higher FPS, but that would be a waste since there is nothing to redraw. There's only the brush cursor moving, but it's hidden during the stroke in the demo video.

For smooth interaction, what we want to have as low as possible is the maximum frame time of 3D viewport redraws. The average frame time can be low, but if there are individual frames that much longer than others it will still be laggy. And I can see how this patch would help even out frame times and reduce stalling.

Just the 100 FPS may indicate a slight inefficiency rather than measure the performance improvement.

Allright fps is clearly useless, and "it feels better" is a terrible performance metric but ideally you'd want to measure the latency between receiving the event from the mouse/tablet in ghost and having the change reflected in the mesh data or on screen.

Given we have no performance metrics available for that, i added a timestamp to wm_event_add_ex and printed the total life time in wm_event_free misses out on the ghost bits but it should still give measurable results and if there is an improvement it should show.

after applying an additional filter to only display when we are making a stroke it produced these results

soo... yeah.. that solved nothing, is it better? perhaps?

plotting a histogram helps a little bit

The curve seems to have moved a little to the left

however although i can logically explain why this change should improve things the few performance metrics i was able to gather do not seem to back this up, and i don't think it's a good idea to land this in it's current form.

unrelated the excessive >100 fps redraws were indeed caused by this bit in paint_stroke.c

if (ar && (p->flags & PAINT_SHOW_BRUSH)) {
  WM_paint_cursor_tag_redraw(window, ar);
}

if it take that out, it caps at 28-30 (but it makes very little difference in the graphs above, so i excluded it from testing)

attached is this same patch but with the output of the wm_event lifetime