Hello Arm graphics team,
We are investigating a reproducible Impeller/OpenGL ES failure on Samsung Galaxy S9 (Firebase Test Lab model starlte), Android 10 / API 29, Mali-G72. Could you help determine whether this matches a known driver issue, and which GPU/driver versions require a workaround?
Public reproducer: github.com/.../mali-crash-app
Flutter issue: github.com/.../190640
Proposed workaround: github.com/.../192158
Self-contained traces and binary identities: github.com/.../evidence.md
The reproducer's Scenario 9 exercises image decode/resize/display using Impeller GLES and shared rendering/resource contexts. The evidence page contains the execution instructions, diagnostic chronology, and APK/engine identities. The driver release string has not yet been included in this report; we do not want to infer it from the device model or Android version.
Observed chronology (condensed, not a standalone GLES reproducer):
1. An old texture with numeric name 7 is initialized and successfully attached to an FBO.
2. It is deleted on another shared context.
3. glGenTextures subsequently returns name 7 for a new logical texture.
4. The upload path binds the destination and issues the upload. The recorded post-upload glGetError is GL_NO_ERROR, but glIsTexture(7) is GL_FALSE.
5. The subsequent glFramebufferTexture2D reports GL_INVALID_OPERATION. The read FBO has no color attachment and is incomplete.
Selected diagnostic fields, with unrelated metadata omitted:
texture.delete.after logical_handle=209 gl_name=7 error=GL_NO_ERROR is_texture=false
texture.generated gl_name=7
upload.tex_sub_image_2d logical_handle=215 gl_name=7 error=GL_NO_ERROR is_texture=false
attachment.framebuffer_texture_2d.after logical_handle=215 gl_name=7 error=GL_INVALID_OPERATION is_texture=false
ConfigureFBO status=GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
[FATAL:flutter/impeller/renderer/backend/gles/blit_pass_gles.cc(88)] Check failed: result. Must be able to encode GL commands without error.
The final SIGABRT is Flutter's response to the failed command encoding, not a directly observed crash inside the Mali driver. We also understand that glIsTexture may legitimately be false immediately after glGenTextures and before the first bind; the concerning observation here is after the upload sequence.
Adding an explicit zero-bind immediately before the destination bind in BlitCopyBufferToTextureCommandGLES::Encode avoids the reproduced failure:
glBindTexture(target, 0);
glBindTexture(target, destination_name);
// Existing buffer-to-texture upload follows.
This variant completed four diagnostic Scenario 9 runs of 606 seconds each without the observed GL/FBO/fatal errors. In contrast, a tested alternative that removed the pre-bind and only unbound after use in the two upload functions still failed after approximately 5.13 seconds (one run). In that trace the previous texture binding originated in InitializeContentsIfNecessary, which passed through neither cleanup site.
Our hypothesis is that the shared-context deletion/name-reuse sequence can leave a stale binding, and a same-numeric-name bind does not restore the intended new object. This is an inference from diagnostics and the workaround comparison, not proof of driver internals; an engine lifetime or context-use error still needs to be ruled out. The diagnostic calls may also affect timing. We are not claiming all Mali devices are affected.
Could you advise:
1. Is this a known GLES texture-name reuse/shared-context issue? Is there an existing erratum or internal tracking reference we can cite?
2. What additional driver identification or reduced GLES/EGL reproduction would you need to investigate it?
3. Is zero-bind followed by destination-bind an appropriate workaround for this sequence?
4. If this is a driver issue, which releases/devices are affected, and is there a fixed release? That would let us scope the workaround and define when it can be removed.
Thank you.
Hi Pete,
Yes. here is the ordering with the context that made each call, taken from an instrumented engine build on the affected device (Galaxy S9 / starlte, Android 10 / API 29, arm64, firmware G960FXXUHFVG4). Every GL call below was logged together with glGetError(), glIsTexture() and eglGetCurrentContext().
## Contexts and threads
Two EGL contexts in one share group, each current on its own thread for the whole run (no context switching; a single eglMakeCurrent per thread, no eglMakeCurrent failures):
Context A onscreen/render context, created with no share context. Current on the render thread. Context B offscreen PBuffer context, created with A as EGL_SHARE_CONTEXT. Current on the image-decode/upload (IO) thread.
### Ordering, GL name 7 (GL_TEXTURE_2D throughout)
1. [B] glGenTextures() -> 7 2. [B] glBindTexture(GL_TEXTURE_2D, 7) glIsTexture(7) = GL_TRUE 3. [B] glTexImage2D() GL_NO_ERROR 4. [B] glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, ..., 7, 0) GL_NO_ERROR, glIsTexture(7) = GL_TRUE (texture 7 is never unbound on context B after this) 5. [A] glDeleteTextures(1, {7}) glIsTexture(7): GL_TRUE before, GL_FALSE after 6. [B] glGenTextures() -> 7 again (new object, same name) 7. [B] glBindTexture(GL_TEXTURE_2D, 7) [B] glTexSubImage2D() GL_NO_ERROR, but glIsTexture(7) = GL_FALSE 8. [B] glFramebufferTexture2D(GL_READ_FRAMEBUFFER, ..., 7, 0) GL_INVALID_OPERATION [B] glCheckFramebufferStatus() GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
So, the texture is created, initialised and attached on context B; it is deleted on context A; context B then receives the same name back from glGenTextures(), and from that point B treats the name as invalid — the upload reports no error but glIsTexture() is false, and the attach fails.
A second captured failure follows the identical pattern with GL name 8 (created/initialised/attached on B, deleted on A, regenerated on B, upload "succeeds" with glIsTexture() false, a
## zero-bind
Step 7's glBindTexture(GL_TEXTURE_2D, 7) is a *redundant* bind from context B's point of view — 7 was already B's currsince step 2 and was never unbound — so it does not appear to trigger the state synchronisation your errata describes. Inserting glBindTexture(GL_TEXTURE_2D, 0) immediately before it makes it a real bind-point change; with that in place the same workload ran 4 × 606 s with zero errors, versus failing at ~5 s without it. You may want the errata woxplicit that the bind must be an actual binding change (bind 0 first if the name may already be current), since a redundant bind satisfies the current wording but does not help.
Can you predict which devices and firmware versions are affected?
We are mitigating today by disabling the affected rendering backend on a hardcoded device list, so we need to know how wide that list has to be and how long it has to stay.
Reproduced with our Test Lab workload:
- Mali-G72 Galaxy S9 (starlte), Android 10, firmware G960FXXUHFVG4 — crash - Mali-G71 Galaxy A10 (a10), Android 10, firmware A105FNXXS6BUB1 — crash
Not reproduced (one run each, all on newer Android releases):
- Mali-G52 Galaxy A31 (a31), Android 12 — pass - Mali-G68 Galaxy A54 (a54x), Android 14 — pass - Mali-G77 Note20 Ultra (c2s), Android 13 — pass - Mali-G57 Galaxy A15 (a15), Android 14 — pass
Production crash reports with the same signature, all on Android 10:
- Mali-G52 Galaxy A31 - Mali-G76 Galaxy S10 / S10 5G / Note10+ 5G
Kind regards,Seunggi