From 43708d905794215355e6226c361e87f2d0621bb3 Mon Sep 17 00:00:00 2001 From: Karim Naaji Date: Thu, 5 Mar 2020 09:05:17 -0800 Subject: [PATCH] Prevent creation of unused depth renderbuffer attachments (#9377) * Remove unused depth renderbuffer Should save width * height * 2 bytes of uncompressed buffer memory * Prevent creation of unused depth renderbuffers Add option to allow not creating extra renderbuffers Refer https://www.khronos.org/registry/webgl/specs/latest/1.0/\#6.8 for supported attachment variants Should save the hillshade offscreen buffer width * height * 2 bytes of uncompressed gpu memory * Fix lint * Update src/gl/framebuffer.js Co-Authored-By: Vladimir Agafonkin Co-authored-by: Vladimir Agafonkin --- src/gl/context.js | 4 ++-- src/gl/framebuffer.js | 14 ++++++++++---- src/render/draw_heatmap.js | 2 +- src/render/draw_hillshade.js | 2 +- src/render/painter.js | 20 -------------------- 5 files changed, 14 insertions(+), 28 deletions(-) diff --git a/src/gl/context.js b/src/gl/context.js index 8290730025b..550f97ba4ab 100644 --- a/src/gl/context.js +++ b/src/gl/context.js @@ -203,8 +203,8 @@ class Context { return rbo; } - createFramebuffer(width: number, height: number) { - return new Framebuffer(this, width, height); + createFramebuffer(width: number, height: number, hasDepth: boolean) { + return new Framebuffer(this, width, height, hasDepth); } clear({color, depth}: ClearArgs) { diff --git a/src/gl/framebuffer.js b/src/gl/framebuffer.js index 7353efec8b8..11cac48f756 100644 --- a/src/gl/framebuffer.js +++ b/src/gl/framebuffer.js @@ -1,5 +1,6 @@ // @flow import {ColorAttachment, DepthAttachment} from './value'; +import assert from 'assert'; import type Context from './context'; @@ -11,7 +12,7 @@ class Framebuffer { colorAttachment: ColorAttachment; depthAttachment: DepthAttachment; - constructor(context: Context, width: number, height: number) { + constructor(context: Context, width: number, height: number, hasDepth: boolean) { this.context = context; this.width = width; this.height = height; @@ -19,7 +20,10 @@ class Framebuffer { const fbo = this.framebuffer = gl.createFramebuffer(); this.colorAttachment = new ColorAttachment(context, fbo); - this.depthAttachment = new DepthAttachment(context, fbo); + if (hasDepth) { + this.depthAttachment = new DepthAttachment(context, fbo); + } + assert(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE); } destroy() { @@ -28,8 +32,10 @@ class Framebuffer { const texture = this.colorAttachment.get(); if (texture) gl.deleteTexture(texture); - const renderbuffer = this.depthAttachment.get(); - if (renderbuffer) gl.deleteRenderbuffer(renderbuffer); + if (this.depthAttachment) { + const renderbuffer = this.depthAttachment.get(); + if (renderbuffer) gl.deleteRenderbuffer(renderbuffer); + } gl.deleteFramebuffer(this.framebuffer); } diff --git a/src/render/draw_heatmap.js b/src/render/draw_heatmap.js index ed2ff6c056a..4cee1dc4862 100644 --- a/src/render/draw_heatmap.js +++ b/src/render/draw_heatmap.js @@ -87,7 +87,7 @@ function bindFramebuffer(context, painter, layer) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - fbo = layer.heatmapFbo = context.createFramebuffer(painter.width / 4, painter.height / 4); + fbo = layer.heatmapFbo = context.createFramebuffer(painter.width / 4, painter.height / 4, false); bindTextureToFramebuffer(context, painter, texture, fbo); diff --git a/src/render/draw_hillshade.js b/src/render/draw_hillshade.js index c72c3912106..2e342486897 100644 --- a/src/render/draw_hillshade.js +++ b/src/render/draw_hillshade.js @@ -90,7 +90,7 @@ function prepareHillshade(painter, tile, layer, sourceMaxZoom, depthMode, stenci const renderTexture = new Texture(context, {width: tileSize, height: tileSize, data: null}, gl.RGBA); renderTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE); - fbo = tile.fbo = context.createFramebuffer(tileSize, tileSize); + fbo = tile.fbo = context.createFramebuffer(tileSize, tileSize, true); fbo.colorAttachment.set(renderTexture.texture); } diff --git a/src/render/painter.js b/src/render/painter.js index 9df7d66fa86..7c9338c2cc1 100644 --- a/src/render/painter.js +++ b/src/render/painter.js @@ -92,8 +92,6 @@ class Painter { emptyProgramConfiguration: ProgramConfiguration; width: number; height: number; - depthRbo: WebGLRenderbuffer; - depthRboNeedsClear: boolean; tileExtentBuffer: VertexBuffer; tileExtentSegments: SegmentVector; debugBuffer: VertexBuffer; @@ -136,8 +134,6 @@ class Painter { this.numSublayers = SourceCache.maxUnderzooming + SourceCache.maxOverzooming + 1; this.depthEpsilon = 1 / Math.pow(2, 16); - this.depthRboNeedsClear = true; - this.crossTileSymbolIndex = new CrossTileSymbolIndex(); this.gpuTimers = {}; @@ -148,8 +144,6 @@ class Painter { * for a new width and height value. */ resize(width: number, height: number) { - const gl = this.context.gl; - this.width = width * browser.devicePixelRatio; this.height = height * browser.devicePixelRatio; this.context.viewport.set([0, 0, this.width, this.height]); @@ -159,11 +153,6 @@ class Painter { this.style._layers[layerId].resize(); } } - - if (this.depthRbo) { - gl.deleteRenderbuffer(this.depthRbo); - this.depthRbo = null; - } } setup() { @@ -402,7 +391,6 @@ class Painter { // framebuffer, and then save those for rendering back to the map // later: in doing this we avoid doing expensive framebuffer restores. this.renderPass = 'offscreen'; - this.depthRboNeedsClear = true; for (const layerId of layerIds) { const layer = this.style._layers[layerId]; @@ -483,14 +471,6 @@ class Painter { this.context.setDefault(); } - setupOffscreenDepthRenderbuffer(): void { - const context = this.context; - // All of the 3D textures will use the same depth renderbuffer. - if (!this.depthRbo) { - this.depthRbo = context.createRenderbuffer(context.gl.DEPTH_COMPONENT16, this.width, this.height); - } - } - renderLayer(painter: Painter, sourceCache: SourceCache, layer: StyleLayer, coords: Array) { if (layer.isHidden(this.transform.zoom)) return; if (layer.type !== 'background' && layer.type !== 'custom' && !coords.length) return;