Use case
Editing a shader source compiled into a Flutter GPU .shaderbundle should hot reload in a running app, the same way FragmentProgram (flutter.shaders:) shaders already do. Today a changed bundle is treated as a regular asset: its bytes sync to the device, but nothing tells the engine to reload the compiled ShaderLibrary, so the app keeps the old shaders until a restart.
Proposal
The engine half (#186344, PR #186793) reloads a shader library in place when the ext.ui.gpu.reinitializeShaderLibrary service extension is called with the bundle's asset path, and no-ops if nothing is registered there. This issue is the remaining flutter_tools wiring: after a DevFS sync, dispatch that extension for changed shader bundle assets.
The design is producer-agnostic. flutter_tools does not classify bundles or know the bundle format; it dispatches by asset path and lets the engine self-filter. So there is no new AssetKind and no flutter.gpu_shader_bundles: pubspec block, and it works however the bundle was produced (a build hook output under flutter.assets:, a future DataAsset, or an asset transformer).
- Add a
vmservice.dart method, mirroring flutterEvictShader, that invokes ext.ui.gpu.reinitializeShaderLibrary with {assetKey: <path>}.
- In
evictDirtyAssets (run_hot.dart), after the DevFS sync, dispatch it for each changed asset path ending in .shaderbundle. Suffix-gating is only a noise filter; correctness comes from the engine no-op on a miss.
- Tolerate the extension being unregistered (it is registered lazily on the first
ShaderLibrary.fromAsset in debug mode): swallow a method-not-found error rather than fail the reload.
The bundle bytes already sync to the device as a normal asset, so no new DevFS handling is needed. Depends on the engine half (#186344); the asset-transformer authoring path additionally needs #187051.
Use case
Editing a shader source compiled into a Flutter GPU
.shaderbundleshould hot reload in a running app, the same way FragmentProgram (flutter.shaders:) shaders already do. Today a changed bundle is treated as a regular asset: its bytes sync to the device, but nothing tells the engine to reload the compiledShaderLibrary, so the app keeps the old shaders until a restart.Proposal
The engine half (#186344, PR #186793) reloads a shader library in place when the
ext.ui.gpu.reinitializeShaderLibraryservice extension is called with the bundle's asset path, and no-ops if nothing is registered there. This issue is the remainingflutter_toolswiring: after a DevFS sync, dispatch that extension for changed shader bundle assets.The design is producer-agnostic.
flutter_toolsdoes not classify bundles or know the bundle format; it dispatches by asset path and lets the engine self-filter. So there is no newAssetKindand noflutter.gpu_shader_bundles:pubspec block, and it works however the bundle was produced (a build hook output underflutter.assets:, a futureDataAsset, or an asset transformer).vmservice.dartmethod, mirroringflutterEvictShader, that invokesext.ui.gpu.reinitializeShaderLibrarywith{assetKey: <path>}.evictDirtyAssets(run_hot.dart), after the DevFS sync, dispatch it for each changed asset path ending in.shaderbundle. Suffix-gating is only a noise filter; correctness comes from the engine no-op on a miss.ShaderLibrary.fromAssetin debug mode): swallow a method-not-found error rather than fail the reload.The bundle bytes already sync to the device as a normal asset, so no new DevFS handling is needed. Depends on the engine half (#186344); the asset-transformer authoring path additionally needs #187051.