Repository navigation
[Windows][Impeller] ANGLE pixel-shader compilation crashes in d3dcompiler_47.dll after FragmentProgram loads #190809
Description
Summary
On Windows in a debug build, a battle-map route loads two Flutter runtime fragment programs and then
terminates while ANGLE is compiling a pixel shader through D3DCompile. Flutter reports the
Impeller OpenGLESSDF backend in both failing runs. The two runs produced the same 0xc0000005 read
from 0xffffffffffffffff at d3dcompiler_47.dll+0x77ebc; the stack then returns through ANGLE frames
in flutter_windows.dll.
In the reported control launch, the same executable continued past the corresponding route
initialization after Impeller was disabled. This makes the renderer path a strong candidate
discriminator, subject to the uncaptured launch-command gap below, but the retained control does not
prove that either custom runtime effect was drawn: its later content-bearing map explicitly logged
that both custom shader paths were skipped. The evidence therefore does not identify whether the
faulting ANGLE program came from an application runtime effect, another engine shader, ANGLE's
generated/input data, or d3dcompiler_47.dll itself.
[NEEDS VERIFICATION: exact draw boundary and shader provenance] The person reproducing the crash
observed the failure when the first shader-bearing scene was expected to draw. The retained logs prove
that both FragmentProgram.fromAsset calls completed before process termination, and the application
source shows the custom paths that create a FragmentShader and supply it to Canvas.drawRect.
There is not yet a log marker immediately before either draw, nor a capture tying the faulting ANGLE
program to one of those runtime effects.
Environment
| Item | Value |
|---|---|
| Flutter | 3.47.0-0.1.pre, beta |
| Framework | bd1e75d918605c91b411e8789fb911e6c9a84534 |
| Engine | bbd15867c003dc66e678cb3c218649fa8bf914f2 |
| Dart | 3.13.0-282.1.beta |
| Build | Windows x64 debug |
| Impeller backend in failing runs | OpenGLESSDF |
| Runtime-effect packaging | Path dependency with three entries under flutter: shaders: |
| Exact Windows build and GPU/driver for these captures | [NEEDS VERIFICATION] |
| Profile/release behavior | [NEEDS VERIFICATION: not tested] |
The version values come from the pinned SDK's flutter.version.json and engine.stamp. The
flutter_windows.dll copied into this build is byte-identical to that SDK's DLL (SHA-256
7902667F7BE09E606AEC1A8679AD53EC02B1E25CA580F525C114FEE8AD697635); the matching engine PDB retained
in our generated Windows ephemeral directory was used for the symbolization below.
Reproduction shape
A standalone minimal application is not available yet. The reproducible shape in the larger app is:
- In a path package, declare these SkSL runtime effects under
flutter: shaders::lib/src/shaders/parallax.fraglib/src/shaders/parallax_stacked.fraglib/src/shaders/lighting.frag
- Load the programs using package asset keys and
FragmentProgram.fromAsset(...). - Create a
FragmentShader, bind its images/uniforms, put it on aPaint, and draw a rectangle in
a layered 2D map scene. - Build and run for Windows in debug mode with Impeller active. The console prints
Using the Impeller rendering backend (OpenGLESSDF). - Open the route. In both captures the two program-load messages are emitted, route activity
continues, and the process then terminates in native shader compilation. The precise application
draw immediately preceding the crash is not logged.
In our application checkout, the package declarations are at
third_party/ue_to_table_runtime/pubspec.yaml:109-113; its loaders are at
third_party/ue_to_table_runtime/lib/src/shaders/shader_configurator.dart:195-218, and the draw paths are at
lib/features/vtt/presentation/game/map_layer_component.dart:1774-1801 and :2062-2098.
In the currently retained Windows debug asset bundle, the compiled shader blobs are 9,632 bytes (parallax), 11,368
bytes (parallax_stacked), and 23,096 bytes (lighting). We can provide all three source shaders
privately or attach them to the issue; none contains application credentials or data.
The two failing captures explicitly log successful loads of the parallax and lighting programs.
The stacked-alpha program is declared in the same package but was not loaded in these particular
runs, so this report does not claim that it is required to trigger the crash.
Expected result
The runtime effects render, or an unsupported/invalid effect fails with a Flutter/Impeller shader
error that the application can log. A shader should not terminate the process inside the native
Direct3D compiler.
Actual result
Both Impeller runs reported the backend and then the same first-chance crash:
The AOA NATIVE CRASH text is the label emitted by our application's local first-chance exception
logger; the addresses below are the captured native frames.
======== AOA NATIVE CRASH (first-chance) ========
code : 0xc0000005
faulting addr : ... (d3dcompiler_47.dll+0x77ebc)
operation : READ at 0xffffffffffffffff
...
d3dcompiler_47.dll+0x77ebc
...
flutter_windows.dll+0xefa13d
flutter_windows.dll+0xeb70d0
flutter_windows.dll+0xf084a2
flutter_windows.dll+0xefeac8
flutter_windows.dll+0x10f9e0a
Evidence locations in the retained artifacts:
- run 1:
drive_stderr.log:2,28-59; shader loads:drive_stdout.log:553-559; - run 2:
drive2_stderr.log:2,28-59; shader loads:drive2_stdout.log:535-541.
The address, operation, compiler offsets, and Flutter offsets match across 2/2 runs. The later
unhandled blocks in each file are the same exception propagating, not additional independent
failures.
Crash localization / root-cause status
The matching engine PDB resolves the Flutter frames as:
flutter_windows.dll+0xefa13d
rx::HLSLCompiler::compileToBinary(...) at HLSLCompiler.cpp:236
flutter_windows.dll+0xeb70d0
rx::Renderer11::compileToExecutable(...) at Renderer11.cpp:3195
flutter_windows.dll+0xf084a2
rx::ProgramExecutableD3D::getPixelExecutableForCachedOutputLayout(...)
at ProgramExecutableD3D.cpp:1477
flutter_windows.dll+0xefeac8
rx::ProgramD3D::GetPixelExecutableTask::operator()() at ProgramD3D.cpp:367
At this engine revision, Flutter pins ANGLE commit
84027aca9b71c9ba335bd000dad1107b8810a511.
The symbolized top Flutter frame is the call that passes HLSL to
mD3DCompileFunc.
The frames below it generate/compile a fragment (pixel) executable in
ProgramExecutableD3D.cpp,
Renderer11.cpp,
and an ANGLE worker task in
ProgramD3D.cpp.
This localizes the failure to ANGLE compiling a fragment/pixel executable on the path used by the
Impeller OpenGLESSDF backend. It does not prove that the compiled program came from either
offered runtime-effect source, that either source is invalid, that ANGLE generated invalid HLSL, or
that a particular argument/lifetime is corrupt. No compiler diagnostic is returned because the
access violation occurs inside d3dcompiler_47.dll.
Backend A/B
No build occurred between the build that preceded failing runs 1 and 2 and the control run. During
manual reproduction, the same debug executable was launched with:
$env:FLUTTER_ENGINE_SWITCHES = '1'
$env:FLUTTER_ENGINE_SWITCH_1 = 'enable-impeller=false'That run loaded both programs twice, displayed the blank-grid battle-map route, and continued through
later scene activity without terminating at the corresponding point (drive3_stdout.log:518-570;
drive3_stderr.log:1-72 contains no crash block). A screenshot retained as shot_r3_bmap.png shows
that blank-grid route displayed. After the content-bearing map hydrated, however, the same log says
parallax shader skipped and lighting shader skipped (drive3_stdout.log:569-584). This control
discriminates the renderer path, but it does not establish that the custom effects render correctly
with Impeller disabled.
[NEEDS VERIFICATION: retained launch-command capture] The environment variables were not echoed
into drive3_stdout.log/drive3_stderr.log. The absent Impeller banner plus the sustained route and
process activity is consistent with the recorded invocation, but the exact command should be captured in a
future automated A/B harness.
Suggested fix / investigation
- Attempt to reproduce with the offered shader sources in a small
FragmentProgram+
Canvas.drawRecttest. - Immediately before ANGLE's
mD3DCompileFunccall, capture the generated HLSL, profile, macros,
compile flags, input lengths, and originating GL program/runtime effect for the failing pixel
executable. - Audit the asynchronous
GetPixelExecutableTaskinputs and output pointers for lifetime/corruption,
then run the captured HLSL directly through the samed3dcompiler_47.dllto separate an ANGLE/
Impeller lifetime problem from a compiler-input trigger. - If one of the effects reproduces the fault, add the reduced effect as a Windows Impeller regression
test. If the fault is a compiler bug, reject/rewrite the triggering HLSL or select a safe compiler
configuration rather than allowing a process-level access violation.
Workaround
Disable Impeller for the Windows process with the two engine-switch environment variables above.
The same executable then remained alive and displayed the captured battle-map route. This is a
process-wide renderer fallback, not a narrow runtime-effect workaround; the retained control does not
prove custom-effect output under the fallback renderer.
Related
This is the second Windows/Impeller fatal failure tracked by this application. The earlier report,
flutter/flutter#190774, concerns snapshotting an
external GPU texture. The reports share the platform/backend context; no causal dependency between
them is claimed.
Remaining verification gaps
- [NEEDS VERIFICATION] Standalone minimal reproduction, precise pre-draw log marker, and proof
that the faulting ANGLE program originates in one of the offered runtime effects. - [NEEDS VERIFICATION] Exact Windows build and GPU/driver for these two captures.
- [NEEDS VERIFICATION] Profile/release behavior and current Flutter master/newest beta.
- [NEEDS VERIFICATION] Saved launch-command output for the non-Impeller control.
Activity
puneetkukreja98 commentedon Aug 10, 2026
@NH-Mason Thanks for reporting the issue. Could you please provide a minimal reproducible example (MRE) or a sample GitHub repository so we can reproduce it on our end?
Without reproducing it or having a minimal reproducible example (MRE) provided, I cannot forward this to the team.
NH-Mason commentedon Aug 11, 2026
Following up on my own report with a standalone reproduction, plus controls and
newer-engine results.
Repro: https://github.com/NH-Mason/flutter-190809-repro
flutter pub get flutter run -d windowsThat's the whole thing — no environment variables, no scripts. The app dies
within a few seconds and
flutter runprintsLost connection to device.If you want the faulting stack printed to stderr rather than a silent exit, set
$env:FLUTTER_REPRO_CRASH_TRACE = '1'first; that enables a small vectoredexception handler in the runner which is off by default and is not part of the
bug. The repo also has a
run_repro.ps1that runs the control matrix below andretains logs, but the crash needs none of it.
Environment
3.47.0-0.1.pre(beta)bd1e75d918605c91b411e8789fb911e6c9a84534bbd15867c003dc66e678cb3c218649fa8bf914f2flutter_windows.dllSHA-2567902667F7BE09E606AEC1A8679AD53EC02B1E25CA580F525C114FEE8AD69763532.0.15.9595)Using the Impeller rendering backend (OpenGLESSDF)Module offsets below are only meaningful against this exact engine revision.
What the repro contains
A default Flutter app plus two
.fragfiles and a singlemain.dart. Nothird-party dependencies (only
flutter,flutter_test,flutter_lints) andno image or media assets — the two shaders are the only declared assets, and the
sampler inputs are synthetic in-memory 64×64 solid-colour images.
SHADER_MODEselects which programs get loaded and whether either is used to paint.
Expected vs actual
Expected: both programs load, the app paints for 30 seconds, prints
clean timeout reached; exiting normallyand exits 0.Actual: shortly after the programs are loaded, the process takes an access
violation inside
d3dcompiler_47.dlland dies with0xC0000005. Normal exit isnever reached.
Two findings that narrow this down
1. Neither program has to be used for painting. In
-Mode load_onlythe appnever calls
FragmentProgram.fragmentShader()and never issues a canvas drawwith either loaded program — the process still dies with the same signature.
Loading is sufficient. (Ordinary Flutter UI rendering still happens, of course;
this rules out use of the runtime effect, not rendering in general.) The Dart
future from
FragmentProgram.fromAssetcompletes normally first, and the faultlands afterwards, outside the calling Dart stack.
2. It's specific to one of the two shaders, not a blanket
FragmentProgramfailure.
-Mode lightingloads only the larger shader and crashes;-Mode parallaxloads only the smaller one, configures it, paints with it, andexits cleanly. Since
lightingskips the parallax load entirely, this isn't aload-ordering or two-program effect.
I have not isolated which shader property is responsible. The two differ
simultaneously in uniform count (~161 vs 9 float components), sampler count
(4 vs 2), array declarations, control flow, generated HLSL, and compiled blob
size (23,096 vs 9,632 bytes). I didn't run a delta-reduction to find the
threshold.
Matrix
Each run used a 30-second configured timeout; the crashing runs end earlier.
-Modeboth(clean build) ×20xC0000005lighting0xC0000005load_only(never used to paint)0xC0000005parallax0both0The Impeller-off run is a genuine control: its log contains zero
Using the Impeller rendering backendlines, still loads both programs, stillissues its draw calls, and exits 0.
Still reproduces on the current beta
I re-ran the repro unchanged against two newer betas (
-AllowAnyEngineskips therevision pin). Both crash the same way:
3.47.0-0.1.prebbd15867c003…d3dcompiler_47.dll+0x77ebc3.47.0-0.3.preeffb186f3172…d3dcompiler_47.dll+0x77ebc3.47.0-0.4.pre(current beta)f88005a259ba…d3dcompiler_47.dll+0x77ebcAll three fault at the identical address with
READ at 0xffffffffffffffff, andthe whole
d3dcompiler_47frame chain is byte-identical(
+0x77bde,+0x768e9,+0xd19b1, …). That's expected:d3dcompiler_47.dllis a system library, not shipped with Flutter, so only the ANGLE frames inside
flutter_windows.dllshift between engines.Retained logs:
logs\cross_beta_0.3.log,logs\cross_beta_0.4.log.Stack
Symbolized under
cdb(d3dcompiler_47symbols from the Microsoft publicsymbol server):
Fault address
d3dcompiler_47.dll+0x77ebc,READ at 0xffffffffffffffff.The top public symbol is
AssignCBSlots_Misc, i.e. HLSL constant-buffer slotassignment. That's suggestive given the uniform-count difference between the two
shaders, but I want to be clear it's a candidate explanation, not something I've
isolated from sampler count, generated HLSL structure, or blob size.
Caveats on the stack:
.ecxrreturnsUnable to get exception context, HRESULT 0x8000FFFF, so the frames come fromthe break-in context at the first-chance AV. There are no public PDBs for
flutter_windows.dll, so the debugger resolves those frames to the nearestexported symbol plus a very large offset — I've quoted
module+offsetonly,since the symbol names there are meaningless.
I have a minidump but haven't attached it, since it captures process environment
data. Happy to produce a scrubbed one, or run additional configurations on this
hardware, if that would help.
puneetkukreja98 commentedon Aug 12, 2026
@NH-Mason Thanks for the response, I was able to reproduce it on latest master.
Findings:
Impeller-enabled-console-logs:
Impeller-enabled-output-ss:
Impeller-disabled-console-logs:
Impeller-disabled-output-ss:
puneetkukreja98 commentedon Aug 12, 2026
Flutter doctor -v:
krll-kov commentedon Aug 13, 2026
I also have something similar but on stable channel. Compilation (_loadShader) itself is good, but usage in render from getShader crashes the app
WinDbg log
Stack
Threads
verbose launch attempt:
walley892 commentedon Aug 17, 2026
@puneetkukreja98, thanks for the reproduction! You've found a cool bug :)
I was able to reproduce locally. After some experimenting, it looks like your shader has a couple of complex interactions that cause the directx compiler to fail when given the ANGLE generated HLSL source. Namely, the combination of using samplers, early returns, and dynamic looping.
This will require some more investigation, but I'm not sure if this is something we can fix at the flutter engine level.
In the meantime, I've rewritten your lighting.frag program to eliminate the early return, which fixes the crash for me locally:
I've also created a minimal reproduction:
Let me know if the rewritten lighting.frag works locally for you. I'll continue to investigate the root cause
krll-kov commentedon Aug 18, 2026
Thank you, i also replaced early return with step 0 + clamp and crash disappeared
puneetkukreja98 commentedon Aug 18, 2026
@walley892 I replaced lighting.frag with your updated code, and the issue is no longer reproducing.
Findings:
Console logs:
Screen-shot:
Flutter doctor -v:
Add a compiler warning for fragment shaders containing both texture s…
walley892 commentedon Sep 29, 2026
Added a compiler warning with a workaround - closing