WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
NEW
235478
WebGL enabling Blend causes high performance drop
https://bugs.webkit.org/show_bug.cgi?id=235478
Summary
WebGL enabling Blend causes high performance drop
Reinis
Reported
2022-01-22 07:16:52 PST
I develop a game using WebGL2. If I enable `gl.enable(gl.BLEND);` it causes the framerate to go down from 30 to 4. (Macbook air M1, but the same is for my iPad and iPhone as well) In my scene, I have around 60k vertices (Updated every frame) + I use blend to overlay the screen with texture. ``` ........ // Bind uniforms gl.uniformBlockBinding(this.glProgram, this.uniBlockMain, 0); gl.uniform1i(this.uniTextures, 1); // texture sampler array is bound to texture1 gl.uniform2fv(this.uniTextureOffsets, this.textureOffsets, 0); // We just allow the GL to do face culling. Note this requires the priority renderer // to have logic to disregard culled faces in the priority depth testing. gl.enable(gl.CULL_FACE); // Enable blending for alpha gl.enable(gl.BLEND); gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); // Draw buffers gl.bindVertexArray(this.vaoHandle); gl.enableVertexAttribArray(0); gl.bindBuffer(gl.ARRAY_BUFFER, this.tmpVertexBuffer.buffer); gl.vertexAttribIPointer(0, 4, gl.INT, 0, 0); gl.enableVertexAttribArray(1); gl.bindBuffer(gl.ARRAY_BUFFER, this.tmpUvBuffer.buffer); gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0); gl.drawArrays(gl.TRIANGLES, 0, this.vertexBuffer.length() / 4); // gl.disable(gl.BLEND); gl.disable(gl.CULL_FACE); gl.useProgram(null); this.vertexBuffer.clear(); this.uvBuffer.clear(); this.drawUi(canvasWidth, canvasHeight); gl.flush(); ..... ``` ```` private drawUi(canvasWidth: number, canvasHeight: number) { const gl = this.gl; gl.enable(gl.BLEND); gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); gl.bindTexture(gl.TEXTURE_2D, this.interfaceTexture); gl.useProgram(this.glUiProgram); gl.uniform2i(this.uniTexSourceDimensions, canvasWidth, canvasHeight); gl.viewport(0, 0, canvasWidth, canvasHeight); gl.uniform2i(this.uniTexTargetDimensions, canvasWidth, canvasHeight); // Texture on UI gl.bindVertexArray(this.vaoUiHandle); gl.drawArrays(gl.TRIANGLE_FAN, 0, 4); gl.disable(gl.BLEND); } ``` Running on chrome I get stable 60fps :/
Attachments
Add attachment
proposed patch, testcase, etc.
Alexey Proskuryakov
Comment 1
2022-01-23 17:27:15 PST
This seems like two issues: frame rate being 2x too low without blend, and 15x too low with it. Could you please provide a complete test case that can be viewed in a browser?
Reinis
Comment 2
2022-01-24 01:47:07 PST
I have a working demo of my project here
https://play.rsps.app/
Let me know if this is enough to check, or if I should create a smaller test case.
Reinis
Comment 3
2022-01-24 02:52:44 PST
I have made a bit of a breakthrough. Issue happens only if I render textures in the scene. Otherwise, it is solid 50 fps ``` export const fragmentShader = `#version 300 es precision highp float; precision highp int; precision highp sampler2DArray; uniform sampler2DArray textures; uniform vec2 textureOffsets[128]; uniform float brightness; uniform float smoothBanding; uniform vec4 fogColor; uniform int colorBlindMode; uniform float textureLightMode; in vec4 Color; centroid in float fHsl; flat in int textureId; in vec2 fUv; in float fogAmount; out vec4 FragColor; ${hslToRgb} void main() { vec4 c; // if (textureId > 0) { // int textureIdx = textureId - 1; // vec2 animatedUv = fUv + textureOffsets[textureIdx]; // vec4 textureColor = texture(textures, vec3(animatedUv, float(textureIdx))); // vec4 textureColorBrightness = pow(textureColor, vec4(brightness, brightness, brightness, 1.0f)); // vec3 mul = 1.0 - (Color.rgb); // c = textureColorBrightness * vec4(mul, 1.f); // } else { c = Color; // } vec3 mixedColor = mix(c.rgb, fogColor.rgb, fogAmount); FragColor = vec4(mixedColor, c.a); } `; ``` This is my fragment shader I have commented part and it works smooth. ``` export const initTextureArray = (gl: WebGL2RenderingContext): WebGLTexture | null => { if (!allTexturesLoaded()) { return null; } const textures = Rasterizer3D.textures; const textureArray = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D_ARRAY, textureArray); gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 8, gl.RGBA8, TEXTURE_SIZE, TEXTURE_SIZE, textures.length); gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); // Set brightness to 1.0d to upload unmodified textures to GPU const save = Rasterizer3D.brightness; Rasterizer3D.setBrightness(1.0); updateTextures(gl); Rasterizer3D.setBrightness(save); gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D_ARRAY, textureArray); gl.generateMipmap(gl.TEXTURE_2D_ARRAY); gl.activeTexture(gl.TEXTURE0); return textureArray; }; ``` Code responsible for loading `uniform sampler2DArray textures;` I did notice this bug
https://bugs.webkit.org/show_bug.cgi?id=223322
I wonder if it is related. Maybe my textures change internal pixel format that safari doesn't support well?
Reinis
Comment 4
2022-01-24 03:21:12 PST
The 30 FPS limit I noticed before was because the console was open. Didn't know before that it affects it. Seems like I found the issue.. * Causes lag ``` int textureIdx = textureId - 1; vec2 animatedUv = fUv + textureOffsets[textureIdx]; ``` * Causes lag ``` int textureIdx = textureId - 1; if (textureIdx > 127) { c = Color; return; } vec2 animatedUv = fUv + textureOffsets[textureIdx]; ``` * Doesn't lag ``` int textureIdx = textureId - 1; vec2 animatedUv = fUv + textureOffsets[1]; ``` * Doesn't lag ``` int textureIdx = 1; vec2 animatedUv = fUv + textureOffsets[textureIdx]; ``` * Doesn't lag ``` int textureIdx = textureId - 1; vec2 animatedUv = fUv; ``` I did a bit more experiments, but it seems that using `flat in int textureId;` as an index in `uniform vec2 textureOffsets[128];` causes lag.
Kenneth Russell
Comment 5
2022-01-24 11:01:09 PST
The use of flat interpolation will probably trigger a code path where indices will be rewritten every frame. This is a known area for future optimization in the Metal backend. Please try to create a smaller test case. This report is not easily investigated without one. Thanks.
Radar WebKit Bug Importer
Comment 6
2022-01-29 07:17:18 PST
<
rdar://problem/88224455
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug