Skip to content

Commit

Permalink
Texture bind and slot caching
Browse files Browse the repository at this point in the history
  • Loading branch information
karimnaaji committed Jul 12, 2022
1 parent d6b5668 commit e09e055
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 16 deletions.
27 changes: 21 additions & 6 deletions src/gl/value.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ export interface Value<T> {
}

class BaseValue<T> implements Value<T> {
context: Context;
gl: WebGLRenderingContext;
current: T;
default: T;
dirty: boolean;

constructor(context: Context) {
this.context = context;
this.gl = context.gl;
this.default = this.getDefault();
this.current = this.default;
Expand Down Expand Up @@ -338,9 +340,10 @@ export class ActiveTextureUnit extends BaseValue<TextureUnitType> {
}
set(v: TextureUnitType) {
if (v === this.current && !this.dirty) return;
this.gl.activeTexture(v);
this.current = v;
this.dirty = false;
}
setDefault() {
this.gl.activeTexture(this.getDefault());
}
}

Expand Down Expand Up @@ -385,15 +388,27 @@ export class BindRenderbuffer extends BaseValue<?WebGLRenderbuffer> {
}

export class BindTexture extends BaseValue<?WebGLTexture> {
slots: Array<?WebGLTexture>;
constructor(context: Context) {
super(context);
this.slots = [];
}
getDefault(): WebGLTexture {
return null;
}
set(v: ?WebGLTexture) {
if (v === this.current && !this.dirty) return;
const gl = this.gl;
gl.bindTexture(gl.TEXTURE_2D, v);
this.current = v;
const textureUnit = this.context.activeTexture;
const slotIndex = textureUnit.current - this.gl.TEXTURE0;
if (this.slots[slotIndex] === v && !this.dirty && !textureUnit.dirty) return;
this.gl.activeTexture(textureUnit.current);
this.gl.bindTexture(this.gl.TEXTURE_2D, v);
this.slots[slotIndex] = v;
this.dirty = false;
textureUnit.dirty = false;
}
get(): ?WebGLTexture {
// Do not use, caching is done per texture unit slot, not globally
return null;
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/render/draw_heatmap.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ function bindFramebuffer(context, painter, layer, scaling) {
if (fbo) { fbo.destroy(); }

const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
context.bindTexture.set(texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
Expand All @@ -111,7 +111,7 @@ function bindFramebuffer(context, painter, layer, scaling) {
bindTextureToFramebuffer(context, painter, texture, fbo, width, height);

} else {
gl.bindTexture(gl.TEXTURE_2D, fbo.colorAttachment.get());
context.bindTexture.set(fbo.colorAttachment.get());
context.bindFramebuffer.set(fbo.framebuffer);
}
}
Expand All @@ -135,7 +135,7 @@ function renderTextureToMap(painter, layer) {
const fbo = layer.heatmapFbo;
if (!fbo) return;
context.activeTexture.set(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, fbo.colorAttachment.get());
context.bindTexture.set(fbo.colorAttachment.get());

context.activeTexture.set(gl.TEXTURE1);
let colorRampTexture = layer.colorRampTexture;
Expand Down
2 changes: 1 addition & 1 deletion src/render/draw_hillshade.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function renderHillshade(painter, coord, tile, layer, depthMode, stencilMode, co
const program = painter.useProgram('hillshade');

context.activeTexture.set(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, fbo.colorAttachment.get());
context.bindTexture.set(fbo.colorAttachment.get());

const uniformValues = hillshadeUniformValues(painter, tile, layer, painter.terrain ? coord.projMatrix : null);

Expand Down
6 changes: 4 additions & 2 deletions src/render/draw_sky.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ function drawSkyboxFromCapture(painter: Painter, layer: SkyLayer, depthMode: Dep
const transform = painter.transform;
const program = painter.useProgram('skybox');

context.activeTexture.set(gl.TEXTURE0);

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, layer.skyboxTexture);

const uniformValues = skyboxUniformValues(transform.skyboxMatrix, layer.getCenter(painter, false), 0, opacity, temporalOffset);
Expand Down Expand Up @@ -144,6 +143,9 @@ function captureSkybox(painter: Painter, layer: SkyLayer, width: number, height:
layer.skyboxGeometry = new SkyboxGeometry(context);
layer.skyboxTexture = context.gl.createTexture();

context.activeTexture.dirty = true;

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, layer.skyboxTexture);
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
Expand Down
3 changes: 2 additions & 1 deletion src/render/painter.js
Original file line number Diff line number Diff line change
Expand Up @@ -988,7 +988,8 @@ class Painter {
canvasCopy(): ?WebGLTexture {
const gl = this.context.gl;
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
this.context.activeTexture.set(gl.TEXTURE0);
this.context.bindTexture.set(texture);
gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, 0);
return texture;
}
Expand Down
7 changes: 4 additions & 3 deletions src/render/texture.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ class Texture {
const {gl} = context;
const {HTMLImageElement, HTMLCanvasElement, HTMLVideoElement, ImageData, ImageBitmap} = window;

gl.bindTexture(gl.TEXTURE_2D, this.texture);

context.bindTexture.set(this.texture);
context.pixelStoreUnpackFlipY.set(false);
context.pixelStoreUnpack.set(1);
context.pixelStoreUnpackPremultiplyAlpha.set(this.format === gl.RGBA && (!options || options.premultiply !== false));
Expand Down Expand Up @@ -90,7 +89,9 @@ class Texture {
bind(filter: TextureFilter, wrap: TextureWrap) {
const {context} = this;
const {gl} = context;
gl.bindTexture(gl.TEXTURE_2D, this.texture);

context.bindTexture.dirty = filter !== this.filter || wrap !== this.wrap;
context.bindTexture.set(this.texture);

if (filter !== this.filter) {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
Expand Down
2 changes: 2 additions & 0 deletions src/util/webp_supported.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ function testWebpTextureUpload(gl: WebGLRenderingContext) {
// Test support for this before allowing WebP images.
// https://github.com/mapbox/mapbox-gl-js/issues/7671
const texture = gl.createTexture();

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);

try {
Expand Down

0 comments on commit e09e055

Please sign in to comment.