OpenCL RGBA/HALF image corruption under concurrent GLES workload on Mali-G720 and Mali-G610

mali-opencl-image-repro-20260923.zip

Hello Arm team,

I would like to report a reproducible OpenCL image-content inconsistency under a concurrent OpenGL ES workload on two Android devices with Mali GPUs.

The attached ZIP contains a standalone synthetic reproduction: an arm64 APK, exact source and build script, reproduction instructions, raw first-failure data, all control runs, device/driver information, SHA-256 manifests and an offline verifier. It does not require any third-party application framework, model, proprietary SDK or private input data. The APK uses native Android GLES and calls the vendor OpenCL driver directly.

Tested environments

- OPPO PKZ110, Android 15, Mali-G720 MC7, GLES driver r49p1.
- vivo V2285A, Android 15, Mali-G610 MC4, GLES driver r38p1.

Full version strings, OS fingerprints and driver-library hashes are included in the attachment.

Reproduction outline

A native GLES 3 thread continuously creates a 1536x3072 R8 texture, clears it through an FBO, samples it into the window, swaps and deletes the texture. After 30 frames, a separate OpenCL context starts an in-order low-priority queue. There is no GL/CL resource sharing.

Each CL generation uses a float4 input and two 1x1 CL_RGBA/CL_HALF_FLOAT images. A kernel converts the input to half and writes the ordinary image and an independently initialized shadow image with opposite-sign markers. The inputs are exactly representable in HALF and include a unique per-process marker. We check the source buffer, conversion echo, both host image readbacks, both GPU-reader outputs and event completion.

Observed behavior

The ordinary image can contain incorrect data even though the original source and conversion echo are correct and the writer/reader events report CL_COMPLETE. Its host readback matches the preceding generation's negative shadow marker; the GPU-reader output is also incorrect and differs from the host readback. This is a numerical observation, not a claim of proven physical aliasing.

After the first ordinary mismatch, the same image is retained without rewriting it. All 12 failed ordinary images remained wrong during 301 additional paired host/GPU reads each, with GLES continuing to run. Earlier shadow-only mismatches are also preserved and reported separately.

Controlled comparison using the same attached APK

On EACH device we ran three independent baseline -> copy -> baseline groups (nine cold processes per device):

- Direct kernel image stores: all three initial baselines and all three returns reproduced an ordinary-image mismatch.

- Alternative upload: the kernel writes tightly packed half buffers, then clEnqueueCopyBufferToImage copies each buffer into its original target image. All three cold processes completed 10,000 generations each without any content error (30,000 generations per device).

- The copy path adds no retry, extra leading kernel, queue-wide finish or GL pause before the original content checks. Its buffers remain alive through the subsequent blocking readbacks.

All 18 test runs are included. No API errors, incomplete test captures or log overflows occurred in this batch. Iteration counts are exposure counts, not independent probability trials. The alternative path changes allocations and command submission as well as the store mechanism, so the result does not identify the internal cause or establish a universal workaround.

Could the Mali driver team inspect this reproduction and advise whether it corresponds to a known issue, whether a corrected driver revision is available, and what additional targeted information would help investigate it? If delivery through another support channel is needed, please let me know the appropriate route.

Please begin with README.md and RESULTS.md; running python3 verify.py checks integrity and recomputes the preserved failure values offline.

Thank you.