Skip to content

Fragment shaders fail to render using uniform arrays on Android with Impeller GLES. #170647

Closed

Description

@heyarny

Steps to reproduce

I would like to create dynamic shaders with array of data.
Note the use of uniform float uRadii[8]; inside shaders file.
This works fine on iOS, but using Android there is simply nothing.
Tried with Impella enabled & disabled.

Tried with versions 3.29.3, 3.32.4 & 3.33.0-1.0.pre.477.

Expected results

Shader should draw circles.

Actual results

Nothing.

Code sample

Shader example
#include <flutter/runtime_effect.glsl>

// 0..1 : canvas size in logical px
uniform vec2  u_size;
// 2    : how many circles to draw (as float)
uniform float uCount;
// 3..10: up to 8 radii in logical px
uniform float uRadii[8];

out vec4 fragColor;

// draw a red circle with hard edge
vec4 drawCircle(vec2 p, vec2 center, float r) {
    float m = step(length(p - center), r);
    return vec4(1.0, 0.0, 0.0, m);
}

void main() {
    vec2 p   = FlutterFragCoord().xy;       // logical px
    float cy = 0.5 * u_size.y;              // vertical center
    vec4 col = vec4(0.0);

    // loop unrolled to max 8
    for (int i = 0; i < 8; i++) {
        if (float(i) < uCount) {
            // evenly spaced X
            float cx = (float(i) + 1.0) / (uCount + 1.0) * u_size.x;
            float r  = uRadii[i];
            col = max(col, drawCircle(p, vec2(cx, cy), r));
        }
    }

    fragColor = col;
}
Flutter sample
import 'dart:ui';
import 'package:flutter/material.dart';

void main() => runApp(const MaterialApp(home: LogicalCirclesDemo()));

class LogicalCirclesDemo extends StatefulWidget {
  const LogicalCirclesDemo({super.key});
  @override
  State<LogicalCirclesDemo> createState() => _LogicalCirclesDemoState();
}

class _LogicalCirclesDemoState extends State<LogicalCirclesDemo> {
  late final FragmentProgram _prog;
  bool _ready = false;

  // your desired radii in **logical** pixels:
  final List<double> _radii = [50, 30, 70, 40, 60];

  @override
  void initState() {
    super.initState();
    FragmentProgram.fromAsset('shaders/circle.frag')
      .then((p) => setState(() {
        _prog = p;
        _ready = true;
      }));
  }

  @override
  Widget build(BuildContext context) {
    if (!_ready) {
      return const Scaffold(
        body: Center(child: CircularProgressIndicator()),
      );
    }

    // **Logical** size of the canvas:
    final sizeLogical = MediaQuery.of(context).size;

    return Scaffold(
      body: CustomPaint(
        size: sizeLogical,
        painter: _LogicalCirclesPainter(
          program: _prog,
          size:    sizeLogical,
          radii:   _radii,
        ),
      ),
    );
  }
}

class _LogicalCirclesPainter extends CustomPainter {
  final FragmentProgram program;
  final Size           size;
  final List<double>   radii;

  _LogicalCirclesPainter({
    required this.program,
    required this.size,
    required this.radii,
  });

  @override
  void paint(Canvas canvas, Size _) {
    // configure the shader with **logical** dimensions
    final shader = program.fragmentShader()
      // u_size.xy in logical px
      ..setFloat(0, size.width)
      ..setFloat(1, size.height)
      // uCount
      ..setFloat(2, radii.length.toDouble());

    // uRadius0..uRadius7 → slots 3..10
    for (int i = 0; i < radii.length && i < 8; i++) {
      shader.setFloat(3 + i, radii[i]);
    }
    // zero out any unused
    for (int i = radii.length; i < 8; i++) {
      shader.setFloat(3 + i, 0.0);
    }

    // draw a full‐screen quad in logical space:
    final paint = Paint()..shader = shader;
    canvas.drawRect(Offset.zero & size, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter old) => false;
}

Screenshots or Video

On iOS (Working) Image

Logs

No response

Flutter Doctor output

Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.32.4, on macOS 15.5 24F74 darwin-arm64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0)
[!] Xcode - develop for iOS and macOS (Xcode 16.4)
    ! CocoaPods 1.15.2 out of date (1.16.2 is recommended).
        CocoaPods is a package manager for iOS or macOS platform code.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/to/platform-plugins
      To update CocoaPods, see https://guides.cocoapods.org/using/getting-started.html#updating-cocoapods
[✓] Chrome - develop for the web
[✓] Android Studio (version 2024.3)
[✓] VS Code (version 1.101.0)
[✓] Connected device (6 available)
[✓] Network resources

Activity

  1. darshankawar commented on Jun 16, 2025

    @darshankawar
    Member

    Thanks for the report. On Android, we see as below:

    Image

    Tried with Impella enabled & disabled.

    This seems to be specific to impeller on Android, as disabling it, properly shows the fragment being rendered like iOS.

    Image

    Verified on stable : 3.32.4 and master: 3.33.0-1.0.pre.494

  2. added
    platform-androidAndroid applications specifically
    engineflutter/engine related. See also e: labels.
    c: renderingUI glitches reported at the engine/skia or impeller rendering level
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    e: impellerImpeller rendering backend issues and features requests
    and removed
    in triagePresently being triaged by the triage team
    on Jun 16, 2025
  3. changed the title [-]Fragment shaders fail to render using uniform arrays on Android[/-] [+]Fragment shaders fail to render using uniform arrays on Android with Impeller[/+] on Jun 16, 2025
  4. added
    P2Important issues not at the top of the work list
    on Jun 16, 2025
  5. jonahwilliams commented on Jun 16, 2025

    @jonahwilliams
    Contributor

    From testing, this works fine on Skia and Impeller Vulkan. It fails to render on the GLES backend.

  6. changed the title [-]Fragment shaders fail to render using uniform arrays on Android with Impeller[/-] [+]Fragment shaders fail to render using uniform arrays on Android with Impeller GLES.[/+] on Jun 16, 2025
  7. added
    r: fixedIssue is closed as already fixed in a newer version
    on Jun 19, 2025
  8. github-actions commented on Jul 3, 2025

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  9. locked as resolved and limited conversation to collaborators on Jul 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listc: renderingUI glitches reported at the engine/skia or impeller rendering levele: impellerImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.found in release: 3.32Found to occur in 3.32found in release: 3.33Found to occur in 3.33has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-androidAndroid applications specificallyr: fixedIssue is closed as already fixed in a newer versionteam-engineOwned by Engine teamtriaged-engineTriaged by Engine team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions