mirror of
https://github.com/status-im/whispervis.git
synced 2025-02-08 11:23:53 +00:00
Add render throttling to decrease CPU/GPU usage while screen is idle
This commit is contained in:
parent
19ed6ded1e
commit
b50c31811d
31
animate.go
31
animate.go
@ -5,11 +5,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gopherjs/gopherjs/js"
|
||||
"github.com/gopherjs/vecty"
|
||||
"github.com/status-im/simulation/propagation"
|
||||
)
|
||||
|
||||
// TODO(divan): move this as variables to the frontend
|
||||
const (
|
||||
// TODO(divan): move this as variables to the frontend
|
||||
BlinkDecay = 100 * time.Millisecond // time for highlighted node/link to be active
|
||||
AnimationSlowdown = 1 // slowdown factor for propagation animation
|
||||
FPS = 30 // default FPS
|
||||
@ -42,7 +43,18 @@ func (w *WebGLScene) animate() {
|
||||
w.updatePositions()
|
||||
}
|
||||
|
||||
w.renderer.Render(w.scene, w.camera)
|
||||
// some render throttling magic to prevent wasting CPU/GPU while idle
|
||||
// if auto rotation or other effects are active, render always
|
||||
var needRendering bool = w.wobble || w.autoRotate
|
||||
if !needRendering {
|
||||
// else, consult render throttler
|
||||
needRendering = w.rt.NeedRendering()
|
||||
}
|
||||
|
||||
if needRendering {
|
||||
w.renderer.Render(w.scene, w.camera)
|
||||
w.rt.ReenableIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
// ToggleAutoRotation switches auto rotation option.
|
||||
@ -75,6 +87,7 @@ func (w *WebGLScene) BlinkEdge(id int) {
|
||||
// AnimatePropagation visualizes propagation of message based on plog.
|
||||
func (w *WebGLScene) AnimatePropagation(plog *propagation.Log) {
|
||||
fmt.Println("Animating plog")
|
||||
w.rt.Disable()
|
||||
for i, ts := range plog.Timestamps {
|
||||
duration := time.Duration(time.Duration(ts) * time.Millisecond)
|
||||
duration = duration * AnimationSlowdown
|
||||
@ -94,3 +107,17 @@ func (w *WebGLScene) AnimatePropagation(plog *propagation.Log) {
|
||||
time.AfterFunc(duration, fn)
|
||||
}
|
||||
}
|
||||
|
||||
// MouseMoveListener implements listener for mousemove events.
|
||||
// We use it for disabling render throttling, as mousemove events
|
||||
// correlates with user moving inside of the WebGL canvas. We
|
||||
// may switch to use mousedown or drag events, but let's see how
|
||||
// mousemove works.
|
||||
// This is sort of a hack, as the proper approach would be to get
|
||||
// data from controls code (w.controls.Update), but it's currently
|
||||
// a JS code, so it's easier use this hack.
|
||||
func (p *Page) MouseMoveListener(e *vecty.Event) {
|
||||
if !p.webgl.rt.NeedRendering() {
|
||||
p.webgl.rt.Disable()
|
||||
}
|
||||
}
|
||||
|
1
page.go
1
page.go
@ -105,6 +105,7 @@ func (p *Page) Render() vecty.ComponentOrHTML {
|
||||
),
|
||||
vecty.Markup(
|
||||
event.KeyDown(p.KeyListener),
|
||||
event.MouseMove(p.MouseMoveListener),
|
||||
event.VisibilityChange(p.VisibilityListener),
|
||||
),
|
||||
)
|
||||
|
58
render_throttler.go
Normal file
58
render_throttler.go
Normal file
@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DefaultRenderThrottleDecay defines a decay period after which throttling should reenabled.
|
||||
const DefaultRenderThrottleDecay = 5 // sec
|
||||
|
||||
// RenderThrottler is a helper to enable rendering only when it's really need to.
|
||||
// Rendering can be enabled/requested externally, but will be turned off/slowed down
|
||||
// after some period of time.
|
||||
// TODO(divan): disable/enable throttling is inverse of enable/disable rendering, and may be confusing. Rename maybe?
|
||||
// TODO(divan): also, instead of disabling, might be a good idea to just decrease FPS. Explore this.
|
||||
type RenderThrottler struct {
|
||||
needRendering bool
|
||||
lastUpdate int64
|
||||
decay int64
|
||||
}
|
||||
|
||||
// NewRenderThrottler returns a new render throttler.
|
||||
func NewRenderThrottler() *RenderThrottler {
|
||||
r := &RenderThrottler{
|
||||
needRendering: true,
|
||||
lastUpdate: time.Now().Unix(),
|
||||
decay: DefaultRenderThrottleDecay,
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// Disable disables render throttling.
|
||||
func (r *RenderThrottler) Disable() {
|
||||
fmt.Printf("Switching ON rendering")
|
||||
r.needRendering = true
|
||||
r.lastUpdate = time.Now().Unix()
|
||||
}
|
||||
|
||||
// Enable enables render throttling.
|
||||
func (r *RenderThrottler) Enable() {
|
||||
fmt.Printf("Switching off rendering")
|
||||
r.needRendering = false
|
||||
}
|
||||
|
||||
// ReenableIfNeeded checks if sufficient time has passed since throttling has been
|
||||
// disabled, and enables throttling back if so.
|
||||
func (r *RenderThrottler) ReenableIfNeeded() {
|
||||
now := time.Now().Unix()
|
||||
if r.lastUpdate+r.decay < now {
|
||||
r.Enable()
|
||||
}
|
||||
}
|
||||
|
||||
// NeedRendering returns true if next frame should be rendered.
|
||||
func (r *RenderThrottler) NeedRendering() bool {
|
||||
return r.needRendering
|
||||
}
|
6
scene.go
6
scene.go
@ -31,11 +31,15 @@ type WebGLScene struct {
|
||||
// TODO(divan): as soon as three.js wrappers allow us to access children, get rid of it here
|
||||
nodes []*Mesh
|
||||
lines []*Line
|
||||
|
||||
rt *RenderThrottler // used as a helper to reduce rendering calls when animation is not needed (experimental)
|
||||
}
|
||||
|
||||
// NewWebGLScene inits and returns new WebGL scene and canvas.
|
||||
func NewWebGLScene() *WebGLScene {
|
||||
w := &WebGLScene{}
|
||||
w := &WebGLScene{
|
||||
rt: NewRenderThrottler(),
|
||||
}
|
||||
w.WebGLRenderer = vthree.NewWebGLRenderer(vthree.WebGLOptions{
|
||||
Init: w.init,
|
||||
Shutdown: w.shutdown,
|
||||
|
Loading…
x
Reference in New Issue
Block a user