flutter3d_impeller 0.6.0
flutter3d_impeller: ^0.6.0 copied to clipboard
The flutter_gpu backend for flutter3d: one implementation of flutter3d_hardware, and the only place in the stack that names a graphics API.
0.6.0 #
- A floor, and no code. The device, the encoder and the shader build are
byte for byte 0.5.2's. What moved is the one line that names
flutter3d_hardware, now^0.6.0: the bundle format and the section names this backend reads live in that package, and a floor is where a resolver is told which version of them this one was built against. - The bundle it refuses and the bundle it accepts are unchanged; a
flutter3d.shaderbundlebuilt for 0.5.2 still loads.
0.5.2 #
- No Dart moved. This package ships
assets/shaders/flutter3d.shaderbundle, built by impellerc fromflutter3d_shadersGLSL, and 0.5.2 of those shaders addedlib/morph.glsland the morph block and sampler to four vertex stages — so this package's contents changed even though nothing here was edited. - One thing worth recording for whoever meets it next: impellerc aborts on
texelFetchin a vertex stage, with a SIGABRT and no diagnostic. Reading texel centres withtexture()is the way past it, and it is why the shader is handed the texel size in a uniform instead of askingtextureSize.
0.5.1 #
- The shader bundle is rebuilt, and this release exists for that alone.
No API change and no line of Dart moved. This package ships
assets/shaders/flutter3d.shaderbundle, which isimpellercoutput compiled fromflutter3d_shaders' GLSL — so a change to that GLSL is a change to this package's contents even when nothing here is edited.flutter3d_shaders0.5.1 addedforwardto theFogInfoblock and changed what the surface buffer's alpha means; an application onflutter3d0.5.1 with this package at 0.5.0 would have been binding a uniform member its compiled shaders did not declare, and reconstructing screen-space effects from a depth in the wrong units. - The gap is the interesting part, and it is a second version of a mistake
this package has already made once. 0.4.0 shipped without the bundle
because the file is gitignored; 0.5.0 shipped with a bundle that no longer
matched its sources. Both are the same failure — a compiled artefact whose
freshness nothing checked at publish time — and
tool/structure.dart's the compiled shader bundle is not older than its sources rule only holds it inside this repository, where the file exists. What it cannot see is the copy already on pub.flutter-io.cn.
0.4.5 #
- A uniform block missing a member the caller named now throws, and used to
return. The block case is unchanged and still answers false — a compiler
drops a whole block nothing reads, which is ordinary. What changed is the
member case: the offset came back null, this backend skipped the write, and
the member's bytes stayed zero. Zero is a plausible value for nearly
everything that goes through a uniform block, so the picture came out wrong
with nothing logged, while the same bundle raised a named exception in a
browser — the web backend has refused this all along.
ARCHITECTURE.md§7.1 said the refusal was the rule; only the HAL's own doc comment said otherwise, on the grounds that "the unlit model legitimately has nolight_direction", which it has:FragInfois declared once and included whole. Checked on a device: all 39 goldens draw and the conformance suite passes 23. - Anisotropic filtering, through the sampler it always built.
SamplerOptions.anisotropyis forwarded as flutter_gpu'smaxAnisotropyandmaxAnisotropyon the device isgpuContext.maxSamplerAnisotropy— sixteen on every Metal and Vulkan device this has met. Nothing clamps here, because flutter_gpu clamps inside its own bind and says so; the sampler cache keys on the field, so eight taps and one are two objects.anisotropic-floorjoins the golden set. - A bundle loaded from bytes, and refused when its SDK is not this one.
GpuRenderBackend.loadShadersreparsesimpellercoutput throughShaderLibrary.fromBytes, andGpuLoadedShaderLibrary.refreshthroughreinitializeFromBytes, so a handle already handed out wraps the stage that now carries the new code. The header's SDK token is held torunningSdk— the first token ofPlatform.version— before the section is looked at: the bundle format is tied to the Flutter version, and a stage compiled for another one draws something else rather than failing to parse. A mismatch, a missingimpellersection and bytes flutter_gpu cannot parse are allShaderBundleRefusednaming the bundle.impellerSectionOfis the pure half, tested without a device. tool/conformance.shalso wants the example's own loadable bundle built, since the harness is the example and its pubspec now declares the asset.- A refresh is held to the header's stage list before flutter_gpu sees a
byte. A bundle that no longer names a stage already handed out is
refused, naming it, rather than reparsed over a live handle — the contract
LoadedShaderLibrary.refreshstates. AndGpuLoadedShaderLibrarykeeps the SDK token its load was given, so a library loaded against one token is never refreshed against another. - The editor's hot-reload loop — the packed engine bundle loaded over the
engine's own asset, a stage edited, rebuilt and repacked — was exercised
on this backend: the reloaded
Pbrtook the edit on the next frame, which is whatreinitializeFromBytesmarking every stage dirty buys even when the entry points collide with the asset bundle's. readback, through a staging texture rather than a buffer. flutter_gpu 3.47 hascopyTextureToBufferand no way for Dart to read theDeviceBufferit fills, so the copy goes texture to texture into a pooled staging texture — a command on a command buffer submitted in order, which is what makes the answer the frame before — and the bytes come off it throughasImage().toByteData()insubmit's completion callback, once the queue says the copy ran. Nothing blocks; the pool grows to however many readbacks are in flight — one for the exposure meter, which waits for its answer before it asks again, and one for each pick asked in the same breath. Checked on the GPU by the two new conformance checks and by theauto-exposuregolden, whose metered frame reproduced to the pixel.- A refused copy gives its staging texture back. flutter_gpu throws rather
than returns false when
copyTextureToTextureorsubmitis refused outright, and the staging texture taken for that readback was never returned to the pool — GPU memory nothing can free, since flutter_gpu has no dispose, withdebugReadbackStagingCountclimbing by one per refusal as the only sign. Every path out ofreadnow returns it. - The bundle gains
LuminanceandObjectId;ObjectIdsamples the material's texture against its cutoff, so a pick through a masked material's hole answers with what is behind it. GpuImageSurfacewas measured, and not taken. flutter_gpu 3.47's presentable surface does the job the renderer's ring of finished frames does by hand — keep a texture out of rotation while Flutter still reads it.tool/surface_probe.shruns the probe: the same clear-only pass through that ring and through a surface, 240 frames each at 1280×800 with Flutter drawing every one, and prints what each costs. Same UI-thread cost and the same interval between frames, no copy on either path; then the surface holding five textures at four megabytes of short-lived allocation per frame and forty-seven with none at all, against the ring's two. Only those two rates were run, so the count a real frame would pay is a range rather than a number. The forty-seven is what shows the mechanism — a texture counts as reusable only once the collector has freed the native wrappers a frame makes — and the ring's two is the count of the variant that makes the surface's own promise, keeping the presented frame back a frame longer. The script is the only part that lives here; the probe itself is in the engine's example beside the entry point that runs it, since it reaches flutter_gpu directly and is no part of this backend's API. The numbers and the verdict are ARCHITECTURE §15.- The stencil passes through.
setStencilbecomessetStencilConfigfor both faces or one call per face,setStencilReferenceits own, andDepthTarget's stencil load, store and clear reach theDepthStencilAttachment.supportsStencilanswers from whether the context names a depth-stencil format at all.stencil-xrayjoins the golden set, and the conformance suite marks a stencil and reads it back through this backend. - A pass renders into a cube face and a mip level.
ColorTarget.facebecomes the attachment's slice andColorTarget.mipLevelits mip index, which flutter_gpu validates against the texture and refuses out loud;createCubeRenderTargetallocates a device-private cube with render-target usage and a chain, andsupportsRenderToMiprepeatsdoesSupportFramebufferRenderMipmap— true on Metal and Vulkan, false on the OpenGL ES path. The bundle gainsProbePrefilter;probe-carjoins the golden set. - A blend state naming the blend constant is refused rather than drawn.
flutter_gpu's
RenderPasshas no blend-constant setter, so this backend answers false tosupportsBlendColor;setBlendColorthrows, and so doessetBlendhanded a state that reads the constant. It used to hand those four factors on and let Impeller multiply by its own transparent black, which lost the term with no error anywhere.
0.4.4 #
- The bundle gains
MeshLightmappedVertexand every lit stage binds a lightmap;lightmapped-roomjoins the golden set. - Block-compressed textures upload, and the device is asked first.
createTextureFromPixelsstops requesting render-target usage for a compressed format, which flutter_gpu refuses before the allocation, andsupportsTextureFormatrepeats flutter_gpu's own per-family answer — BC on a desktop GPU, ETC2 and ASTC on a mobile one, all three on Apple silicon. The conformance suite now draws a BC1 and an ETC2 block through this backend and reads the colour back, which had never been done.
0.4.3 #
- The pubspec declares its platforms instead of leaving them to pub.flutter-io.cn's
detector: every native platform — Android, iOS, macOS, Windows, Linux —
and deliberately not the web, which is what
flutter3d_webglexists for.
0.4.2 #
- The package actually ships its shaders this time. 0.4.1 claimed this
fix and repeated the failure: its
.pubignorereplaced only the package directory's gitignore, while*.shaderbundleis excluded by the repository ROOT's — which still applied from above. The explicit!*.shaderbundlenegation is the whole difference, and this release was checked by reading the dry-run's file list before uploading, which is the step 0.4.1 skipped.
0.4.1 #
- The package ships its shaders. 0.4.0 declared
assets/shaders/flutter3d.shaderbundleand did not contain it: the bundle is generated and gitignored, and pub packages by the gitignore — so every hosted consumer failed at build with "No file or variants found for asset". A.pubignorenow decides what the archive carries, and the bundle rides along, built fresh at publish. Found the first time anything resolved this backend from pub.flutter-io.cn alone.
0.4.0 #
presentowns its image. It returnsGpuFrameImage, a widget that creates theui.Imagein its state, disposes the previous one when the frame changes and the last one indispose— which ends the one undisposed image per presented frame.readPixelsdisposes its image too.- A workaround for flutter_gpu's
HostBuffer, whose overflow branch appends a block per boundary crossing and never reuses the tail, so a frame writing over a megabyte of transients parked a megabyte for ever.BlockCursorcounts crossings andbeginFramerecreates a slot's buffer at 32, at the reset point whose own comment is the safety argument; the clause names the upstream file and dies with the SDK upgrade. - Texture creation validates pixel sizes before allocating rather than after.
0.3.0 #
tool/conformance.shruns the conformance suite against a live GPU and returns an exit code. Until it existed, the only thing checking this backend was somebody remembering to look at a list.
0.2.0 #
- A host buffer ring sized by the frames in flight, because submission is asynchronous and resetting a bump allocator the GPU is still reading flickers rather than crashes.
- The build script prints the compiled binding table, so the engine's hand-written permutation metadata cannot drift from what the compiler kept.
0.1.0 #
-
flutter3d_hardwareoverflutter_gpu: the backend a desktop build draws through, and the only place in the stack that names a graphics API. -
A shader bundle built from
flutter3d_shadersbytool/build_shaders.sh. -
Anisotropic filtering, through the sampler it always built.
SamplerOptions.anisotropyis forwarded as flutter_gpu'smaxAnisotropyandmaxAnisotropyon the device isgpuContext.maxSamplerAnisotropy— sixteen on every Metal and Vulkan device this has met. Nothing clamps here, because flutter_gpu clamps inside its own bind and says so; the sampler cache keys on the field, so eight taps and one are two objects.anisotropic-floorjoins the golden set. -
A bundle loaded from bytes, and refused when its SDK is not this one.
GpuRenderBackend.loadShadersreparsesimpellercoutput throughShaderLibrary.fromBytes, andGpuLoadedShaderLibrary.refreshthroughreinitializeFromBytes, so a handle already handed out wraps the stage that now carries the new code. The header's SDK token is held torunningSdk— the first token ofPlatform.version— before the section is looked at: the bundle format is tied to the Flutter version, and a stage compiled for another one draws something else rather than failing to parse. A mismatch, a missingimpellersection and bytes flutter_gpu cannot parse are allShaderBundleRefusednaming the bundle.impellerSectionOfis the pure half, tested without a device. -
tool/conformance.shalso wants the example's own loadable bundle built, since the harness is the example and its pubspec now declares the asset. -
A refresh is held to the header's stage list before flutter_gpu sees a byte. A bundle that no longer names a stage already handed out is refused, naming it, rather than reparsed over a live handle — the contract
LoadedShaderLibrary.refreshstates. AndGpuLoadedShaderLibrarykeeps the SDK token its load was given, so a library loaded against one token is never refreshed against another. -
The editor's hot-reload loop — the packed engine bundle loaded over the engine's own asset, a stage edited, rebuilt and repacked — was exercised on this backend: the reloaded
Pbrtook the edit on the next frame, which is whatreinitializeFromBytesmarking every stage dirty buys even when the entry points collide with the asset bundle's. -
readback, through a staging texture rather than a buffer. flutter_gpu 3.47 hascopyTextureToBufferand no way for Dart to read theDeviceBufferit fills, so the copy goes texture to texture into a pooled staging texture — a command on a command buffer submitted in order, which is what makes the answer the frame before — and the bytes come off it throughasImage().toByteData()insubmit's completion callback, once the queue says the copy ran. Nothing blocks; the pool grows to however many readbacks are in flight — one for the exposure meter, which waits for its answer before it asks again, and one for each pick asked in the same breath. Checked on the GPU by the two new conformance checks and by theauto-exposuregolden, whose metered frame reproduced to the pixel. -
A refused copy gives its staging texture back. flutter_gpu throws rather than returns false when
copyTextureToTextureorsubmitis refused outright, and the staging texture taken for that readback was never returned to the pool — GPU memory nothing can free, since flutter_gpu has no dispose, withdebugReadbackStagingCountclimbing by one per refusal as the only sign. Every path out ofreadnow returns it. -
The bundle gains
LuminanceandObjectId;ObjectIdsamples the material's texture against its cutoff, so a pick through a masked material's hole answers with what is behind it. -
GpuImageSurfacewas measured, and not taken. flutter_gpu 3.47's presentable surface does the job the renderer's ring of finished frames does by hand — keep a texture out of rotation while Flutter still reads it.tool/surface_probe.shruns the probe: the same clear-only pass through that ring and through a surface, 240 frames each at 1280×800 with Flutter drawing every one, and prints what each costs. Same UI-thread cost and the same interval between frames, no copy on either path; then the surface holding five textures at four megabytes of short-lived allocation per frame and forty-seven with none at all, against the ring's two. Only those two rates were run, so the count a real frame would pay is a range rather than a number. The forty-seven is what shows the mechanism — a texture counts as reusable only once the collector has freed the native wrappers a frame makes — and the ring's two is the count of the variant that makes the surface's own promise, keeping the presented frame back a frame longer. The script is the only part that lives here; the probe itself is in the engine's example beside the entry point that runs it, since it reaches flutter_gpu directly and is no part of this backend's API. The numbers and the verdict are ARCHITECTURE §15. -
The stencil passes through.
setStencilbecomessetStencilConfigfor both faces or one call per face,setStencilReferenceits own, andDepthTarget's stencil load, store and clear reach theDepthStencilAttachment.supportsStencilanswers from whether the context names a depth-stencil format at all.stencil-xrayjoins the golden set, and the conformance suite marks a stencil and reads it back through this backend. -
A pass renders into a cube face and a mip level.
ColorTarget.facebecomes the attachment's slice andColorTarget.mipLevelits mip index, which flutter_gpu validates against the texture and refuses out loud;createCubeRenderTargetallocates a device-private cube with render-target usage and a chain, andsupportsRenderToMiprepeatsdoesSupportFramebufferRenderMipmap— true on Metal and Vulkan, false on the OpenGL ES path. The bundle gainsProbePrefilter;probe-carjoins the golden set.
0.4.4 #
- The bundle gains
MeshLightmappedVertexand every lit stage binds a lightmap;lightmapped-roomjoins the golden set. - Block-compressed textures upload, and the device is asked first.
createTextureFromPixelsstops requesting render-target usage for a compressed format, which flutter_gpu refuses before the allocation, andsupportsTextureFormatrepeats flutter_gpu's own per-family answer — BC on a desktop GPU, ETC2 and ASTC on a mobile one, all three on Apple silicon. The conformance suite now draws a BC1 and an ETC2 block through this backend and reads the colour back, which had never been done.
0.4.3 #
- The pubspec declares its platforms instead of leaving them to pub.flutter-io.cn's
detector: every native platform — Android, iOS, macOS, Windows, Linux —
and deliberately not the web, which is what
flutter3d_webglexists for.
0.4.2 #
- The package actually ships its shaders this time. 0.4.1 claimed this
fix and repeated the failure: its
.pubignorereplaced only the package directory's gitignore, while*.shaderbundleis excluded by the repository ROOT's — which still applied from above. The explicit!*.shaderbundlenegation is the whole difference, and this release was checked by reading the dry-run's file list before uploading, which is the step 0.4.1 skipped.
0.4.1 #
- The package ships its shaders. 0.4.0 declared
assets/shaders/flutter3d.shaderbundleand did not contain it: the bundle is generated and gitignored, and pub packages by the gitignore — so every hosted consumer failed at build with "No file or variants found for asset". A.pubignorenow decides what the archive carries, and the bundle rides along, built fresh at publish. Found the first time anything resolved this backend from pub.flutter-io.cn alone.
0.4.0 #
presentowns its image. It returnsGpuFrameImage, a widget that creates theui.Imagein its state, disposes the previous one when the frame changes and the last one indispose— which ends the one undisposed image per presented frame.readPixelsdisposes its image too.- A workaround for flutter_gpu's
HostBuffer, whose overflow branch appends a block per boundary crossing and never reuses the tail, so a frame writing over a megabyte of transients parked a megabyte for ever.BlockCursorcounts crossings andbeginFramerecreates a slot's buffer at 32, at the reset point whose own comment is the safety argument; the clause names the upstream file and dies with the SDK upgrade. - Texture creation validates pixel sizes before allocating rather than after.
0.3.0 #
tool/conformance.shruns the conformance suite against a live GPU and returns an exit code. Until it existed, the only thing checking this backend was somebody remembering to look at a list.
0.2.0 #
- A host buffer ring sized by the frames in flight, because submission is asynchronous and resetting a bump allocator the GPU is still reading flickers rather than crashes.
- The build script prints the compiled binding table, so the engine's hand-written permutation metadata cannot drift from what the compiler kept.
0.1.0 #
flutter3d_hardwareoverflutter_gpu: the backend a desktop build draws through, and the only place in the stack that names a graphics API.- A shader bundle built from
flutter3d_shadersbytool/build_shaders.sh.