Created attachment 388497 [details] source code for repro case Sometimes calling gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video) populates the texture with frame data that is old, usually 2-3 frames old but sometimes 15 or more. When drawing these textures to a canvas, this gives an impression that the video feed is jumping, because a scene from a while ago will flash momentarily. The effect is rare in normal conditions but can be reliably triggered by extending the length of an animation frame by a long random interval, e.g. 20ms-200ms. The effect can be mitigated by skipping every other animation frame, i.e. const nativeRaf = window.requestAnimationFrame window.requestAnimationFrame = (fn) => nativeRaf(() => nativeRaf((timestamp) => fn(timestamp))) A repro case can be viewed on an iphone here: 8th.io/ft4h9 The repro app does the following: * getUserMedia -> stream -> video * video -> texture (there is a rotating pool of 10 textures) * texture -> luminance shader -> framebuffer -> readpixels -> uint8array * texture -> canvas -> window * uint8array -> frame hash code based on pixel content -> frame hash history * search frame hash history to find duplicate hashes * if there is a duplicate hash, print the number of frames ago for the duplicate frame pixels (do this for the 5 most recent duplicates), and increment a counter for the number of duplicate frames. We tested this with an iPhone11 Pro with iOS 13.3. Source code for the repro is attached.
<rdar://problem/58825426>
I am wondering whether this still repro with WebKit ToT. We got rid off re-enqueuing samples when the display layer could not go fast enough, which could explain why old samples would come back.
As you mention using a texture pool, this sounds like a duplicate of Bug 203148. Effectively there's an optimization in WebKit that prevents re-uploading frames if the source video hasn't changed since the last texImage2d call, but it fails to check whether a different texture is now bound. In that case the previous content of the newly-bound texture is left unchanged, which with a texture pool will probably appear to be an older frame.