Skip to content

Flutter Web RuntimeEffect rejects derivative built-ins (dFdx/dFdy/fwidth) at runtime #180959

@Laurie-Lin

Description

@Laurie-Lin

Steps to reproduce

  1. Run flutter create bug and open the project.
  2. Add a runtime shader asset shaders/derivatives_repro.frag (see shader code below).
  3. In pubspec.yaml, register the shader:
    flutter:
      shaders:
        - shaders/derivatives_repro.frag
    
  4. Replace main.dart with the code below.
  5. Run on Flutter Web:
    • flutter run -d chrome

⚠️ Note: This issue is Web-only. See the platform notes below.


Expected results

On Flutter Web, the runtime shader should:

  • Run correctly when derivative functions (dFdx / dFdy / fwidth) are supported by the underlying browser backend (e.g. WebGL2), or
  • Fail with a clear runtime capability error indicating that derivatives are not supported on the active Web backend, with actionable guidance.

Behavior should be consistent with other platforms and with WebGL expectations.


Actual results

On Flutter Web only, the shader fails at runtime when the FragmentProgram is instantiated.
Derivative builtins are rejected during runtime effect creation:

RuntimeEffect error error: 22: no match for dFdx(float)
    dx = dFdx(uv.x);
         ^^^^^^^^^^
error: 23: no match for dFdy(float)
    dy = dFdy(uv.y);
         ^^^^^^^^^^
error: 24: no match for fwidth(float)
    fw = fwidth((uv.x + uv.y) + (sin(iTime) * 0.0));
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 errors

Platform comparison

  • macOS (Skia): works correctly
  • macOS (Impeller disabled): works correctly
  • Android: works correctly
  • iOS: works correctly
  • Web (Chrome, JS & WASM): fails at runtime

The same browser (Chrome) successfully runs derivative-based shaders on ShaderToy, indicating that the Web platform itself supports derivatives.
The same runtime failure occurs when running with --wasm; the behavior is identical to the JS backend.
This suggests a Flutter Web–specific runtime shader validation / translation issue, rather than a general SkSL or shader logic problem.


Code sample

Code sample
// lib/main.dart
import 'dart:ui' as ui;
import 'package:flutter/material.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Preload shader so failure is obvious and happens immediately.
  final ui.FragmentProgram program =
      await ui.FragmentProgram.fromAsset('shaders/derivatives_repro.frag');

  runApp(MaterialApp(
    home: Scaffold(
      body: Center(
        child: CustomPaint(
          size: const Size(512, 512),
          painter: _ShaderPainter(program),
        ),
      ),
    ),
  ));
}

class _ShaderPainter extends CustomPainter {
  _ShaderPainter(this.program);

  final ui.FragmentProgram program;

  @override
  void paint(Canvas canvas, Size size) {
    final shader = program.fragmentShader();

    // Pass uniforms (by index) for runtime_effect.glsl:
    // iResolution: vec2, iTime: float
    shader
      ..setFloat(0, size.width)
      ..setFloat(1, size.height)
      ..setFloat(2, 0.0);

    canvas.drawRect(Offset.zero & size, Paint()..shader = shader);
  }

  @override
  bool shouldRepaint(covariant _ShaderPainter oldDelegate) => false;
}
// shaders/derivatives_repro.frag
#include <flutter/runtime_effect.glsl>
precision highp float;
precision highp int;

uniform vec2 iResolution;
uniform float iTime;

out vec4 fragColor;

void main() {
    vec2 fragCoord = FlutterFragCoord().xy;
    vec2 uv = fragCoord / max(iResolution, vec2(1.0));

    float dx = 0.0;
    float dy = 0.0;
    float fw = 0.0;

    dx = dFdx(uv.x);
    dy = dFdy(uv.y);
    fw = fwidth((uv.x + uv.y) + (sin(iTime) * 0.0));

    vec3 rgb = vec3(abs(dx), abs(dy), abs(fw)) * 200.0;
    fragColor = vec4(clamp(rgb, 0.0, 1.0), 1.0);
}

Logs

Logs
RuntimeEffect error error: 22: no match for dFdx(float)
    dx = dFdx(uv.x);
         ^^^^^^^^^^
error: 23: no match for dFdy(float)
    dy = dFdy(uv.y);
         ^^^^^^^^^^
error: 24: no match for fwidth(float)
    fw = fwidth((uv.x + uv.y) + (sin(iTime) * 0.0));
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 errors

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.38.4, on macOS 26.2 25C56 darwin-arm64, locale zh-Hans-CN)
    • Flutter version 3.38.4 on channel stable
    • Framework revision 66dd93f9a2
    • Engine revision a5cb96369e
    • Dart version 3.10.3
    • DevTools version 2.51.1

[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 26.1.1)
[✓] Chrome - develop for the web
    • Google Chrome 143.0.7499.193
[✓] Connected device (3 available)
    • Chrome (web) • chrome • web-javascript • Google Chrome 143.0.7499.193

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: renderingUI glitches reported at the engine/skia or impeller rendering levelengineflutter/engine related. See also e: labels.found in release: 3.38Found to occur in 3.38found in release: 3.40Found to occur in 3.40has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-webWeb applications specificallyteam-webOwned by Web platform teamtriaged-webTriaged by Web platform team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions