visgl / deck.gl

WebGL2 powered visualization framework
https://deck.gl
MIT License
12.26k stars 2.08k forks source link

Wobbling when zooming in Chrome #988

Closed ilyabo closed 6 years ago

ilyabo commented 7 years ago

I experience a strange wobbling behaviour in Chrome when zooming:

oct-06-2017 11-25-26

My setup:

MacOS 10.11.6
Chrome  61.0.3163.100
NVIDIA GeForce GT 750M
deck.gl 4.1.3
luma.gl 4.0.4
react-map-gl 3.0.4
mapbox-gl 0.38.0

I can reproduce the problem when using just one GeoJsonLayer but also with some custom layers.

It doesn't seem to be related to fp64, because it doesn't depend on the zoom level.

Same problem could be reproduced on two other Macbooks with Intel on-board graphic cards.

The problem can be seen on both my Macbook Pro retina screen as well as on an external monitor, but is significantly more pronounced on the retina display.

I have Chrome Canary on the same machine where the problem cannot be reproduced. So chances are it's a Chrome rendering bug.

I accidentally found a workaround. Adding this 2D canvas overlay beside <DeckGL> magically solves the problem:

class AntiWobbleLayer extends PureComponent {

  componentDidMount() {
    this._redraw()
  }

  componentDidUpdate() {
    this._redraw()
  }

  _redraw() {
    const canvas = this.refs.overlay
    const ctx: CanvasRenderingContext2D = canvas.getContext('2d')
    ctx.clearRect(0, 0, this.props.width, this.props.height)
  }

  render() {
    return (
      <canvas
        ref="overlay"
        width={this.props.width}
        height={this.props.height}
        style={{
          width: `${this.props.width}px`,
          height: `${this.props.height}px`,
          position: 'absolute',
          pointerEvents: 'none',
          left: 0,
          top: 0,
        }}
      />
    )
  }
}

If I comment the line with ctx.clearRect() above, the problem is back.

ibgreen commented 7 years ago

@ilyabo Thanks for the detailed report, it is very helpful. We started seeing other rendering issues (e.g. flickering graphics and background maps) as soon as Chrome 61 autoupdates started, so it may indeed be a browser issue. I guess you could test on Firefox and Safari as well to collect further evidence.

Especially given your fix, it looks like a graphics synchronization issue, as if chrome had changed their graphics stack and changed ordering of operations. Especially as your clear call changes the order and restores synchronization.

Since mapbox and deck.gl draw in different canvases/different WebGL contexts, it is a good questions if there are guarantees that the browser must update them in sync. Worst case, Chrome has changed behavior but is still spec compliant.

In any case, perhaps we can build in something like you anti-wobble layer into the DeckGL component.

@shaojingli @Apercu @georgios-uber

ilyabo commented 7 years ago

I remember seeing the issue in Safari once, but I couldn't reproduce it now. Didn't see it in Firefox.

Note that AntiWobbleLayer is pure, hence clearRect is only called once, and that's enough to fix the problem.

jfsiii commented 7 years ago

Pinging @samccone to see if he has any insights. Sam, I recall seeing something about Chrome <canvas> changes when you were working with Shirley Wu on the regressions in her large <canvas>. Does this seem related to the internal changes made? Should we file a crbug?

samccone commented 7 years ago

Happy to take a look, could someone stand up a demo for me somewhere where this is reproducible?

Thanks!

jfsiii commented 7 years ago

@samccone it might be a different issue, but I'd also appreciate it if you took a look at https://github.com/uber/deck.gl/issues/1067 as well. There are standalone demos.

ilyabo commented 7 years ago

Found one easy way to reproduce (at least on my Mac). Just add opacity to DeckGL: image

Works with the deck.gl example layers, e.g. GeoJsonLayer and Scatterplot: wobble-deck gl

Note, that opacity is not the only way. I think I could see it after setting mixBlendMode also. And in my app it can be reproduced with neither of those.

1chandu commented 7 years ago

Thanks @ilyabo , I can also reproduce this with any layer using layer-browser example by setting style={{opacity: 0.5}}, @ibgreen fp64 prop has no affect on this.

1chandu commented 7 years ago

Tested on Safari and Firefox, no issue there, so this is specific to Chrome.

georgios-uber commented 7 years ago

@1chandu This is specific to Chrome 61. It is fixed on Chrome 62 and did not happen before 61.

yocontra commented 7 years ago

@georgios-uber I'm still seeing this on Chrome 62 on an Nvidia GPU w/ High Sierra btw, so not fixed on their end yet.

jianhuang01 commented 6 years ago

Tested with Chrome64, can't reproduce it.