Group F: compressed-format tables, BMP/ICO suffixes, sprite MRT and ZLIB KTX2 (LOW-N36, LOW-N37, LOW-N38, ME-83) - #633
Conversation
…bles Both backends already implement the full LDR ASTC set, but the engine exposed four of the fourteen block sizes - leaving out 8x6 and 10x8, the two steps a mobile VRAM budget is usually met with. The signed BC variants were missing for the same reason: same blocks, different interpretation, and tangent-space normal maps need the [-1, 1] range rather than a shader-side "v * 2 - 1". Adds the ten missing ASTC sizes plus bc4-r-snorm, bc5-rg-snorm and bc6h-rgb-float to the format enum, the block-geometry table, the preference order, both backend format tables and the KTX2 vkFormat mapping. The sRGB twins stay out: the code would be trivial, the decision is not - they belong to an engine-wide color space contract.
The load path already served both: decodeImageBlob hands the blob to createImageBitmap, which decodes BMP and ICO in every browser, and the MIME sniffer already carried their magic bytes. Only the suffix list was missing, so a bare "icon.ico" path resolved to no asset type at all. An .ico container may hold several resolutions and which one the browser picks is unspecified. That is documented as belonging to the runtime rather than resolved by a bespoke ICO parser: the format is practically absent as a game asset, and parsing it ourselves would cost more than it settles.
A G-buffer could only be authored from meshes, while a 2D scene is sprites - so exactly the case multiple render targets exist for (deferred lighting, normal mapping, selection ids) was unreachable in the form the scene already has. It is the same seam and mechanically the same change as on the mesh side: the custom sprite pipeline built a fixed single-entry target list and keyed on one format, and now keys on the whole format list from renderTargetFormats and declares one target per attachment. WebGL2 needs nothing beyond letting the refusal guard through - it has no pipeline object. Deliberately not extended to the built-in shaders: sprite, text, nine-slice, repeating and video all declare exactly one output, and minting pipeline variants that never write slot 1 is the unused API surface the multi-attachment work package set out to avoid. A sprite WITHOUT a material is still refused.
Scheme 3 stores every mip level as a plain zlib stream, which DecompressionStream inflates natively in every browser we target - no decoder, no dependency, no bundle cost. Refusing it alongside BasisLZ and Zstandard, which genuinely need a WASM transcoder, cost download bytes for nothing. The inflation happens ahead of the parser rather than inside it: DecompressionStream is a stream and parseKtx2 is synchronous, and keeping it that way keeps the parser testable without I/O. inflateKtx2Levels rewrites the container into an equivalent scheme-0 one - level index patched, everything the header points at by absolute offset copied verbatim - and hands back the input untouched when there is nothing to inflate. A level whose inflated size is not the one the container declares is refused rather than uploaded short.
Bundle ReportChanges will increase total bundle size by 50.18kB (0.11%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: exo-full-iife-Exo-iifeAssets Changed:
Files in
view changes for bundle: exo-full-iife-min-Exo-iifeAssets Changed:
Files in
view changes for bundle: site-server-esmAssets Changed:
Files in
Files in
view changes for bundle: exo-esm-esmAssets Changed:
Files in
view changes for bundle: exo-iife-min-Exo-iifeAssets Changed:
Files in
view changes for bundle: exo-iife-Exo-iifeAssets Changed:
Files in
view changes for bundle: exo-esm-modules-esmAssets Changed:
Files in
Files in
Files in
Files in
Files in
Files in
Files in
Files in
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Four follow-ups from the Group D review, all in the compressed-texture and render-target seams they share. One commit per point.
Complete the ASTC and signed BC format tables (LOW-N38)
Both backends implement the full LDR ASTC set; the engine exposed 4 of 14 block sizes, missing exactly the
8x6and10x8steps a mobile VRAM budget is met with. Adds the ten missing sizes plusbc4-r-snorm,bc5-rg-snormandbc6h-rgb-floatto the enum, the block table, the preference order, both backend tables and the KTX2vkFormatmap. The-srgbtwins stay out: trivial code, undecided colour-space contract.Claim
.bmpand.icofor the texture type (LOW-N37)The load path and the MIME sniffer already handled both; only the suffix list was missing, so a bare
icon.icoresolved to no asset type. Which resolution the browser picks out of a multi-resolution ICO is documented as belonging to the runtime rather than settled by a bespoke parser.Let a SpriteMaterial write every colour attachment (ME-83)
A G-buffer could only be authored from meshes while a 2D scene is sprites. The custom sprite pipeline now keys on the whole format list and declares one target per attachment, exactly like the mesh path. Not extended to the built-in shaders, and a sprite without a material is still refused.
Read ZLIB-supercompressed KTX2 (LOW-N36)
Scheme 3 is a plain zlib stream per level, which
DecompressionStreaminflates natively - no decoder, no bundle cost. Inflation runs ahead of the parser soparseKtx2stays synchronous and testable without I/O; BasisLZ and Zstandard stay refused.Validation
pnpm lanes --runselection green via the pre-push hook (typecheck, lint, sync,pnpm test,test:alloc, WebGL2/WebGPU/build/assets browser lanes,gates site). New cells verified red before the change for ME-83 and the format tables. API docs regenerated; guide sections for render targets and device variants corrected.