Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return early from draw calls on layers with constant opacity=0 #5429

Merged
merged 8 commits into from
Oct 11, 2017

Conversation

lbud
Copy link
Contributor

@lbud lbud commented Oct 9, 2017

We're completing full draw calls for layers even when their opacity is set to zero. This cuts back on render passes by bailing early from draw functions if a layer's opacity is constant at 0. One common use case for this is switching very quickly between several visualization layers without having to reparse buckets/re-download tiles.

Locally I replaced the Streets style in the Paint benchmark with a version where half of the layers are set to opacity=0 — obviously this example is extremely contrived, but
image

Copy link
Contributor

@anandthakker anandthakker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

This made me wonder how we handle visibility: none, and it looks like that's done via the StyleLayer#isHidden() method. I wonder if it makes sense to fold these checks into isHidden() for each layer type?

@@ -12,6 +12,7 @@ module.exports = drawCircles;

function drawCircles(painter: Painter, sourceCache: SourceCache, layer: CircleStyleLayer, coords: Array<TileCoord>) {
if (painter.renderPass !== 'translucent') return;
if (layer.paint['circle-opacity'] === 0 && layer.paint['circle-stroke-opacity'] === 0) return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With an eye towards #3044, we should use layer.isPaintValueFeatureConstant() and layer.getPaintValue() instead of directly accessing layer.paint

@lbud lbud force-pushed the bail-zero-opacity branch from 9856917 to 09ed3de Compare October 9, 2017 14:36
@lbud
Copy link
Contributor Author

lbud commented Oct 9, 2017

Good idea @anandthakker — moved these in 09ed3de.

Lauren Budorick added 2 commits October 9, 2017 16:42
@jfirebaugh
Copy link
Contributor

I wonder if it makes sense to fold these checks into isHidden() for each layer type?

I seem to recall that's what we used to do, but we had reason to stop. Can you please review the history and see why?

@lbud
Copy link
Contributor Author

lbud commented Oct 9, 2017

Good call @jfirebaugh — looks like this was removed in #3120. It seems like the cause of that underlying bug was that we were also trying to be smart about the alpha channel in the color, which I think isn't necessary here — users trying to show/hide layers with opacity would do so with explicit -opacity properties. From that PR:

The latest commit removes all opacity tests from the StyleLayer#isHidden method. This is unlikely to cause performance regressions in core styles because we don't often have 0 opacity layers in core styles. It's possible a 3rd party style may see a perf regression due to this change.

¯_(ツ)_/¯

@jfirebaugh
Copy link
Contributor

Yeah, that's the one I was thinking of. In addition to that, we also tell people to use opacity 0 if they don't want the layer to be visible, but do want it to be queryable with queryRenderedFeatures. I believe including an opacity check in isHidden would break that, because isHidden affects whether the tiles are loaded. So I think we should short circuit in drawing, but not change isHidden.

…ing for invisible features

* Add query tests for invisible features + render test for visible circle-stroke with zero-opacity circle
@lbud
Copy link
Contributor Author

lbud commented Oct 10, 2017

Okay, this now short-circuits only in draw functions with isOpacityZero methods per StyleLayer subclass. I've also added two query tests for invisible features (one opacity=0 and one visibility=none) and a render test for circles with strokes but zero-opacity fills, since that's a slightly weird edge case here.

@mourner
Copy link
Member

mourner commented Oct 10, 2017

@lbud let's also run the bench for a style with no opacity=0 layers since this may affect performance (many additional getPaintValue calls)

@lbud
Copy link
Contributor Author

lbud commented Oct 10, 2017

@mourner with the regular Streets style there's no statistically significant change. Here are bench results from #Paint — ran it several times, always ± just a bit in either direction:

image

Full bench run:
image

@anandthakker and I discussed this yesterday as well — we could theoretically just use computed layer.paint[<type>-opacity], but as he noted in #5429 (comment) we'd like to get away from doing that.

@@ -9,6 +9,8 @@ import type StyleLayer from '../style/style_layer';
module.exports = drawBackground;

function drawBackground(painter: Painter, sourceCache: SourceCache, layer: StyleLayer) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change layer: StyleLayer to layer: BackgroundStyleLayer...

@@ -12,6 +12,7 @@ module.exports = drawRaster;

function drawRaster(painter: Painter, sourceCache: SourceCache, layer: StyleLayer, coords: Array<TileCoord>) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...layer: RasterStyleLayer...

@@ -41,6 +41,7 @@ class StyleLayer extends Evented {
_layoutFunctions: {[string]: boolean};

+createBucket: (parameters: BucketParameters) => Bucket;
+isOpacityZero: (zoom: number, property?: string) => boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...then you can remove this...

@@ -48,6 +48,13 @@ class SymbolStyleLayer extends StyleLayer {
return (new SymbolBucket((parameters: any)): any);
}

isOpacityZero(zoom: number, property?: string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and make property non-optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 thanks @jfirebaugh!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants