Steps to reproduce
Remaining issue: first-dialog raster stalls in a fresh native Windows process, reproduced on current master. The separate sustained warm-opening slowdown observed on stable 3.47.2 is substantially improved on master; this report does NOT claim that warm problem remains unfixed.
Standalone sample uses only Flutter framework widgets: no backend/application code, plugins, images, custom fonts, BackdropFilter, shader packages, startup shader warm-up or hidden dialog pre-render.
- Unzip the attached probe. Run flutter pub get, then flutter build windows --profile.
- Run a fresh process with Impeller and --auto --variant=baseline --renderer=Impeller. Repeat with Skia on the same monitor/client viewport. Exact child-process switches are in README. With flutter run use --enable-impeller versus --no-enable-impeller, --dart-define=PROBE_AUTO=true, and --dart-define=PROBE_RENDERER=Impeller or Skia. The label alone does NOT select the backend.
- Wait for six open/close cycles and the JSON report. Do not manually open before the batch. Compare opening cycle 1 separately from cycles 2-6 and closing. Close only after the report; omit the optional --exit flag (separate native teardown failure after JSON).
- Repeat a fresh process. Master traces additionally use --trace-skia. No performance overlay or video capture.
Expected: the first small opaque rounded dialog should not lose most of its 260ms fade/slide/scale animation to long raster stalls.
Observed on master framework d03768e, engine content hash ad9da2e50980fdf83889721559c19f5403ef8f87 (2026-10-02):
| First opening / fresh process |
Captured opening frames |
Raster max ms |
Warm opening raster median ms |
| Impeller baseline |
4 |
283.277 |
5.354 |
| Skia baseline |
15 |
91.622 |
2.431 |
| Impeller noScale |
4 |
396.714 |
5.487 |
| Impeller baseline confirmation |
5 |
183.074 |
4.674 |
| Skia baseline, trace-skia capture |
35 |
45.582 |
1.877 |
| Impeller baseline, trace-skia capture |
6 |
125.993 |
4.541 |
Both renderers can have first-opening spikes; observed Impeller spikes are greater. Results vary with startup/driver caches, so maxima are NOT fixed latency guarantees; first-opening sample counts are small. In the master traced Impeller run the first-opening raster p50 was 60.560ms, UI/build max 3.760ms; corresponding Skia raster p50 2.619ms, UI max 1.541ms. Raw frames and complete non-empty timelines are attached. No failures/dropped samples in the reports. Raster timing is engine FrameTiming, not GPU utilization or proof of an engine/driver/shader root cause.
Warm means pooled opening cycles 2-6 including settle/rest frames. On stable 3.47.2 warm Impeller median was 35.734ms versus Skia 2.097ms; noScale 6.277ms. On master this warm scale penalty disappears. Back-to-back old-SDK control still measured 34.702ms versus master 4.674ms. The remaining first-opening stalls also occur without scale.
Cold here means first dialog in a fresh process, NOT cleared GPU/disk caches. Same physical host, source, window, monitor and renderer selection method. Master SDK was separate; production SDK/PATH were not switched. Its depth-1 clone fetched one official version tag for dependency resolution; exact commit/content hash above are the tested identity.
Related context: #191207 uses BackdropFilter, absent here. #191175/#183495 concern Vulkan support; this is a measured first-opening performance report for the existing OpenGLESSDF backend, not a Vulkan feature request.
Code sample
The attached ZIP contains the complete self-contained lib/main.dart and a stock Windows Flutter runner (only the initial client size is adjusted). No plugins or extra assets are needed; uses-material-design: true. Copy lib/main.dart into a fresh flutter create --platforms=windows app if preferred. The native runner adjustment keeps the CLIENT viewport 540x960 logical pixels, rather than sizing the outer frame. The automatic collector is included to make cold/warm opening measurements repeatable.
Relevant transition excerpt from the measured source (complete runnable file in ZIP):
RawDialogRoute<void> createProbeRoute(
BuildContext context,
ProbeVariant variant, {
bool interactive = true,
}) => RawDialogRoute<void>(
barrierDismissible: interactive,
barrierLabel: 'Close dialog',
barrierColor: const Color(0x6b000000),
transitionDuration: const Duration(milliseconds: 260),
pageBuilder: (context, animation, secondaryAnimation) =>
ProbeDialog(variant: variant, interactive: interactive),
transitionBuilder: (context, animation, secondaryAnimation, child) {
final curved = animation.drive(CurveTween(curve: Curves.easeOutCubic));
Widget result = variant == ProbeVariant.withRepaintBoundary
? RepaintBoundary(child: child)
: child;
if (variant != ProbeVariant.noScale)
result = ScaleTransition(
scale: Tween<double>(begin: 0.96, end: 1).animate(curved),
child: result,
);
result = SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 0.035),
end: Offset.zero,
).animate(curved),
child: result,
);
if (variant != ProbeVariant.noFade)
result = FadeTransition(opacity: curved, child: result);
return result;
},
);
ProbeDialog is a transparent Dialog wrapping an opaque static-gradient rounded PhysicalModel panel, elevation 12, Clip.antiAlias, two rounded opaque gradient cards, ordinary Cyrillic Text and Material icons. noShadow changes only elevation to 0; noText hides text painting while retaining layout (icon-font glyphs remain). No BackdropFilter. The complete source includes all details and window-boundary/raw-frame reporting.
Performance profiling on master channel
Timeline Traces
ZIP below contains the complete framework-only source, raw FrameTiming JSON for stable/master runs, environment metadata and redacted doctor outputs, and non-empty .pftrace files. Open .pftrace with Perfetto UI. These are VM-service getPerfettoVMTimeline exports (default Dart/Embedder streams), not DevTools JSON exports. Master files ending master-traced additionally use the engine trace-skia switch; no performance overlay/recording. FrameTiming raw samples/window boundaries provide the quantitative first/warm opening comparisons separately. No source-application traces, order data, usernames, local paths, auth URLs or secrets are included.
flutter-windows-dialog-repro-2026-10-02.zip
Video demonstration
No video capture was used during the measurements. Source, raw FrameTiming results and non-empty Perfetto timelines are attached.
What target platforms are you seeing this bug on?
Windows
OS/Browser name and version | Device information
Native Windows desktop (not web, emulator, or simulator). Windows 11 Pro 23H2, build 22631.6199; x64; Intel Core i9-13900HK; Intel Iris Xe integrated graphics, driver 32.0.101.7082; 32 GB RAM. Built and measured in profile mode. Window client 540x960 logical pixels, DPR 2.0, 1080x1920 physical pixels; display reports 120 Hz; OS text scale 1.0. Same monitor/window/driver for the Impeller and Skia processes. No performance overlay or screen recording.
Does the problem occur on emulator/simulator as well as on physical devices?
Unknown
Is the problem only reproducible with Impeller?
No
Logs
Native profile builds succeeded on both SDKs; source and raw measurements are in ZIP. Backend banners:
Stable Impeller: embedder_surface_gl_impeller.cc(126): Using the Impeller rendering backend (OpenGLESSDF).
Master Impeller: embedder_surface_gl_impeller.cc(127): Using the Impeller rendering backend (OpenGLESSDF).
Skia processes use enable-impeller=false. The engine switch reader prepends -- itself; environment switch values intentionally have no -- prefix. Switches are child-process-only. Master trace runs use FLUTTER_ENGINE_SWITCHES=2, switch 1=enable-impeller=true/false, switch 2=trace-skia. Raw reports have failure=null, droppedFrameCount=0, explicit first/warm/closing sample windows and actual viewport/DPR. No per-frame console logging during transitions. VM-service auth URLs are omitted.
Flutter Doctor output
Full redacted doctor-stable.txt and doctor-master.txt are in the attached ZIP. Selected identity/toolchain output:
Stable: Flutter 3.47.2, channel stable
Framework d3b14c8769, engine a804b26164
Dart 3.13.2, DevTools 2.60.0
Master: Flutter 3.49.0-0.2.pre (depth-1 clone; use exact revision below), channel master
Framework d03768eef05516a030f4eb12457b0d297111d526
Engine content hash ad9da2e50980fdf83889721559c19f5403ef8f87
Dart 3.14.0-294.0.dev, DevTools 2.61.0
Windows 11 Pro 23H2, 22631.6199, x64
Visual Studio Build Tools 2019 16.11.50
Windows 10 SDK 10.0.19041.0
Windows desktop device available; native profile build successful
Android SDK unavailable (not relevant to Windows reproduction)
Master is a separate diagnostic SDK invoked by absolute path; default PATH intentionally remains on stable. For doctor only, FLUTTER_GIT_URL was scoped to the local official SDK clone to avoid fetching all historical tags after retrieving one official version tag. Doctor reports the intentional PATH/local-mirror warnings. This did not change the source revision, engine artifacts, native build or renderer selection.
Steps to reproduce
Remaining issue: first-dialog raster stalls in a fresh native Windows process, reproduced on current master. The separate sustained warm-opening slowdown observed on stable 3.47.2 is substantially improved on master; this report does NOT claim that warm problem remains unfixed.
Standalone sample uses only Flutter framework widgets: no backend/application code, plugins, images, custom fonts, BackdropFilter, shader packages, startup shader warm-up or hidden dialog pre-render.
Expected: the first small opaque rounded dialog should not lose most of its 260ms fade/slide/scale animation to long raster stalls.
Observed on master framework d03768e, engine content hash ad9da2e50980fdf83889721559c19f5403ef8f87 (2026-10-02):
Both renderers can have first-opening spikes; observed Impeller spikes are greater. Results vary with startup/driver caches, so maxima are NOT fixed latency guarantees; first-opening sample counts are small. In the master traced Impeller run the first-opening raster p50 was 60.560ms, UI/build max 3.760ms; corresponding Skia raster p50 2.619ms, UI max 1.541ms. Raw frames and complete non-empty timelines are attached. No failures/dropped samples in the reports. Raster timing is engine FrameTiming, not GPU utilization or proof of an engine/driver/shader root cause.
Warm means pooled opening cycles 2-6 including settle/rest frames. On stable 3.47.2 warm Impeller median was 35.734ms versus Skia 2.097ms; noScale 6.277ms. On master this warm scale penalty disappears. Back-to-back old-SDK control still measured 34.702ms versus master 4.674ms. The remaining first-opening stalls also occur without scale.
Cold here means first dialog in a fresh process, NOT cleared GPU/disk caches. Same physical host, source, window, monitor and renderer selection method. Master SDK was separate; production SDK/PATH were not switched. Its depth-1 clone fetched one official version tag for dependency resolution; exact commit/content hash above are the tested identity.
Related context: #191207 uses BackdropFilter, absent here. #191175/#183495 concern Vulkan support; this is a measured first-opening performance report for the existing OpenGLESSDF backend, not a Vulkan feature request.
Code sample
The attached ZIP contains the complete self-contained lib/main.dart and a stock Windows Flutter runner (only the initial client size is adjusted). No plugins or extra assets are needed; uses-material-design: true. Copy lib/main.dart into a fresh flutter create --platforms=windows app if preferred. The native runner adjustment keeps the CLIENT viewport 540x960 logical pixels, rather than sizing the outer frame. The automatic collector is included to make cold/warm opening measurements repeatable.
Relevant transition excerpt from the measured source (complete runnable file in ZIP):
ProbeDialog is a transparent Dialog wrapping an opaque static-gradient rounded PhysicalModel panel, elevation 12, Clip.antiAlias, two rounded opaque gradient cards, ordinary Cyrillic Text and Material icons. noShadow changes only elevation to 0; noText hides text painting while retaining layout (icon-font glyphs remain). No BackdropFilter. The complete source includes all details and window-boundary/raw-frame reporting.
Performance profiling on master channel
Timeline Traces
ZIP below contains the complete framework-only source, raw FrameTiming JSON for stable/master runs, environment metadata and redacted doctor outputs, and non-empty .pftrace files. Open .pftrace with Perfetto UI. These are VM-service getPerfettoVMTimeline exports (default Dart/Embedder streams), not DevTools JSON exports. Master files ending master-traced additionally use the engine trace-skia switch; no performance overlay/recording. FrameTiming raw samples/window boundaries provide the quantitative first/warm opening comparisons separately. No source-application traces, order data, usernames, local paths, auth URLs or secrets are included.
flutter-windows-dialog-repro-2026-10-02.zip
Video demonstration
No video capture was used during the measurements. Source, raw FrameTiming results and non-empty Perfetto timelines are attached.
What target platforms are you seeing this bug on?
Windows
OS/Browser name and version | Device information
Native Windows desktop (not web, emulator, or simulator). Windows 11 Pro 23H2, build 22631.6199; x64; Intel Core i9-13900HK; Intel Iris Xe integrated graphics, driver 32.0.101.7082; 32 GB RAM. Built and measured in profile mode. Window client 540x960 logical pixels, DPR 2.0, 1080x1920 physical pixels; display reports 120 Hz; OS text scale 1.0. Same monitor/window/driver for the Impeller and Skia processes. No performance overlay or screen recording.
Does the problem occur on emulator/simulator as well as on physical devices?
Unknown
Is the problem only reproducible with Impeller?
No
Logs
Native profile builds succeeded on both SDKs; source and raw measurements are in ZIP. Backend banners:
Skia processes use enable-impeller=false. The engine switch reader prepends -- itself; environment switch values intentionally have no -- prefix. Switches are child-process-only. Master trace runs use FLUTTER_ENGINE_SWITCHES=2, switch 1=enable-impeller=true/false, switch 2=trace-skia. Raw reports have failure=null, droppedFrameCount=0, explicit first/warm/closing sample windows and actual viewport/DPR. No per-frame console logging during transitions. VM-service auth URLs are omitted.
Flutter Doctor output
Full redacted doctor-stable.txt and doctor-master.txt are in the attached ZIP. Selected identity/toolchain output:
Master is a separate diagnostic SDK invoked by absolute path; default PATH intentionally remains on stable. For doctor only, FLUTTER_GIT_URL was scoped to the local official SDK clone to avoid fetching all historical tags after retrieving one official version tag. Doctor reports the intentional PATH/local-mirror warnings. This did not change the source revision, engine artifacts, native build or renderer selection.