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.
*EDIT* Bug description clarified. Hi,
I can confirm we have a known driver errata where attaching or reattaching a texture or renderbuffer to an FBO attachment in a shared context does not always resync the shared state from another context. This is not yet in our non-confidential errata document, but I will get it added and let you know the tracking ID for it.
Attaching texture ID zero and then attaching the real ID might not be enough to sync the texture. The recommended workaround for this issue is to bind the texture to a bind point, using glBindTexture(), before changing the attachment.
This is a long standing issue and there is no fixed driver shipping, so workarounds should assume all current Arm GPUs are impacted. Any future fix versions will be published in the non-confidential errata document.
The non-confidential document is here, and I'll try and get the errata added in the next week.
support.arm.com/.../
Kind regards, Pete
I would add, it's not entirely clear from your description which context makes each API call and how they are interleaved. Can you clarify the ordering of commands and which context makes each call, so that we can confirm this is your issue?
This is the errata writeup we'll be using - can you confirm if this matches what you are seeing:
Description Attaching a texture or renderbuffer to a framebuffer object does not trigger synchronization with state updates made in a shared context. Implications An application might encounter incorrect rendering because reattaching a resource fails to synchronize state updates. An application might encounter an API error if the stale render state results in invalid API behavior. Workaround You can bind the resource to a bind point using glBindTexture() or glBindRenderBuffer() to force a state synchronization, before attaching the resource to a framebuffer object.
Attaching a texture or renderbuffer to a framebuffer object does not trigger synchronization with state updates made in a shared context.
An application might encounter incorrect rendering because reattaching a resource fails to synchronize state updates.
An application might encounter an API error if the stale render state results in invalid API behavior.
You can bind the resource to a bind point using glBindTexture() or glBindRenderBuffer() to force a state synchronization, before attaching the resource to a framebuffer object.
Kind regards,
Pete
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
Thanks for confirming - we'll look more. This sounds like a different issue, not the one I originally thought.
OK, I have found the correct driver errata this time and it matches your API sequence. This erratum impacts Bifrost and Valhall GPU driver versions between r17p0 and r23p0, and was fixed in r24p0. Some OEMs may have taken a patch for an earlier driver version - applications have no way to tell, but you might find some devices in the impacted version range will not reproduce the issue.
Your workaround of binding texture zero before rebinding the actual desired name is valid and will reliably avoid the issue.
This driver version is below the current cutoff for our public errata document, which only covers r36p0 or later, so this issue won't be included in the next update. If you need a reference for it you can use "Arm errata EN_ID 1,792,661".