Open Bug 1590515 Opened 5 years ago Updated 2 years ago

CanvasRenderingContext2D.drawImage is very slow in three.js demo

Categories

(Core :: Graphics: Canvas2D, defect, P3)

x86_64
macOS
defect

Tracking

()

People

(Reporter: gregtatum, Unassigned)

References

(Regression)

Details

(Keywords: regression)

I just loaded up this demo showing off some shiny new graphics: https://model-viewer-tester.glitch.me/

It is fairly slow in Firefox, but performant in Chrome. Here is a profile:

https://perfht.ml/31EpEhu

The culprit appears to be our implementation of CanvasRenderingContext2D.drawImage.

The three.js render method appears to do all the WebGL stuff, and then blit it out using the 2d canvas method:

    render(t) {
        if (!this.canRender || this.isPresenting) {
            return;
        }
        const delta = t - this.lastTick;
        const dpr = resolveDpr();
        if (dpr !== this.renderer.getPixelRatio()) {
            this.renderer.setPixelRatio(dpr);
        }
        for (let scene of this.scenes) {
            const { element, width, height, context } = scene;
            element[$tick$1](t, delta);
            if (!scene.isVisible || !scene.isDirty || scene.paused) {
                continue;
            }
            const camera = scene.getCamera();
            if (width > this.width || height > this.height) {
                const maxWidth = Math.max(width, this.width);
                const maxHeight = Math.max(height, this.height);
                this.setRendererSize(maxWidth, maxHeight);
            }
            const { exposure } = scene;
            const exposureIsNumber = typeof exposure === 'number' && !self.isNaN(exposure);
            this.renderer.toneMappingExposure = exposureIsNumber ? exposure : 1.0;
            this.renderer.setRenderTarget(null);
            this.renderer.clearDepth();
            this.renderer.setViewport(0, 0, width, height);
            this.renderer.render(scene, camera);
            const widthDPR = width * dpr;
            const heightDPR = height * dpr;
            context.drawImage(this.renderer.domElement, 0, this.canvas.height - heightDPR, widthDPR, heightDPR, 0, 0, widthDPR, heightDPR);
            scene.isDirty = false;
        }
        this.lastTick = t;
    }

The line taking up all the profile time is:

context.drawImage(this.renderer.domElement, 0, this.canvas.height - heightDPR, widthDPR, heightDPR, 0, 0, widthDPR, heightDPR);

I also filed an issue on the source project: https://github.com/GoogleWebComponents/model-viewer/issues/845

However, it seems that if other browsers are fast here, we could be fast too.

Priority: -- → P3
Regressed by: 1468801
Keywords: regression
Has Regression Range: --- → yes
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.