@woosh/meep-engine 3.14.2 → 3.14.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/editor/prototypeEditorShell.js +6 -0
- package/package.json +1 -1
- package/src/CODEC_LAYOUT_VERIFICATION.md +420 -0
- package/src/core/binary/zstd/ZstdReverseBitReader.d.ts +76 -0
- package/src/core/binary/zstd/ZstdReverseBitReader.d.ts.map +1 -0
- package/src/core/binary/zstd/ZstdReverseBitReader.js +223 -0
- package/src/core/binary/zstd/zstd_decompress.d.ts +31 -0
- package/src/core/binary/zstd/zstd_decompress.d.ts.map +1 -0
- package/src/core/binary/zstd/zstd_decompress.js +628 -0
- package/src/core/binary/zstd/zstd_fse.d.ts +83 -0
- package/src/core/binary/zstd/zstd_fse.d.ts.map +1 -0
- package/src/core/binary/zstd/zstd_fse.js +265 -0
- package/src/core/binary/zstd/zstd_huffman.d.ts +56 -0
- package/src/core/binary/zstd/zstd_huffman.d.ts.map +1 -0
- package/src/core/binary/zstd/zstd_huffman.js +244 -0
- package/src/core/binary/zstd/zstd_sequence_tables.d.ts +62 -0
- package/src/core/binary/zstd/zstd_sequence_tables.d.ts.map +1 -0
- package/src/core/binary/zstd/zstd_sequence_tables.js +98 -0
- package/src/core/color/COLOR_REVIEW_2026_08_28.md +1 -1
- package/src/core/color/PQ/PQ_constants.d.ts +1 -1
- package/src/core/color/PQ/PQ_constants.js +1 -1
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +733 -726
- package/src/engine/asset/GameAssetType.d.ts +1 -0
- package/src/engine/asset/GameAssetType.js +8 -0
- package/src/engine/asset/codec/DecodedImage.d.ts +39 -0
- package/src/engine/asset/codec/DecodedImage.d.ts.map +1 -0
- package/src/engine/asset/codec/DecodedImage.js +26 -0
- package/src/engine/asset/guessAssetType.d.ts.map +1 -1
- package/src/engine/asset/guessAssetType.js +10 -0
- package/src/engine/asset/load_model_scene_bundle.d.ts +1 -1
- package/src/engine/asset/load_model_scene_bundle.d.ts.map +1 -1
- package/src/engine/asset/load_model_scene_bundle.js +6 -2
- package/src/engine/asset/loaders/USDSceneBundleAssetLoader.d.ts +37 -0
- package/src/engine/asset/loaders/USDSceneBundleAssetLoader.d.ts.map +1 -0
- package/src/engine/asset/loaders/USDSceneBundleAssetLoader.js +104 -0
- package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +83 -71
- package/src/engine/asset/loaders/image/ImageDecoderWorker.js +2 -2
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts +8 -9
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts.map +1 -1
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +12 -3
- package/src/engine/asset/loaders/image/avif/encode_image_source.d.ts +70 -0
- package/src/engine/asset/loaders/image/avif/encode_image_source.d.ts.map +1 -0
- package/src/engine/asset/loaders/image/avif/encode_image_source.js +117 -0
- package/src/engine/asset/loaders/image/avif/encoder_worker.d.ts.map +1 -0
- package/src/engine/asset/loaders/image/avif/threaded_image_encoder.d.ts.map +1 -0
- package/src/engine/asset/loaders/image/codec/AvifCodec.d.ts +34 -0
- package/src/engine/asset/loaders/image/codec/AvifCodec.d.ts.map +1 -0
- package/src/engine/asset/loaders/image/codec/AvifCodec.js +85 -0
- package/src/engine/asset/loaders/image/codec/JpegCodec.d.ts +26 -0
- package/src/engine/asset/loaders/image/codec/JpegCodec.d.ts.map +1 -0
- package/src/engine/asset/loaders/image/codec/JpegCodec.js +66 -0
- package/src/engine/asset/loaders/image/codec/NativeImageDecoder.d.ts +4 -16
- package/src/engine/asset/loaders/image/codec/NativeImageDecoder.d.ts.map +1 -1
- package/src/engine/asset/loaders/image/codec/NativeImageDecoder.js +2 -2
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.d.ts +21 -1
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.d.ts.map +1 -1
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +21 -1
- package/src/engine/asset/loaders/image/prototypePNG.d.ts.map +1 -0
- package/src/engine/asset/loaders/image/prototypePNG.js +37 -0
- package/src/engine/asset/preloader/extractAssetListFromManager.d.ts.map +1 -1
- package/src/engine/asset/preloader/extractAssetListFromManager.js +2 -1
- package/src/engine/graphics/ecs/mesh/assetTypeByPath.d.ts.map +1 -1
- package/src/engine/graphics/ecs/mesh/assetTypeByPath.js +6 -0
- package/src/engine/graphics/texture/sampler/avif_to_sampler2d.d.ts +25 -0
- package/src/engine/graphics/texture/sampler/avif_to_sampler2d.d.ts.map +1 -0
- package/src/engine/graphics/texture/sampler/avif_to_sampler2d.js +42 -0
- package/src/engine/graphics/texture/sampler/compare/sampler2d_compare.d.ts.map +1 -0
- package/src/engine/graphics/texture/sampler/compare/sampler2d_compare.js +94 -0
- package/src/engine/graphics/texture/sampler/compare/sampler2d_max_absolute_difference.d.ts +19 -0
- package/src/engine/graphics/texture/sampler/compare/sampler2d_max_absolute_difference.d.ts.map +1 -0
- package/src/engine/graphics/texture/sampler/compare/sampler2d_max_absolute_difference.js +62 -0
- package/src/engine/graphics/texture/sampler/compare/sampler2d_psnr.d.ts +30 -0
- package/src/engine/graphics/texture/sampler/compare/sampler2d_psnr.d.ts.map +1 -0
- package/src/engine/graphics/texture/sampler/compare/sampler2d_psnr.js +115 -0
- package/src/engine/graphics/texture/sampler/sampler2d_to_avif.d.ts.map +1 -0
- package/src/engine/graphics/texture/sampler/sampler2d_to_avif.js +108 -0
- package/src/engine/graphics/texture/sampler/sampler2d_to_f16.d.ts +7 -1
- package/src/engine/graphics/texture/sampler/sampler2d_to_f16.d.ts.map +1 -1
- package/src/engine/graphics/texture/sampler/sampler2d_to_f16.js +28 -21
- package/src/engine/graphics/texture/sampler/sampler2d_to_uint8_RGBA.d.ts.map +1 -1
- package/src/engine/graphics/texture/sampler/sampler2d_to_uint8_RGBA.js +3 -0
- package/src/engine/network/NetworkSession.d.ts +24 -4
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +28 -4
- package/src/engine/network/orchestrator/NetworkPeer.d.ts +47 -6
- package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/NetworkPeer.js +184 -56
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +97 -11
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +304 -22
- package/src/engine/network/replication/Replicator.d.ts +14 -1
- package/src/engine/network/replication/Replicator.d.ts.map +1 -1
- package/src/engine/network/replication/Replicator.js +44 -3
- package/src/engine/network/sim/ActionLog.d.ts +21 -3
- package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
- package/src/engine/network/sim/ActionLog.js +24 -3
- package/src/engine/network/sim/SimAction.d.ts +15 -0
- package/src/engine/network/sim/SimAction.d.ts.map +1 -1
- package/src/engine/network/sim/SimAction.js +15 -0
- package/src/engine/network/sim/SimActionExecutor.d.ts +51 -1
- package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
- package/src/engine/network/sim/SimActionExecutor.js +73 -5
- package/src/engine/network/transport/Channel.d.ts +1 -1
- package/src/engine/network/transport/Channel.js +1 -1
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/simulation/Ticker.d.ts.map +1 -1
- package/src/engine/simulation/Ticker.js +4 -1
- package/src/engine/ui/GUIEngine.d.ts.map +1 -1
- package/src/engine/ui/GUIEngine.js +6 -0
- package/src/format/image/avif/DECISIONS.md +545 -0
- package/src/format/image/avif/api/AvifDecoder.d.ts.map +1 -0
- package/src/format/image/avif/api/apply_transformations.d.ts.map +1 -0
- package/src/format/image/avif/api/convert_to_rgba.d.ts.map +1 -0
- package/src/format/image/avif/api/convert_to_rgba.js +204 -0
- package/src/format/image/avif/api/decode_avif.d.ts.map +1 -0
- package/src/format/image/avif/api/decode_image_item.d.ts.map +1 -0
- package/src/format/image/avif/api/encode_avif.d.ts.map +1 -0
- package/src/format/image/avif/av1/decode/Av1FrameContext.d.ts.map +1 -0
- package/src/format/image/avif/av1/decode/block_decoded.d.ts.map +1 -0
- package/src/format/image/avif/av1/decode/decode_av1_still.d.ts.map +1 -0
- package/src/format/image/avif/av1/decode/decode_coefficients.d.ts.map +1 -0
- package/src/format/image/avif/av1/decode/decode_palette.d.ts.map +1 -0
- package/src/format/image/avif/av1/decode/decode_palette.js +442 -0
- package/src/format/image/avif/av1/decode/decode_tile.d.ts.map +1 -0
- package/src/format/image/avif/av1/decode/decode_tile.js +1213 -0
- package/src/format/image/avif/av1/decode/get_scan.d.ts.map +1 -0
- package/src/format/image/avif/av1/decode/read_lr.d.ts.map +1 -0
- package/src/format/image/avif/av1/decode/read_lr.js +277 -0
- package/src/format/image/avif/av1/decode/read_transform_type.d.ts.map +1 -0
- package/src/format/image/avif/av1/decode/read_transform_type.js +92 -0
- package/src/format/image/avif/av1/decode/reconstruct.d.ts.map +1 -0
- package/src/format/image/avif/av1/decode/reconstruct.js +241 -0
- package/src/format/image/avif/av1/decode/transform_type.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/Av1BlockSnapshot.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/Av1EncodeContext.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/build_headers.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/choose_chroma_alpha.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/choose_filters.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/choose_restoration.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/choose_restoration.js +616 -0
- package/src/format/image/avif/av1/encode/decode_effort.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/encode_av1_still.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/encode_effort.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/encode_tile.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/encode_tile.js +2331 -0
- package/src/format/image/avif/av1/encode/quantise.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/write_coefficients.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/write_lr.d.ts.map +1 -0
- package/src/format/image/avif/av1/encode/write_transform_type.d.ts.map +1 -0
- package/src/format/image/avif/av1/entropy/CdfContext.d.ts.map +1 -0
- package/src/format/image/avif/av1/entropy/SymbolReader.d.ts.map +1 -0
- package/src/format/image/avif/av1/entropy/SymbolWriter.d.ts.map +1 -0
- package/src/format/image/avif/av1/entropy/coefficient_context.d.ts.map +1 -0
- package/src/format/image/avif/av1/entropy/partition_cdf.d.ts.map +1 -0
- package/src/format/image/avif/av1/entropy/symbol_cost.d.ts.map +1 -0
- package/src/format/image/avif/av1/filter/cdef.d.ts.map +1 -0
- package/src/format/image/avif/av1/filter/cdef.js +313 -0
- package/src/format/image/avif/av1/filter/loop_filter.d.ts.map +1 -0
- package/src/format/image/avif/av1/filter/loop_filter.js +377 -0
- package/src/format/image/avif/av1/filter/loop_restoration.d.ts.map +1 -0
- package/src/format/image/avif/av1/filter/loop_restoration.js +451 -0
- package/src/format/image/avif/av1/filter/superres.d.ts.map +1 -0
- package/src/format/image/avif/av1/filter/superres.js +86 -0
- package/src/format/image/avif/av1/grain/FilmGrainState.d.ts.map +1 -0
- package/src/format/image/avif/av1/grain/film_grain.d.ts.map +1 -0
- package/src/format/image/avif/av1/grain/film_grain.js +623 -0
- package/src/format/image/avif/av1/obu/FrameHeader.d.ts.map +1 -0
- package/src/format/image/avif/av1/obu/ObuHeader.d.ts.map +1 -0
- package/src/format/image/avif/av1/obu/SequenceHeader.d.ts.map +1 -0
- package/src/format/image/avif/av1/obu/for_each_obu.d.ts.map +1 -0
- package/src/format/image/avif/av1/obu/parse_frame_header.d.ts.map +1 -0
- package/src/format/image/avif/av1/obu/parse_frame_header.js +841 -0
- package/src/format/image/avif/av1/obu/parse_obu_header.d.ts.map +1 -0
- package/src/format/image/avif/av1/obu/parse_sequence_header.d.ts.map +1 -0
- package/src/format/image/avif/av1/obu/write_frame_header.d.ts.map +1 -0
- package/src/format/image/avif/av1/obu/write_sequence_header.d.ts.map +1 -0
- package/src/format/image/avif/av1/predict/IntraPredictionState.d.ts.map +1 -0
- package/src/format/image/avif/av1/predict/intra_filter_type.d.ts.map +1 -0
- package/src/format/image/avif/av1/predict/predict_chroma_from_luma.d.ts.map +1 -0
- package/src/format/image/avif/av1/predict/predict_chroma_from_luma.js +153 -0
- package/src/format/image/avif/av1/predict/predict_intra.d.ts.map +1 -0
- package/src/format/image/avif/av1/predict/predict_intra.js +803 -0
- package/src/format/image/avif/av1/predict/predict_palette.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/av1_symbols.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/av1_symbols.js +419 -0
- package/src/format/image/avif/av1/tables/block_tables.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/block_tables.js +270 -0
- package/src/format/image/avif/av1/tables/cdf_tables.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/cdf_tables.js +1893 -0
- package/src/format/image/avif/av1/tables/coefficient_tables.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/coefficient_tables.js +82 -0
- package/src/format/image/avif/av1/tables/derived_block_tables.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/filter_tables.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/filter_tables.js +313 -0
- package/src/format/image/avif/av1/tables/grain_tables.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/grain_tables.js +190 -0
- package/src/format/image/avif/av1/tables/prediction_tables.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/prediction_tables.js +223 -0
- package/src/format/image/avif/av1/tables/quantizer_matrix_tables.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/quantizer_matrix_tables.js +38 -0
- package/src/format/image/avif/av1/tables/quantizer_tables.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/quantizer_tables.js +160 -0
- package/src/format/image/avif/av1/tables/scan_tables.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/scan_tables.js +727 -0
- package/src/format/image/avif/av1/tables/segmentation_tables.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/segmentation_tables.js +48 -0
- package/src/format/image/avif/av1/tables/transform_tables.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/transform_tables.js +140 -0
- package/src/format/image/avif/av1/tables/unpack_table.d.ts.map +1 -0
- package/src/format/image/avif/av1/tables/unpack_table.js +73 -0
- package/src/format/image/avif/av1/transform/forward_transform_2d.d.ts.map +1 -0
- package/src/format/image/avif/av1/transform/inverse_transform_1d.d.ts.map +1 -0
- package/src/format/image/avif/av1/transform/inverse_transform_1d.js +590 -0
- package/src/format/image/avif/av1/transform/inverse_transform_2d.d.ts.map +1 -0
- package/src/format/image/avif/av1/transform/inverse_transform_2d.js +180 -0
- package/src/format/image/avif/av1/util/ceil_log2.d.ts.map +1 -0
- package/src/format/image/avif/av1/util/floor_log2.d.ts +20 -0
- package/src/format/image/avif/av1/util/floor_log2.d.ts.map +1 -0
- package/src/format/image/avif/av1/util/floor_log2.js +20 -0
- package/src/format/image/avif/av1/util/round2.d.ts.map +1 -0
- package/src/format/image/avif/av1/util/round2_signed.d.ts.map +1 -0
- package/src/format/image/avif/av1/util/tile_log2.d.ts.map +1 -0
- package/src/format/image/avif/bitstream/BitReader.d.ts.map +1 -0
- package/src/format/image/avif/bitstream/BitWriter.d.ts.map +1 -0
- package/src/format/image/avif/color/ColourTransform.d.ts.map +1 -0
- package/src/format/image/avif/color/YuvImage.d.ts.map +1 -0
- package/src/format/image/avif/color/clamp_sample.d.ts.map +1 -0
- package/src/format/image/avif/color/linear_to_transfer.d.ts.map +1 -0
- package/src/format/image/avif/color/linear_to_transfer.js +126 -0
- package/src/format/image/avif/color/primaries.d.ts.map +1 -0
- package/src/format/image/avif/color/rgb_row_to_ycbcr.d.ts.map +1 -0
- package/src/format/image/avif/color/transfer_to_linear.d.ts.map +1 -0
- package/src/format/image/avif/color/transfer_to_linear.js +171 -0
- package/src/format/image/avif/color/upsample_chroma_row.d.ts.map +1 -0
- package/src/format/image/avif/color/upsample_chroma_row.js +89 -0
- package/src/format/image/avif/color/ycbcr_row_to_rgb.d.ts.map +1 -0
- package/src/format/image/avif/color/ycbcr_row_to_rgb.js +78 -0
- package/src/format/image/avif/heif/AvifFile.d.ts.map +1 -0
- package/src/format/image/avif/heif/ItemProperty.d.ts.map +1 -0
- package/src/format/image/avif/heif/find_item_property.d.ts.map +1 -0
- package/src/format/image/avif/heif/find_item_references.d.ts.map +1 -0
- package/src/format/image/avif/heif/find_items_referencing.d.ts.map +1 -0
- package/src/format/image/avif/heif/parse_avif_file.d.ts.map +1 -0
- package/src/format/image/avif/heif/parse_avif_file.js +384 -0
- package/src/format/image/avif/heif/parse_image_grid.d.ts.map +1 -0
- package/src/format/image/avif/heif/parse_image_grid.js +49 -0
- package/src/format/image/avif/heif/parse_item_property.d.ts.map +1 -0
- package/src/format/image/avif/heif/read_item_data.d.ts.map +1 -0
- package/src/format/image/avif/heif/write_avif_file.d.ts.map +1 -0
- package/src/format/image/avif/heif/write_item_property.d.ts.map +1 -0
- package/src/format/image/avif/index.d.ts +12 -0
- package/src/format/image/avif/index.d.ts.map +1 -0
- package/src/format/image/avif/index.js +58 -0
- package/src/format/image/avif/isobmff/BoxHeader.d.ts.map +1 -0
- package/src/format/image/avif/isobmff/BoxWriter.d.ts +118 -0
- package/src/format/image/avif/isobmff/BoxWriter.d.ts.map +1 -0
- package/src/format/image/avif/isobmff/BoxWriter.js +264 -0
- package/src/format/image/avif/isobmff/for_each_box.d.ts.map +1 -0
- package/src/format/image/avif/isobmff/read_box_header.d.ts.map +1 -0
- package/src/format/image/avif/isobmff/read_full_box_header.d.ts.map +1 -0
- package/src/format/image/jpeg/JpegFrame.d.ts.map +1 -0
- package/src/format/image/jpeg/JpegFrameComponent.d.ts.map +1 -0
- package/src/format/image/jpeg/JpegImage.d.ts.map +1 -0
- package/src/format/image/jpeg/JpegImage.js +664 -0
- package/src/format/image/jpeg/buildComponentData.d.ts.map +1 -0
- package/src/format/image/jpeg/buildHuffmanTable.d.ts.map +1 -0
- package/src/format/image/jpeg/decodeScan.d.ts.map +1 -0
- package/src/format/image/jpeg/idct8x8_float.d.ts.map +1 -0
- package/src/format/image/jpeg/idct8x8_float.js +31 -0
- package/src/format/image/jpeg/jpeg_component_row.d.ts.map +1 -0
- package/src/format/image/jpeg/jpeg_decode.d.ts.map +1 -0
- package/src/format/image/png/PNG.d.ts.map +1 -0
- package/src/format/image/png/PNGReader.d.ts +158 -0
- package/src/format/image/png/PNGReader.d.ts.map +1 -0
- package/src/format/image/png/PNGReader.js +656 -0
- package/src/format/image/png/PNG_HEADER_BYTES.d.ts.map +1 -0
- package/src/format/image/png/chunk/png_chunk_decode_iTXt.d.ts.map +1 -0
- package/src/format/image/png/chunk/png_chunk_decode_iTXt.js +53 -0
- package/src/format/image/png/chunk/png_chunk_decode_zTXt.d.ts.map +1 -0
- package/src/format/image/png/chunk/png_chunk_decode_zTXt.js +42 -0
- package/src/format/image/png/crc32.d.ts +2 -0
- package/src/format/image/png/crc32.d.ts.map +1 -0
- package/src/format/image/png/crc32.js +8 -0
- package/src/format/image/png/filter/png_filter_unFilterAverage.d.ts.map +1 -0
- package/src/format/image/png/filter/png_filter_unFilterNone.d.ts.map +1 -0
- package/src/format/image/png/filter/png_filter_unFilterPaeth.d.ts.map +1 -0
- package/src/format/image/png/filter/png_filter_unFilterSub.d.ts.map +1 -0
- package/src/format/image/png/filter/png_filter_unFilterUp.d.ts.map +1 -0
- package/src/format/image/png/filter/png_unfilter.d.ts.map +1 -0
- package/src/format/image/png/filter/png_unfilter.js +68 -0
- package/src/format/image/png/png_inflate.d.ts.map +1 -0
- package/src/format/image/png/png_unpack_samples.d.ts.map +1 -0
- package/src/format/scene/gltf/GLTF_PRIMITIVE_MODE.d.ts.map +1 -0
- package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +793 -0
- package/src/format/scene/gltf/coalesce_array_duplicates.d.ts.map +1 -0
- package/src/format/scene/gltf/ext/GltfBufferViewExtension.d.ts.map +1 -0
- package/src/format/scene/gltf/ext/GltfBufferViewExtensionSet.d.ts.map +1 -0
- package/src/format/scene/gltf/ext/GltfBufferViewExtensionSet.js +109 -0
- package/src/format/scene/gltf/ext/gltf_apply_buffer_view_extensions.d.ts.map +1 -0
- package/src/format/scene/gltf/ext/gltf_buffer_view_extensions.d.ts.map +1 -0
- package/src/format/scene/gltf/ext/gltf_geometry_extensions.d.ts.map +1 -0
- package/src/format/scene/gltf/ext/meshopt/MeshoptBufferViewExtension.d.ts.map +1 -0
- package/src/format/scene/gltf/ext/meshopt/MeshoptBufferViewExtension.js +301 -0
- package/src/format/scene/gltf/gltf_component_type.d.ts.map +1 -0
- package/src/format/scene/gltf/gltf_node_world_matrices.d.ts.map +1 -0
- package/src/format/scene/gltf/gltf_node_world_matrices.js +137 -0
- package/src/format/scene/gltf/gltf_parse_container.d.ts.map +1 -0
- package/src/format/scene/gltf/gltf_read_accessor.d.ts.map +1 -0
- package/src/format/scene/gltf/gltf_read_accessor.js +294 -0
- package/src/format/scene/gltf/gltf_used_image_indices.d.ts +51 -0
- package/src/format/scene/gltf/gltf_used_image_indices.d.ts.map +1 -0
- package/src/format/scene/gltf/gltf_used_image_indices.js +122 -0
- package/src/format/scene/usd/UsdError.d.ts.map +1 -0
- package/src/format/scene/usd/parse_usda.d.ts.map +1 -0
- package/src/format/scene/usd/unpack_usdz.d.ts.map +1 -0
- package/src/format/scene/usd/unpack_usdz.js +106 -0
- package/src/format/scene/usd/usd_compose_transform.d.ts.map +1 -0
- package/src/format/scene/usd/usd_compose_transform.js +258 -0
- package/src/format/scene/usd/usd_lz4.d.ts.map +1 -0
- package/src/format/scene/usd/usd_lz4.js +182 -0
- package/src/format/scene/usd/usd_triangulate.d.ts.map +1 -0
- package/src/format/texture/TexelPayload.d.ts +55 -0
- package/src/format/texture/TexelPayload.d.ts.map +1 -0
- package/src/format/texture/TexelPayload.js +39 -0
- package/src/format/texture/basis/BasisBitReader.d.ts +77 -0
- package/src/format/texture/basis/BasisBitReader.d.ts.map +1 -0
- package/src/format/texture/basis/BasisBitReader.js +231 -0
- package/src/format/texture/basis/BasisHuffmanTable.d.ts.map +1 -0
- package/src/format/texture/basis/astc_block.d.ts +92 -0
- package/src/format/texture/basis/astc_block.d.ts.map +1 -0
- package/src/format/texture/basis/astc_block.js +164 -0
- package/src/format/texture/basis/astc_integer_sequence.d.ts +59 -0
- package/src/format/texture/basis/astc_integer_sequence.d.ts.map +1 -0
- package/src/format/texture/basis/astc_integer_sequence.js +251 -0
- package/src/format/texture/basis/astc_partition.d.ts +56 -0
- package/src/format/texture/basis/astc_partition.d.ts.map +1 -0
- package/src/format/texture/basis/astc_partition.js +199 -0
- package/src/format/texture/basis/basis_read_huffman_table.d.ts.map +1 -0
- package/src/format/texture/basis/etc1s/Etc1sSelectorHistory.d.ts.map +1 -0
- package/src/format/texture/basis/etc1s/etc1s_block_colors.d.ts.map +1 -0
- package/src/format/texture/basis/etc1s/etc1s_decode_slice.d.ts.map +1 -0
- package/src/format/texture/basis/etc1s/etc1s_decode_slice.js +290 -0
- package/src/format/texture/basis/etc1s/etc1s_read_endpoint_codebook.d.ts.map +1 -0
- package/src/format/texture/basis/etc1s/etc1s_read_selector_codebook.d.ts.map +1 -0
- package/src/format/texture/basis/etc1s/etc1s_read_slice_tables.d.ts.map +1 -0
- package/src/format/texture/basis/transcode/build_range_plan.d.ts +46 -0
- package/src/format/texture/basis/transcode/build_range_plan.d.ts.map +1 -0
- package/src/format/texture/basis/transcode/etc1s_to_astc.d.ts +30 -0
- package/src/format/texture/basis/transcode/etc1s_to_astc.d.ts.map +1 -0
- package/src/format/texture/basis/transcode/etc1s_to_astc.js +328 -0
- package/src/format/texture/basis/transcode/etc1s_to_bc1.d.ts +34 -0
- package/src/format/texture/basis/transcode/etc1s_to_bc1.d.ts.map +1 -0
- package/src/format/texture/basis/transcode/etc1s_to_bc1.js +486 -0
- package/src/format/texture/basis/transcode/etc1s_to_bc7.d.ts +27 -0
- package/src/format/texture/basis/transcode/etc1s_to_bc7.d.ts.map +1 -0
- package/src/format/texture/basis/transcode/etc1s_to_etc2.d.ts +31 -0
- package/src/format/texture/basis/transcode/etc1s_to_etc2.d.ts.map +1 -0
- package/src/format/texture/basis/transcode/etc1s_to_etc2.js +332 -0
- package/src/format/texture/basis/transcode/etc1s_to_rgba8.d.ts +39 -0
- package/src/format/texture/basis/transcode/etc1s_to_rgba8.d.ts.map +1 -0
- package/src/format/texture/basis/transcode/etc1s_to_rgba8.js +115 -0
- package/src/format/texture/basis/transcode/fit_endpoints.d.ts +79 -0
- package/src/format/texture/basis/transcode/fit_endpoints.d.ts.map +1 -0
- package/src/format/texture/basis/transcode/fit_endpoints.js +297 -0
- package/src/format/texture/basis/transcode_basis.d.ts +109 -0
- package/src/format/texture/basis/transcode_basis.d.ts.map +1 -0
- package/src/format/texture/basis/transcode_basis.js +250 -0
- package/src/format/texture/basis/transcode_uastc.d.ts +55 -0
- package/src/format/texture/basis/transcode_uastc.d.ts.map +1 -0
- package/src/format/texture/basis/transcode_uastc.js +117 -0
- package/src/format/texture/basis/uastc/bc7_tables.d.ts +111 -0
- package/src/format/texture/basis/uastc/bc7_tables.d.ts.map +1 -0
- package/src/format/texture/basis/uastc/bc7_tables.js +276 -0
- package/src/format/texture/basis/uastc/bc7_write_block.d.ts +124 -0
- package/src/format/texture/basis/uastc/bc7_write_block.d.ts.map +1 -0
- package/src/format/texture/basis/uastc/bc7_write_block.js +227 -0
- package/src/format/texture/basis/uastc/uastc_decode_block.d.ts +105 -0
- package/src/format/texture/basis/uastc/uastc_decode_block.d.ts.map +1 -0
- package/src/format/texture/basis/uastc/uastc_decode_block.js +480 -0
- package/src/format/texture/basis/uastc/uastc_tables.d.ts +240 -0
- package/src/format/texture/basis/uastc/uastc_tables.d.ts.map +1 -0
- package/src/format/texture/basis/uastc/uastc_tables.js +383 -0
- package/src/format/texture/basis/uastc/uastc_to_astc.d.ts +30 -0
- package/src/format/texture/basis/uastc/uastc_to_astc.d.ts.map +1 -0
- package/src/format/texture/basis/uastc/uastc_to_astc.js +421 -0
- package/src/format/texture/basis/uastc/uastc_to_bc5.d.ts +26 -0
- package/src/format/texture/basis/uastc/uastc_to_bc5.d.ts.map +1 -0
- package/src/format/texture/basis/uastc/uastc_to_bc5.js +115 -0
- package/src/format/texture/basis/uastc/uastc_to_bc7.d.ts +36 -0
- package/src/format/texture/basis/uastc/uastc_to_bc7.d.ts.map +1 -0
- package/src/format/texture/basis/uastc/uastc_to_bc7.js +602 -0
- package/src/format/texture/basis/uastc/uastc_to_rgba8.d.ts +37 -0
- package/src/format/texture/basis/uastc/uastc_to_rgba8.d.ts.map +1 -0
- package/src/format/texture/basis/uastc/uastc_to_rgba8.js +87 -0
- package/src/format/texture/bc/bc1_write_block.d.ts +28 -0
- package/src/format/texture/bc/bc1_write_block.d.ts.map +1 -0
- package/src/format/texture/bc/bc1_write_block.js +41 -0
- package/src/format/texture/bc/bc4_write_block.d.ts +32 -0
- package/src/format/texture/bc/bc4_write_block.d.ts.map +1 -0
- package/src/format/texture/bc/bc4_write_block.js +50 -0
- package/src/format/texture/bc/bc6h_write_block_mode11.d.ts +30 -0
- package/src/format/texture/bc/bc6h_write_block_mode11.d.ts.map +1 -0
- package/src/format/texture/bc/bc6h_write_block_mode11.js +62 -0
- package/src/format/texture/ktx2/KTX2_IDENTIFIER.d.ts.map +1 -0
- package/src/format/texture/ktx2/KhrDfModel.d.ts.map +1 -0
- package/src/format/texture/ktx2/SupercompressionScheme.d.ts.map +1 -0
- package/src/format/texture/ktx2/ktx2_read.d.ts +105 -0
- package/src/format/texture/ktx2/ktx2_read.d.ts.map +1 -0
- package/src/format/texture/ktx2/ktx2_read.js +909 -0
- package/src/format/texture/ktx2/ktx2_read_basis_lz_global_data.d.ts +27 -0
- package/src/format/texture/ktx2/ktx2_read_basis_lz_global_data.d.ts.map +1 -0
- package/src/format/texture/ktx2/ktx2_read_basis_lz_global_data.js +189 -0
- package/src/format/texture/ktx2/vk_format_to_texture_format.d.ts +55 -0
- package/src/format/texture/ktx2/vk_format_to_texture_format.d.ts.map +1 -0
- package/src/format/texture/ktx2/vk_format_to_texture_format.js +290 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_feature.d.ts +16 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_feature.d.ts.map +1 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_feature.js +44 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_info.d.ts +16 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_info.d.ts.map +1 -1
- package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +24 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_srgb.d.ts +19 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_srgb.d.ts.map +1 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_srgb.js +50 -0
- package/src/shade/device/COPY_BYTES_PER_ROW_ALIGNMENT.d.ts +14 -0
- package/src/shade/device/COPY_BYTES_PER_ROW_ALIGNMENT.d.ts.map +1 -0
- package/src/shade/device/COPY_BYTES_PER_ROW_ALIGNMENT.js +13 -0
- package/src/shade/device/mock/SoftwareGPUDevice.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUDevice.js +37 -3
- package/src/shade/device/mock/SoftwareGPUTexture.d.ts +4 -2
- package/src/shade/device/mock/SoftwareGPUTexture.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUTexture.js +39 -3
- package/src/shade/device/mock/SoftwareGPUTextureView.d.ts +7 -0
- package/src/shade/device/mock/SoftwareGPUTextureView.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUTextureView.js +8 -0
- package/src/shade/device/mock/texture_copy.d.ts.map +1 -1
- package/src/shade/device/mock/texture_copy.js +74 -12
- package/src/shade/playground/basis_textures/README.md +105 -0
- package/src/shade/playground/basis_textures/index.html +141 -0
- package/src/shade/playground/basis_textures/main.d.ts +8 -0
- package/src/shade/playground/basis_textures/main.d.ts.map +1 -0
- package/src/shade/playground/basis_textures/main.js +351 -0
- package/src/shade/playground/basis_textures/make_basis_gltf.d.mts +2 -0
- package/src/shade/playground/basis_textures/make_basis_gltf.d.mts.map +1 -0
- package/src/shade/playground/basis_textures/make_basis_gltf.mjs +197 -0
- package/src/shade/playground/basis_textures/node_modules/basis_universal/bin/basisu.exe +0 -0
- package/src/shade/playground/basis_textures/texture_inventory.d.ts +28 -0
- package/src/shade/playground/basis_textures/texture_inventory.d.ts.map +1 -0
- package/src/shade/playground/basis_textures/texture_inventory.js +98 -0
- package/src/shade/playground/image_decode_bench/README.md +42 -0
- package/src/shade/playground/image_decode_bench/decode_worker.d.ts +2 -0
- package/src/shade/playground/image_decode_bench/decode_worker.d.ts.map +1 -0
- package/src/shade/playground/image_decode_bench/decode_worker.js +19 -0
- package/src/shade/playground/image_decode_bench/index.html +34 -0
- package/src/shade/playground/image_decode_bench/main.d.ts +2 -0
- package/src/shade/playground/image_decode_bench/main.d.ts.map +1 -0
- package/src/shade/playground/image_decode_bench/main.js +211 -0
- package/src/shade/playground/particle_system/README.md +98 -0
- package/src/shade/playground/particle_system/index.html +124 -0
- package/src/shade/playground/particle_system/main.d.ts +2 -0
- package/src/shade/playground/particle_system/main.d.ts.map +1 -0
- package/src/shade/playground/particle_system/main.js +180 -0
- package/src/shade/playground/particle_system/particle_scene.d.ts +52 -0
- package/src/shade/playground/particle_system/particle_scene.d.ts.map +1 -0
- package/src/shade/playground/particle_system/particle_scene.js +552 -0
- package/src/shade/playground/skinned_blas_refit/README.md +1 -1
- package/src/shade/playground/skinned_blas_refit/index.html +15 -1
- package/src/shade/playground/skinned_blas_refit/main.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/main.js +339 -3
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.d.ts +8 -1
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/shader_blas_audit_leaf_triangles.js +27 -5
- package/src/shade/playground/skinned_blas_refit/verify_clone_leaves.d.ts +27 -0
- package/src/shade/playground/skinned_blas_refit/verify_clone_leaves.d.ts.map +1 -0
- package/src/shade/playground/skinned_blas_refit/verify_clone_leaves.js +127 -0
- package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/verify_leaf_triangles.js +3 -3
- package/src/shade/playground/skinned_blas_refit/verify_skinned_blas_refit.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/verify_skinned_blas_refit.js +10 -8
- package/src/shade/playground/skinned_mesh_soup/README.md +122 -0
- package/src/shade/playground/skinned_mesh_soup/index.html +199 -0
- package/src/shade/playground/skinned_mesh_soup/main.d.ts +7 -0
- package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -0
- package/src/shade/playground/skinned_mesh_soup/main.js +564 -0
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts +23 -0
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts.map +1 -0
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.js +409 -0
- package/src/shade/playground/texture_encode/README.md +109 -0
- package/src/shade/playground/texture_encode/index.html +133 -0
- package/src/shade/playground/texture_encode/main.d.ts +24 -0
- package/src/shade/playground/texture_encode/main.d.ts.map +1 -0
- package/src/shade/playground/texture_encode/main.js +1430 -0
- package/src/shade/playground/texture_encode/panel_view.d.ts +118 -0
- package/src/shade/playground/texture_encode/panel_view.d.ts.map +1 -0
- package/src/shade/playground/texture_encode/panel_view.js +363 -0
- package/src/shade/renderer/Renderer.js +2 -2
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +49 -5
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +32 -14
- package/src/shade/renderer/geometry/GPUGeometryManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/GPUGeometryManager.js +591 -497
- package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts +9 -0
- package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts.map +1 -1
- package/src/shade/renderer/geometry/GPUGeometryMetadata.js +10 -0
- package/src/shade/renderer/geometry/bvh/BLAS_REFIT_BATCH_PLAN.md +606 -0
- package/src/shade/renderer/geometry/bvh/BLAS_REFIT_TARGET_STRUCT.d.ts +17 -0
- package/src/shade/renderer/geometry/bvh/BLAS_REFIT_TARGET_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/bvh/BLAS_REFIT_TARGET_STRUCT.js +44 -0
- package/src/shade/renderer/geometry/bvh/GPUBLASRefitBatch.d.ts +58 -0
- package/src/shade/renderer/geometry/bvh/GPUBLASRefitBatch.d.ts.map +1 -0
- package/src/shade/renderer/geometry/bvh/GPUBLASRefitBatch.js +362 -0
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts +38 -0
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +730 -617
- package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts +15 -2
- package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts.map +1 -1
- package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.js +15 -1
- package/src/shade/renderer/geometry/bvh/shader_blas_refit_batch.d.ts +39 -0
- package/src/shade/renderer/geometry/bvh/shader_blas_refit_batch.d.ts.map +1 -0
- package/src/shade/renderer/geometry/bvh/shader_blas_refit_batch.js +134 -0
- package/src/shade/renderer/geometry/virtual/build/gltf/gltf_collect_geometries.js +3 -3
- package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.js +3 -3
- package/src/shade/renderer/geometry/virtual/build/gltf/gltf_read_geometry.js +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/BVH_NODE_LAYOUT_DEFINITION.d.ts +17 -0
- package/src/shade/renderer/gpu_primitive/bvh/BVH_NODE_LAYOUT_DEFINITION.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/bvh/BVH_NODE_LAYOUT_DEFINITION.js +30 -0
- package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +8 -1
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_refit_climb.d.ts +34 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_refit_climb.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_refit_climb.js +102 -0
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.d.ts +11 -9
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_refit.js +24 -86
- package/src/shade/renderer/loader/gltf/gltf_create_texture.d.ts +18 -0
- package/src/shade/renderer/loader/gltf/gltf_create_texture.d.ts.map +1 -0
- package/src/shade/renderer/loader/gltf/gltf_create_texture.js +103 -0
- package/src/shade/renderer/loader/gltf/gltf_image_roles.d.ts +26 -0
- package/src/shade/renderer/loader/gltf/gltf_image_roles.d.ts.map +1 -0
- package/src/shade/renderer/loader/gltf/gltf_image_roles.js +108 -0
- package/src/shade/renderer/loader/gltf/load_gltf.d.ts +10 -3
- package/src/shade/renderer/loader/gltf/load_gltf.d.ts.map +1 -1
- package/src/shade/renderer/loader/gltf/load_gltf.js +1179 -1253
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +18 -1
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts.map +1 -1
- package/src/shade/renderer/loader/gltf/tiny-gltf.js +837 -646
- package/src/shade/renderer/loader/usd/load_usd.js +3 -3
- package/src/shade/renderer/loader/usd/usd_build_scene.js +2 -2
- package/src/shade/renderer/loader/usd/usd_decode_image.d.ts +6 -5
- package/src/shade/renderer/loader/usd/usd_decode_image.d.ts.map +1 -1
- package/src/shade/renderer/loader/usd/usd_decode_image.js +197 -384
- package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +1 -1
- package/src/shade/renderer/particles/cull/chunk_particle_cull.js +3 -1
- package/src/shade/renderer/particles/data/chunk_particle_emitter.js +1 -1
- package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts +1 -1
- package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts +89 -0
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -0
- package/src/shade/renderer/particles/isa/InstructionStream.js +162 -0
- package/src/shade/renderer/particles/isa/ParticleAssembler.d.ts +1 -48
- package/src/shade/renderer/particles/isa/ParticleAssembler.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/ParticleAssembler.js +25 -114
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.js +4 -2
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +4 -4
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +7 -5
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +3 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +3 -1
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +5 -2
- package/src/shade/renderer/particles/shaders/shader_particle_render.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_render.js +9 -2
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +3 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/postprocess/taa/TAA.d.ts +3 -3
- package/src/shade/renderer/postprocess/taa/TAA.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/taa/TAA.js +2 -6
- package/src/shade/renderer/postprocess/taa/chunk_depth_clip_offset_codec.d.ts +18 -0
- package/src/shade/renderer/postprocess/taa/chunk_depth_clip_offset_codec.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/taa/chunk_depth_clip_offset_codec.js +36 -0
- package/src/shade/renderer/postprocess/taa/chunk_taa_history_color_bounding_box_YCoCg.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/taa/chunk_taa_history_color_bounding_box_YCoCg.js +4 -1
- package/src/shade/renderer/postprocess/taa/shader_depth_occlusion_clip.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/taa/shader_depth_occlusion_clip.js +13 -8
- package/src/shade/renderer/postprocess/taa/shader_taa.d.ts +1 -1
- package/src/shade/renderer/postprocess/taa/shader_taa.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/taa/shader_taa.js +52 -38
- package/src/shade/renderer/restir/di/chunk_restir_temporal_reuse.d.ts +4 -2
- package/src/shade/renderer/restir/di/chunk_restir_temporal_reuse.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/chunk_restir_temporal_reuse.js +9 -6
- package/src/shade/renderer/scene/optimization/deduplicate_images.js +93 -93
- package/src/shade/renderer/scene/optimization/downscale_images.js +216 -216
- package/src/shade/renderer/scene/serialization/decode_image_source_hdr.js +1 -1
- package/src/shade/renderer/scene/serialization/deserialize_scene.js +1 -1
- package/src/shade/renderer/scene/serialization/write_image_source.js +1 -1
- package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_eotf_st2084.d.ts +1 -1
- package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_eotf_st2084.js +1 -1
- package/src/shade/renderer/shader/chunk/texture/sample/chunk_texture_sample_catmullrom_hardware_5tap_uv.d.ts +2 -1
- package/src/shade/renderer/shader/chunk/texture/sample/chunk_texture_sample_catmullrom_hardware_5tap_uv.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/texture/sample/chunk_texture_sample_catmullrom_hardware_5tap_uv.js +2 -1
- package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +893 -10
- package/src/shade/renderer/texture/encode/ENCODE_NOTES_2026_09_02.md +462 -0
- package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.d.ts +33 -0
- package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.js +310 -0
- package/src/shade/renderer/texture/encode/chunk_astc_pack_4x4_rgb.d.ts +17 -0
- package/src/shade/renderer/texture/encode/chunk_astc_pack_4x4_rgb.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_astc_pack_4x4_rgb.js +51 -0
- package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts +42 -0
- package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.js +375 -0
- package/src/shade/renderer/texture/encode/chunk_bc1_pack_block.d.ts +12 -0
- package/src/shade/renderer/texture/encode/chunk_bc1_pack_block.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc1_pack_block.js +24 -0
- package/src/shade/renderer/texture/encode/chunk_bc4_encode_block.d.ts +45 -0
- package/src/shade/renderer/texture/encode/chunk_bc4_encode_block.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc4_encode_block.js +348 -0
- package/src/shade/renderer/texture/encode/chunk_bc4_pack_block.d.ts +16 -0
- package/src/shade/renderer/texture/encode/chunk_bc4_pack_block.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc4_pack_block.js +33 -0
- package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.d.ts +32 -0
- package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.js +346 -0
- package/src/shade/renderer/texture/encode/chunk_bc6h_pack_mode11.d.ts +10 -0
- package/src/shade/renderer/texture/encode/chunk_bc6h_pack_mode11.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc6h_pack_mode11.js +54 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts +36 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.js +327 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts +22 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.js +71 -0
- package/src/shade/renderer/texture/encode/chunk_texture_encode_level.d.ts +20 -0
- package/src/shade/renderer/texture/encode/chunk_texture_encode_level.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_texture_encode_level.js +73 -0
- package/src/shade/renderer/texture/encode/chunk_texture_encode_load_block.d.ts +16 -0
- package/src/shade/renderer/texture/encode/chunk_texture_encode_load_block.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_texture_encode_load_block.js +36 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_astc_4x4.d.ts +13 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_astc_4x4.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_astc_4x4.js +63 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc1.d.ts +12 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc1.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc1.js +60 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc4.d.ts +28 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc4.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc4.js +76 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc4_snorm.d.ts +16 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc4_snorm.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc4_snorm.js +64 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc5.d.ts +14 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc5.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc5.js +67 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc5_snorm.d.ts +10 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc5_snorm.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc5_snorm.js +63 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc6h.d.ts +12 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc6h.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc6h.js +62 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts +14 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.js +58 -0
- package/src/shade/renderer/texture/encode/texture_encode.d.ts +84 -0
- package/src/shade/renderer/texture/encode/texture_encode.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/texture_encode.js +168 -0
- package/src/shade/renderer/texture/encode/texture_encode_layout.d.ts +196 -0
- package/src/shade/renderer/texture/encode/texture_encode_layout.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/texture_encode_layout.js +248 -0
- package/src/shade/renderer/texture/encode/texture_encode_resources.d.ts +15 -0
- package/src/shade/renderer/texture/encode/texture_encode_resources.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/texture_encode_resources.js +25 -0
- package/src/shade/renderer/texture/encode/texture_encode_shader.d.ts +30 -0
- package/src/shade/renderer/texture/encode/texture_encode_shader.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/texture_encode_shader.js +108 -0
- package/src/shade/renderer/texture/format/gpu_texture_compression_support.d.ts +3 -1
- package/src/shade/renderer/texture/format/gpu_texture_compression_support.d.ts.map +1 -1
- package/src/shade/renderer/texture/format/gpu_texture_compression_support.js +8 -25
- package/src/shade/renderer/texture/format/texture_format_from_shade_image.d.ts.map +1 -1
- package/src/shade/renderer/texture/format/texture_format_from_shade_image.js +26 -2
- package/src/shade/renderer/texture/source/texel_data_from_ktx2.d.ts +32 -0
- package/src/shade/renderer/texture/source/texel_data_from_ktx2.d.ts.map +1 -0
- package/src/shade/renderer/texture/source/texel_data_from_ktx2.js +48 -0
- package/src/shade/renderer/texture/texture_write_level.d.ts.map +1 -1
- package/src/shade/renderer/texture/texture_write_level.js +11 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +20 -0
- package/src/shade/renderer/volumetrics/NOTES.md +28 -0
- package/src/shade/renderer/volumetrics/taa/chunk_volumetric_history_bounding_box.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/taa/chunk_volumetric_history_bounding_box.js +7 -2
- package/src/shade/renderer/volumetrics/taa/chunk_volumetrics_taa_reproject.d.ts +17 -0
- package/src/shade/renderer/volumetrics/taa/chunk_volumetrics_taa_reproject.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/taa/chunk_volumetrics_taa_reproject.js +168 -0
- package/src/shade/renderer/volumetrics/taa/chunk_volumetrics_taa_resolve.d.ts +13 -0
- package/src/shade/renderer/volumetrics/taa/chunk_volumetrics_taa_resolve.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/taa/chunk_volumetrics_taa_resolve.js +56 -0
- package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.js +134 -334
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +49 -21
- package/src/avif/encode_image_source.d.ts +0 -70
- package/src/avif/encode_image_source.d.ts.map +0 -1
- package/src/avif/encode_image_source.js +0 -117
- package/src/avif/encoder_worker.d.ts.map +0 -1
- package/src/avif/index.d.ts +0 -5
- package/src/avif/index.d.ts.map +0 -1
- package/src/avif/index.js +0 -21
- package/src/avif/native/DECISIONS.md +0 -545
- package/src/avif/native/api/AvifDecoder.d.ts.map +0 -1
- package/src/avif/native/api/apply_transformations.d.ts.map +0 -1
- package/src/avif/native/api/avif_to_sampler2d.d.ts +0 -25
- package/src/avif/native/api/avif_to_sampler2d.d.ts.map +0 -1
- package/src/avif/native/api/avif_to_sampler2d.js +0 -42
- package/src/avif/native/api/convert_to_rgba.d.ts.map +0 -1
- package/src/avif/native/api/convert_to_rgba.js +0 -204
- package/src/avif/native/api/decode_avif.d.ts.map +0 -1
- package/src/avif/native/api/decode_image_item.d.ts.map +0 -1
- package/src/avif/native/api/encode_avif.d.ts.map +0 -1
- package/src/avif/native/api/sampler2d_to_avif.d.ts.map +0 -1
- package/src/avif/native/api/sampler2d_to_avif.js +0 -108
- package/src/avif/native/av1/decode/Av1FrameContext.d.ts.map +0 -1
- package/src/avif/native/av1/decode/block_decoded.d.ts.map +0 -1
- package/src/avif/native/av1/decode/decode_av1_still.d.ts.map +0 -1
- package/src/avif/native/av1/decode/decode_coefficients.d.ts.map +0 -1
- package/src/avif/native/av1/decode/decode_palette.d.ts.map +0 -1
- package/src/avif/native/av1/decode/decode_palette.js +0 -442
- package/src/avif/native/av1/decode/decode_tile.d.ts.map +0 -1
- package/src/avif/native/av1/decode/decode_tile.js +0 -1213
- package/src/avif/native/av1/decode/get_scan.d.ts.map +0 -1
- package/src/avif/native/av1/decode/read_lr.d.ts.map +0 -1
- package/src/avif/native/av1/decode/read_lr.js +0 -277
- package/src/avif/native/av1/decode/read_transform_type.d.ts.map +0 -1
- package/src/avif/native/av1/decode/read_transform_type.js +0 -92
- package/src/avif/native/av1/decode/reconstruct.d.ts.map +0 -1
- package/src/avif/native/av1/decode/reconstruct.js +0 -241
- package/src/avif/native/av1/decode/transform_type.d.ts.map +0 -1
- package/src/avif/native/av1/encode/Av1BlockSnapshot.d.ts.map +0 -1
- package/src/avif/native/av1/encode/Av1EncodeContext.d.ts.map +0 -1
- package/src/avif/native/av1/encode/build_headers.d.ts.map +0 -1
- package/src/avif/native/av1/encode/choose_chroma_alpha.d.ts.map +0 -1
- package/src/avif/native/av1/encode/choose_filters.d.ts.map +0 -1
- package/src/avif/native/av1/encode/choose_restoration.d.ts.map +0 -1
- package/src/avif/native/av1/encode/choose_restoration.js +0 -616
- package/src/avif/native/av1/encode/decode_effort.d.ts.map +0 -1
- package/src/avif/native/av1/encode/encode_av1_still.d.ts.map +0 -1
- package/src/avif/native/av1/encode/encode_effort.d.ts.map +0 -1
- package/src/avif/native/av1/encode/encode_tile.d.ts.map +0 -1
- package/src/avif/native/av1/encode/encode_tile.js +0 -2331
- package/src/avif/native/av1/encode/quantise.d.ts.map +0 -1
- package/src/avif/native/av1/encode/write_coefficients.d.ts.map +0 -1
- package/src/avif/native/av1/encode/write_lr.d.ts.map +0 -1
- package/src/avif/native/av1/encode/write_transform_type.d.ts.map +0 -1
- package/src/avif/native/av1/entropy/CdfContext.d.ts.map +0 -1
- package/src/avif/native/av1/entropy/SymbolReader.d.ts.map +0 -1
- package/src/avif/native/av1/entropy/SymbolWriter.d.ts.map +0 -1
- package/src/avif/native/av1/entropy/coefficient_context.d.ts.map +0 -1
- package/src/avif/native/av1/entropy/partition_cdf.d.ts.map +0 -1
- package/src/avif/native/av1/entropy/symbol_cost.d.ts.map +0 -1
- package/src/avif/native/av1/filter/cdef.d.ts.map +0 -1
- package/src/avif/native/av1/filter/cdef.js +0 -313
- package/src/avif/native/av1/filter/loop_filter.d.ts.map +0 -1
- package/src/avif/native/av1/filter/loop_filter.js +0 -377
- package/src/avif/native/av1/filter/loop_restoration.d.ts.map +0 -1
- package/src/avif/native/av1/filter/loop_restoration.js +0 -451
- package/src/avif/native/av1/filter/superres.d.ts.map +0 -1
- package/src/avif/native/av1/filter/superres.js +0 -86
- package/src/avif/native/av1/grain/FilmGrainState.d.ts.map +0 -1
- package/src/avif/native/av1/grain/film_grain.d.ts.map +0 -1
- package/src/avif/native/av1/grain/film_grain.js +0 -623
- package/src/avif/native/av1/obu/FrameHeader.d.ts.map +0 -1
- package/src/avif/native/av1/obu/ObuHeader.d.ts.map +0 -1
- package/src/avif/native/av1/obu/SequenceHeader.d.ts.map +0 -1
- package/src/avif/native/av1/obu/for_each_obu.d.ts.map +0 -1
- package/src/avif/native/av1/obu/parse_frame_header.d.ts.map +0 -1
- package/src/avif/native/av1/obu/parse_frame_header.js +0 -841
- package/src/avif/native/av1/obu/parse_obu_header.d.ts.map +0 -1
- package/src/avif/native/av1/obu/parse_sequence_header.d.ts.map +0 -1
- package/src/avif/native/av1/obu/write_frame_header.d.ts.map +0 -1
- package/src/avif/native/av1/obu/write_sequence_header.d.ts.map +0 -1
- package/src/avif/native/av1/predict/IntraPredictionState.d.ts.map +0 -1
- package/src/avif/native/av1/predict/intra_filter_type.d.ts.map +0 -1
- package/src/avif/native/av1/predict/predict_chroma_from_luma.d.ts.map +0 -1
- package/src/avif/native/av1/predict/predict_chroma_from_luma.js +0 -153
- package/src/avif/native/av1/predict/predict_intra.d.ts.map +0 -1
- package/src/avif/native/av1/predict/predict_intra.js +0 -803
- package/src/avif/native/av1/predict/predict_palette.d.ts.map +0 -1
- package/src/avif/native/av1/tables/av1_symbols.d.ts.map +0 -1
- package/src/avif/native/av1/tables/av1_symbols.js +0 -419
- package/src/avif/native/av1/tables/block_tables.d.ts.map +0 -1
- package/src/avif/native/av1/tables/block_tables.js +0 -270
- package/src/avif/native/av1/tables/cdf_tables.d.ts.map +0 -1
- package/src/avif/native/av1/tables/cdf_tables.js +0 -1893
- package/src/avif/native/av1/tables/coefficient_tables.d.ts.map +0 -1
- package/src/avif/native/av1/tables/coefficient_tables.js +0 -82
- package/src/avif/native/av1/tables/derived_block_tables.d.ts.map +0 -1
- package/src/avif/native/av1/tables/filter_tables.d.ts.map +0 -1
- package/src/avif/native/av1/tables/filter_tables.js +0 -313
- package/src/avif/native/av1/tables/grain_tables.d.ts.map +0 -1
- package/src/avif/native/av1/tables/grain_tables.js +0 -190
- package/src/avif/native/av1/tables/prediction_tables.d.ts.map +0 -1
- package/src/avif/native/av1/tables/prediction_tables.js +0 -223
- package/src/avif/native/av1/tables/quantizer_matrix_tables.d.ts.map +0 -1
- package/src/avif/native/av1/tables/quantizer_matrix_tables.js +0 -38
- package/src/avif/native/av1/tables/quantizer_tables.d.ts.map +0 -1
- package/src/avif/native/av1/tables/quantizer_tables.js +0 -160
- package/src/avif/native/av1/tables/scan_tables.d.ts.map +0 -1
- package/src/avif/native/av1/tables/scan_tables.js +0 -727
- package/src/avif/native/av1/tables/segmentation_tables.d.ts.map +0 -1
- package/src/avif/native/av1/tables/segmentation_tables.js +0 -48
- package/src/avif/native/av1/tables/transform_tables.d.ts.map +0 -1
- package/src/avif/native/av1/tables/transform_tables.js +0 -140
- package/src/avif/native/av1/tables/unpack_table.d.ts.map +0 -1
- package/src/avif/native/av1/tables/unpack_table.js +0 -73
- package/src/avif/native/av1/transform/forward_transform_2d.d.ts.map +0 -1
- package/src/avif/native/av1/transform/inverse_transform_1d.d.ts.map +0 -1
- package/src/avif/native/av1/transform/inverse_transform_1d.js +0 -590
- package/src/avif/native/av1/transform/inverse_transform_2d.d.ts.map +0 -1
- package/src/avif/native/av1/transform/inverse_transform_2d.js +0 -180
- package/src/avif/native/av1/util/ceil_log2.d.ts.map +0 -1
- package/src/avif/native/av1/util/floor_log2.d.ts +0 -20
- package/src/avif/native/av1/util/floor_log2.d.ts.map +0 -1
- package/src/avif/native/av1/util/floor_log2.js +0 -20
- package/src/avif/native/av1/util/round2.d.ts.map +0 -1
- package/src/avif/native/av1/util/round2_signed.d.ts.map +0 -1
- package/src/avif/native/av1/util/tile_log2.d.ts.map +0 -1
- package/src/avif/native/bitstream/BitReader.d.ts.map +0 -1
- package/src/avif/native/bitstream/BitWriter.d.ts.map +0 -1
- package/src/avif/native/color/ColourTransform.d.ts.map +0 -1
- package/src/avif/native/color/YuvImage.d.ts.map +0 -1
- package/src/avif/native/color/clamp_sample.d.ts.map +0 -1
- package/src/avif/native/color/linear_to_transfer.d.ts.map +0 -1
- package/src/avif/native/color/linear_to_transfer.js +0 -126
- package/src/avif/native/color/primaries.d.ts.map +0 -1
- package/src/avif/native/color/rgb_row_to_ycbcr.d.ts.map +0 -1
- package/src/avif/native/color/transfer_to_linear.d.ts.map +0 -1
- package/src/avif/native/color/transfer_to_linear.js +0 -171
- package/src/avif/native/color/upsample_chroma_row.d.ts.map +0 -1
- package/src/avif/native/color/upsample_chroma_row.js +0 -89
- package/src/avif/native/color/ycbcr_row_to_rgb.d.ts.map +0 -1
- package/src/avif/native/color/ycbcr_row_to_rgb.js +0 -78
- package/src/avif/native/heif/AvifFile.d.ts.map +0 -1
- package/src/avif/native/heif/ItemProperty.d.ts.map +0 -1
- package/src/avif/native/heif/find_item_property.d.ts.map +0 -1
- package/src/avif/native/heif/find_item_references.d.ts.map +0 -1
- package/src/avif/native/heif/find_items_referencing.d.ts.map +0 -1
- package/src/avif/native/heif/parse_avif_file.d.ts.map +0 -1
- package/src/avif/native/heif/parse_avif_file.js +0 -384
- package/src/avif/native/heif/parse_image_grid.d.ts.map +0 -1
- package/src/avif/native/heif/parse_image_grid.js +0 -49
- package/src/avif/native/heif/parse_item_property.d.ts.map +0 -1
- package/src/avif/native/heif/read_item_data.d.ts.map +0 -1
- package/src/avif/native/heif/write_avif_file.d.ts.map +0 -1
- package/src/avif/native/heif/write_item_property.d.ts.map +0 -1
- package/src/avif/native/index.d.ts +0 -14
- package/src/avif/native/index.d.ts.map +0 -1
- package/src/avif/native/index.js +0 -56
- package/src/avif/native/isobmff/BoxHeader.d.ts.map +0 -1
- package/src/avif/native/isobmff/BoxWriter.d.ts +0 -118
- package/src/avif/native/isobmff/BoxWriter.d.ts.map +0 -1
- package/src/avif/native/isobmff/BoxWriter.js +0 -264
- package/src/avif/native/isobmff/for_each_box.d.ts.map +0 -1
- package/src/avif/native/isobmff/read_box_header.d.ts.map +0 -1
- package/src/avif/native/isobmff/read_full_box_header.d.ts.map +0 -1
- package/src/avif/threaded_image_encoder.d.ts.map +0 -1
- package/src/basis/BasisBitReader.d.ts +0 -77
- package/src/basis/BasisBitReader.d.ts.map +0 -1
- package/src/basis/BasisBitReader.js +0 -231
- package/src/basis/BasisHuffmanTable.d.ts.map +0 -1
- package/src/basis/basis_read_huffman_table.d.ts.map +0 -1
- package/src/basis/etc1s/Etc1sSelectorHistory.d.ts.map +0 -1
- package/src/basis/etc1s/etc1s_block_colors.d.ts.map +0 -1
- package/src/basis/etc1s/etc1s_decode_slice.d.ts.map +0 -1
- package/src/basis/etc1s/etc1s_decode_slice.js +0 -258
- package/src/basis/etc1s/etc1s_read_endpoint_codebook.d.ts.map +0 -1
- package/src/basis/etc1s/etc1s_read_selector_codebook.d.ts.map +0 -1
- package/src/basis/etc1s/etc1s_read_slice_tables.d.ts.map +0 -1
- package/src/basis/transcode/etc1s_to_bc1.d.ts +0 -24
- package/src/basis/transcode/etc1s_to_bc1.d.ts.map +0 -1
- package/src/basis/transcode/etc1s_to_bc1.js +0 -205
- package/src/basis/transcode/etc1s_to_bc7.d.ts +0 -30
- package/src/basis/transcode/etc1s_to_bc7.d.ts.map +0 -1
- package/src/basis/transcode/fit_endpoints.d.ts +0 -59
- package/src/basis/transcode/fit_endpoints.d.ts.map +0 -1
- package/src/basis/transcode/fit_endpoints.js +0 -226
- package/src/engine/asset/loaders/gltf/computeObjectBoundingSphere.d.ts +0 -8
- package/src/engine/asset/loaders/gltf/computeObjectBoundingSphere.d.ts.map +0 -1
- package/src/engine/asset/loaders/gltf/computeObjectBoundingSphere.js +0 -70
- package/src/engine/asset/loaders/gltf/isMesh.d.ts +0 -7
- package/src/engine/asset/loaders/gltf/isMesh.d.ts.map +0 -1
- package/src/engine/asset/loaders/gltf/isMesh.js +0 -8
- package/src/engine/asset/loaders/image/jpeg/JpegFrame.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/jpeg/JpegFrameComponent.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/jpeg/JpegImage.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/jpeg/JpegImage.js +0 -664
- package/src/engine/asset/loaders/image/jpeg/buildComponentData.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/jpeg/buildHuffmanTable.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/jpeg/decodeScan.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/jpeg/idct8x8_float.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/jpeg/idct8x8_float.js +0 -31
- package/src/engine/asset/loaders/image/jpeg/jpeg_component_row.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/jpeg/jpeg_decode.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/PNG.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/PNGReader.d.ts +0 -158
- package/src/engine/asset/loaders/image/png/PNGReader.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/PNGReader.js +0 -656
- package/src/engine/asset/loaders/image/png/PNG_HEADER_BYTES.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/chunk/png_chunk_decode_iTXt.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/chunk/png_chunk_decode_iTXt.js +0 -53
- package/src/engine/asset/loaders/image/png/chunk/png_chunk_decode_zTXt.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/chunk/png_chunk_decode_zTXt.js +0 -42
- package/src/engine/asset/loaders/image/png/crc32.d.ts +0 -2
- package/src/engine/asset/loaders/image/png/crc32.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/crc32.js +0 -8
- package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterAverage.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterNone.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterPaeth.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterSub.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterUp.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/filter/png_unfilter.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/filter/png_unfilter.js +0 -68
- package/src/engine/asset/loaders/image/png/png_inflate.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/png_unpack_samples.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/prototypePNG.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/png/prototypePNG.js +0 -37
- package/src/ktx2/KTX2_IDENTIFIER.d.ts.map +0 -1
- package/src/ktx2/KhrDfModel.d.ts.map +0 -1
- package/src/ktx2/SupercompressionScheme.d.ts.map +0 -1
- package/src/ktx2/ktx2_read.d.ts +0 -71
- package/src/ktx2/ktx2_read.d.ts.map +0 -1
- package/src/ktx2/ktx2_read.js +0 -581
- package/src/ktx2/ktx2_read_basis_lz_global_data.d.ts +0 -27
- package/src/ktx2/ktx2_read_basis_lz_global_data.d.ts.map +0 -1
- package/src/ktx2/ktx2_read_basis_lz_global_data.js +0 -189
- package/src/ktx2/vk_format_to_texture_format.d.ts +0 -55
- package/src/ktx2/vk_format_to_texture_format.d.ts.map +0 -1
- package/src/ktx2/vk_format_to_texture_format.js +0 -290
- package/src/shade/renderer/geometry/bvh/record_blas_refit.d.ts +0 -25
- package/src/shade/renderer/geometry/bvh/record_blas_refit.d.ts.map +0 -1
- package/src/shade/renderer/geometry/bvh/record_blas_refit.js +0 -102
- package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.d.ts +0 -30
- package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.d.ts.map +0 -1
- package/src/shade/renderer/geometry/bvh/shader_blas_refit_leaf_bounds.js +0 -125
- package/src/shade/renderer/loader/gltf/GLTF_PRIMITIVE_MODE.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/MESHOPT_COMPRESSION_PLAN.md +0 -793
- package/src/shade/renderer/loader/gltf/coalesce_array_duplicates.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtension.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtensionSet.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtensionSet.js +0 -109
- package/src/shade/renderer/loader/gltf/ext/gltf_apply_buffer_view_extensions.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/ext/gltf_buffer_view_extensions.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/ext/gltf_geometry_extensions.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/ext/meshopt/MeshoptBufferViewExtension.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/ext/meshopt/MeshoptBufferViewExtension.js +0 -301
- package/src/shade/renderer/loader/gltf/gltf_component_type.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/gltf_node_world_matrices.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/gltf_node_world_matrices.js +0 -137
- package/src/shade/renderer/loader/gltf/gltf_parse_container.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/gltf_read_accessor.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/gltf_read_accessor.js +0 -294
- package/src/shade/renderer/loader/gltf/gltf_used_image_indices.d.ts +0 -25
- package/src/shade/renderer/loader/gltf/gltf_used_image_indices.d.ts.map +0 -1
- package/src/shade/renderer/loader/gltf/gltf_used_image_indices.js +0 -49
- package/src/shade/renderer/loader/usd/UsdError.d.ts.map +0 -1
- package/src/shade/renderer/loader/usd/parse_usda.d.ts.map +0 -1
- package/src/shade/renderer/loader/usd/unpack_usdz.d.ts.map +0 -1
- package/src/shade/renderer/loader/usd/unpack_usdz.js +0 -106
- package/src/shade/renderer/loader/usd/usd_compose_transform.d.ts.map +0 -1
- package/src/shade/renderer/loader/usd/usd_compose_transform.js +0 -258
- package/src/shade/renderer/loader/usd/usd_lz4.d.ts.map +0 -1
- package/src/shade/renderer/loader/usd/usd_lz4.js +0 -182
- package/src/shade/renderer/loader/usd/usd_triangulate.d.ts.map +0 -1
- package/src/shade/renderer/particles/prototypeParticleSystem.d.ts +0 -2
- package/src/shade/renderer/particles/prototypeParticleSystem.d.ts.map +0 -1
- package/src/shade/renderer/particles/prototypeParticleSystem.js +0 -448
- package/src/shade/renderer/postprocess/taa/chunk_taa_sample_history_color.d.ts +0 -2
- package/src/shade/renderer/postprocess/taa/chunk_taa_sample_history_color.d.ts.map +0 -1
- package/src/shade/renderer/postprocess/taa/chunk_taa_sample_history_color.js +0 -43
- package/src/shade/renderer/scene/optimization/sampler2d_compare.d.ts.map +0 -1
- package/src/shade/renderer/scene/optimization/sampler2d_compare.js +0 -94
- /package/src/{avif → engine/asset/loaders/image/avif}/encoder_worker.d.ts +0 -0
- /package/src/{avif → engine/asset/loaders/image/avif}/encoder_worker.js +0 -0
- /package/src/{avif → engine/asset/loaders/image/avif}/threaded_image_encoder.d.ts +0 -0
- /package/src/{avif → engine/asset/loaders/image/avif}/threaded_image_encoder.js +0 -0
- /package/src/engine/asset/loaders/image/{png/prototypePNG.d.ts → prototypePNG.d.ts} +0 -0
- /package/src/{shade/renderer/scene/optimization → engine/graphics/texture/sampler/compare}/sampler2d_compare.d.ts +0 -0
- /package/src/{avif/native/api → engine/graphics/texture/sampler}/sampler2d_to_avif.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/NOTICE.md +0 -0
- /package/src/{avif/native → format/image/avif}/api/AvifDecoder.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/api/AvifDecoder.js +0 -0
- /package/src/{avif/native → format/image/avif}/api/apply_transformations.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/api/apply_transformations.js +0 -0
- /package/src/{avif/native → format/image/avif}/api/convert_to_rgba.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/api/decode_avif.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/api/decode_avif.js +0 -0
- /package/src/{avif/native → format/image/avif}/api/decode_image_item.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/api/decode_image_item.js +0 -0
- /package/src/{avif/native → format/image/avif}/api/encode_avif.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/api/encode_avif.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/Av1FrameContext.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/Av1FrameContext.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/block_decoded.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/block_decoded.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/decode_av1_still.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/decode_av1_still.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/decode_coefficients.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/decode_coefficients.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/decode_palette.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/decode_tile.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/get_scan.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/get_scan.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/read_lr.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/read_transform_type.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/reconstruct.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/transform_type.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/decode/transform_type.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/Av1BlockSnapshot.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/Av1BlockSnapshot.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/Av1EncodeContext.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/Av1EncodeContext.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/build_headers.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/build_headers.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/choose_chroma_alpha.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/choose_chroma_alpha.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/choose_filters.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/choose_filters.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/choose_restoration.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/decode_effort.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/decode_effort.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/encode_av1_still.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/encode_av1_still.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/encode_effort.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/encode_effort.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/encode_tile.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/quantise.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/quantise.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/write_coefficients.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/write_coefficients.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/write_lr.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/write_lr.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/write_transform_type.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/encode/write_transform_type.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/entropy/CdfContext.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/entropy/CdfContext.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/entropy/SymbolReader.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/entropy/SymbolReader.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/entropy/SymbolWriter.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/entropy/SymbolWriter.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/entropy/coefficient_context.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/entropy/coefficient_context.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/entropy/partition_cdf.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/entropy/partition_cdf.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/entropy/symbol_cost.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/entropy/symbol_cost.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/filter/cdef.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/filter/loop_filter.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/filter/loop_restoration.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/filter/superres.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/grain/FilmGrainState.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/grain/FilmGrainState.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/grain/film_grain.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/FrameHeader.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/FrameHeader.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/ObuHeader.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/ObuHeader.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/SequenceHeader.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/SequenceHeader.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/for_each_obu.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/for_each_obu.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/parse_frame_header.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/parse_obu_header.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/parse_obu_header.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/parse_sequence_header.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/parse_sequence_header.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/write_frame_header.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/write_frame_header.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/write_sequence_header.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/obu/write_sequence_header.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/predict/IntraPredictionState.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/predict/IntraPredictionState.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/predict/intra_filter_type.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/predict/intra_filter_type.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/predict/predict_chroma_from_luma.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/predict/predict_intra.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/predict/predict_palette.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/predict/predict_palette.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/av1_symbols.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/block_tables.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/cdf_tables.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/coefficient_tables.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/derived_block_tables.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/derived_block_tables.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/filter_tables.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/grain_tables.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/prediction_tables.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/quantizer_matrix_tables.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/quantizer_tables.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/scan_tables.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/segmentation_tables.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/transform_tables.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/tables/unpack_table.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/transform/forward_transform_2d.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/transform/forward_transform_2d.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/transform/inverse_transform_1d.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/transform/inverse_transform_2d.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/util/ceil_log2.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/util/ceil_log2.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/util/round2.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/util/round2.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/util/round2_signed.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/util/round2_signed.js +0 -0
- /package/src/{avif/native → format/image/avif}/av1/util/tile_log2.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/av1/util/tile_log2.js +0 -0
- /package/src/{avif/native → format/image/avif}/bitstream/BitReader.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/bitstream/BitReader.js +0 -0
- /package/src/{avif/native → format/image/avif}/bitstream/BitWriter.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/bitstream/BitWriter.js +0 -0
- /package/src/{avif/native → format/image/avif}/color/ColourTransform.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/color/ColourTransform.js +0 -0
- /package/src/{avif/native → format/image/avif}/color/YuvImage.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/color/YuvImage.js +0 -0
- /package/src/{avif/native → format/image/avif}/color/clamp_sample.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/color/clamp_sample.js +0 -0
- /package/src/{avif/native → format/image/avif}/color/linear_to_transfer.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/color/primaries.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/color/primaries.js +0 -0
- /package/src/{avif/native → format/image/avif}/color/rgb_row_to_ycbcr.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/color/rgb_row_to_ycbcr.js +0 -0
- /package/src/{avif/native → format/image/avif}/color/transfer_to_linear.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/color/upsample_chroma_row.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/color/ycbcr_row_to_rgb.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/heif/AvifFile.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/heif/AvifFile.js +0 -0
- /package/src/{avif/native → format/image/avif}/heif/ItemProperty.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/heif/ItemProperty.js +0 -0
- /package/src/{avif/native → format/image/avif}/heif/find_item_property.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/heif/find_item_property.js +0 -0
- /package/src/{avif/native → format/image/avif}/heif/find_item_references.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/heif/find_item_references.js +0 -0
- /package/src/{avif/native → format/image/avif}/heif/find_items_referencing.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/heif/find_items_referencing.js +0 -0
- /package/src/{avif/native → format/image/avif}/heif/parse_avif_file.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/heif/parse_image_grid.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/heif/parse_item_property.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/heif/parse_item_property.js +0 -0
- /package/src/{avif/native → format/image/avif}/heif/read_item_data.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/heif/read_item_data.js +0 -0
- /package/src/{avif/native → format/image/avif}/heif/write_avif_file.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/heif/write_avif_file.js +0 -0
- /package/src/{avif/native → format/image/avif}/heif/write_item_property.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/heif/write_item_property.js +0 -0
- /package/src/{avif/native → format/image/avif}/isobmff/BoxHeader.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/isobmff/BoxHeader.js +0 -0
- /package/src/{avif/native → format/image/avif}/isobmff/for_each_box.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/isobmff/for_each_box.js +0 -0
- /package/src/{avif/native → format/image/avif}/isobmff/read_box_header.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/isobmff/read_box_header.js +0 -0
- /package/src/{avif/native → format/image/avif}/isobmff/read_full_box_header.d.ts +0 -0
- /package/src/{avif/native → format/image/avif}/isobmff/read_full_box_header.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/JpegFrame.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/JpegFrame.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/JpegFrameComponent.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/JpegFrameComponent.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/JpegImage.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/NOTES.md +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/buildComponentData.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/buildComponentData.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/buildHuffmanTable.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/buildHuffmanTable.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/decodeScan.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/decodeScan.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/idct8x8_float.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/jpeg_component_row.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/jpeg_component_row.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/jpeg_decode.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/jpeg/jpeg_decode.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/PNG.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/PNG.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/PNG_HEADER_BYTES.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/PNG_HEADER_BYTES.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/chunk/png_chunk_decode_iTXt.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/chunk/png_chunk_decode_zTXt.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/filter/png_filter_unFilterAverage.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/filter/png_filter_unFilterAverage.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/filter/png_filter_unFilterNone.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/filter/png_filter_unFilterNone.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/filter/png_filter_unFilterPaeth.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/filter/png_filter_unFilterPaeth.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/filter/png_filter_unFilterSub.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/filter/png_filter_unFilterSub.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/filter/png_filter_unFilterUp.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/filter/png_filter_unFilterUp.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/filter/png_unfilter.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/png_inflate.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/png_inflate.js +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/png_unpack_samples.d.ts +0 -0
- /package/src/{engine/asset/loaders → format}/image/png/png_unpack_samples.js +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/GLTF_PRIMITIVE_MODE.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/GLTF_PRIMITIVE_MODE.js +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/coalesce_array_duplicates.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/coalesce_array_duplicates.js +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/ext/GltfBufferViewExtension.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/ext/GltfBufferViewExtension.js +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/ext/GltfBufferViewExtensionSet.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/ext/gltf_apply_buffer_view_extensions.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/ext/gltf_apply_buffer_view_extensions.js +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/ext/gltf_buffer_view_extensions.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/ext/gltf_buffer_view_extensions.js +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/ext/gltf_geometry_extensions.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/ext/gltf_geometry_extensions.js +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/ext/meshopt/MeshoptBufferViewExtension.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/gltf_component_type.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/gltf_component_type.js +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/gltf_node_world_matrices.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/gltf_parse_container.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/gltf_parse_container.js +0 -0
- /package/src/{shade/renderer/loader → format/scene}/gltf/gltf_read_accessor.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/usd/UsdError.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/usd/UsdError.js +0 -0
- /package/src/{shade/renderer/loader → format/scene}/usd/parse_usda.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/usd/parse_usda.js +0 -0
- /package/src/{shade/renderer/loader → format/scene}/usd/unpack_usdz.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/usd/usd_compose_transform.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/usd/usd_lz4.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/usd/usd_triangulate.d.ts +0 -0
- /package/src/{shade/renderer/loader → format/scene}/usd/usd_triangulate.js +0 -0
- /package/src/{basis → format/texture/basis}/BasisHuffmanTable.d.ts +0 -0
- /package/src/{basis → format/texture/basis}/BasisHuffmanTable.js +0 -0
- /package/src/{basis → format/texture/basis}/basis_read_huffman_table.d.ts +0 -0
- /package/src/{basis → format/texture/basis}/basis_read_huffman_table.js +0 -0
- /package/src/{basis → format/texture/basis}/etc1s/Etc1sSelectorHistory.d.ts +0 -0
- /package/src/{basis → format/texture/basis}/etc1s/Etc1sSelectorHistory.js +0 -0
- /package/src/{basis → format/texture/basis}/etc1s/etc1s_block_colors.d.ts +0 -0
- /package/src/{basis → format/texture/basis}/etc1s/etc1s_block_colors.js +0 -0
- /package/src/{basis → format/texture/basis}/etc1s/etc1s_decode_slice.d.ts +0 -0
- /package/src/{basis → format/texture/basis}/etc1s/etc1s_read_endpoint_codebook.d.ts +0 -0
- /package/src/{basis → format/texture/basis}/etc1s/etc1s_read_endpoint_codebook.js +0 -0
- /package/src/{basis → format/texture/basis}/etc1s/etc1s_read_selector_codebook.d.ts +0 -0
- /package/src/{basis → format/texture/basis}/etc1s/etc1s_read_selector_codebook.js +0 -0
- /package/src/{basis → format/texture/basis}/etc1s/etc1s_read_slice_tables.d.ts +0 -0
- /package/src/{basis → format/texture/basis}/etc1s/etc1s_read_slice_tables.js +0 -0
- /package/src/{basis → format/texture/basis}/transcode/build_range_plan.js +0 -0
- /package/src/{basis → format/texture/basis}/transcode/etc1s_to_bc7.js +0 -0
- /package/src/{ktx2 → format/texture/ktx2}/KTX2_IDENTIFIER.d.ts +0 -0
- /package/src/{ktx2 → format/texture/ktx2}/KTX2_IDENTIFIER.js +0 -0
- /package/src/{ktx2 → format/texture/ktx2}/KhrDfModel.d.ts +0 -0
- /package/src/{ktx2 → format/texture/ktx2}/KhrDfModel.js +0 -0
- /package/src/{ktx2 → format/texture/ktx2}/SupercompressionScheme.d.ts +0 -0
- /package/src/{ktx2 → format/texture/ktx2}/SupercompressionScheme.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Block-compressed textures — implementation plan
|
|
2
2
|
|
|
3
|
-
**Status:** proposal — revision
|
|
3
|
+
**Status:** proposal — revision 6
|
|
4
4
|
**Date:** 2026-09-01
|
|
5
5
|
**Author:** Alex Goldring / Company Named Limited
|
|
6
6
|
**Scope:** `src/shade/renderer/texture/`, `src/shade/descriptor/texture/format/`,
|
|
@@ -30,6 +30,11 @@
|
|
|
30
30
|
> memoised (§11.2), `alpha_mode` needed a third state or it would premultiply every data texture
|
|
31
31
|
> (§11.3), the uploader could not see the flag it was told to honour (§11.4), per-format resolution
|
|
32
32
|
> needs a manifest (§11.5), plus corrections of fact (§11.6). §0's central move survived all six.
|
|
33
|
+
>
|
|
34
|
+
> **Revision 6** adds step 11, the GPU block encoder of §4.5 (§9.20), and corrects §4.4's item 2: a
|
|
35
|
+
> copy of a block-compressed level is sized in whole blocks against its physical extent, which the
|
|
36
|
+
> first real `copyBufferToTexture` found and which `texture_write_level` had been getting wrong on
|
|
37
|
+
> hardware since step 3.
|
|
33
38
|
|
|
34
39
|
Assumes the payload is already an `ArrayBuffer` in JS memory. Fetching is not discussed, except in
|
|
35
40
|
§5, where *which* bytes to fetch is the whole point.
|
|
@@ -139,7 +144,7 @@ shade/device/mock/
|
|
|
139
144
|
|
|
140
145
|
Container readers (KTX2, DDS, whatever ships next) are **not** engine code in this list: each is a
|
|
141
146
|
free function `bytes -> ShadeTexelData` living with its container, the way
|
|
142
|
-
[`GltfBufferViewExtension`](
|
|
147
|
+
[`GltfBufferViewExtension`](../../../format/scene/gltf/ext/GltfBufferViewExtension.js) keeps meshopt out of the
|
|
143
148
|
glTF parser. The engine names no container. Transcoders (§4) are likewise their own tree.
|
|
144
149
|
|
|
145
150
|
### 2.1 `TextureFormat` — and the load-time globals underneath it
|
|
@@ -560,6 +565,12 @@ compressed: an uncompressed procedural texture takes the same route.
|
|
|
560
565
|
|
|
561
566
|
### 4.5 Runtime compression, later
|
|
562
567
|
|
|
568
|
+
> **Landed 2026-09-02, as step 11** — [`texture_encode`](encode/texture_encode.js), with BC4 as the
|
|
569
|
+
> first encoder and the rest refused by name; see §9.20 and
|
|
570
|
+
> [`encode/ENCODE_NOTES_2026_09_02.md`](encode/ENCODE_NOTES_2026_09_02.md). Everything below held,
|
|
571
|
+
> with one correction: the copy extent for a partial mip is the level's *physical* size, rounded up to
|
|
572
|
+
> whole blocks, not its logical one.
|
|
573
|
+
|
|
563
574
|
Not being built now. Recorded because the seam either admits it or does not, and it costs nothing to
|
|
564
575
|
make sure it does.
|
|
565
576
|
|
|
@@ -808,7 +819,7 @@ right granularity for that.
|
|
|
808
819
|
- **On-GPU BC/ASTC encoders** — the shader behind §4.5.
|
|
809
820
|
- **The offline encoder.** First-party content has to be compressed by something, and that something
|
|
810
821
|
is a tool, not the engine. It belongs beside the AVIF encoder
|
|
811
|
-
([`avif/threaded_image_encoder.js`](../../../avif/threaded_image_encoder.js)), reusing its worker
|
|
822
|
+
([`avif/threaded_image_encoder.js`](../../../engine/asset/loaders/image/avif/threaded_image_encoder.js)), reusing its worker
|
|
812
823
|
pool. Mips are generated *before* compression, from the source texels, with the same filters
|
|
813
824
|
[`mipmaps/filters/`](mipmaps/filters) uses — compressing level 0 and decompressing it to build
|
|
814
825
|
level 1 is how a pyramid rots.
|
|
@@ -830,9 +841,17 @@ Each step is independently committable and leaves the engine working.
|
|
|
830
841
|
| 5 | **Landed.** `writeTexture` delegates to `texture_copy` (§6.3, §9.6). A BC7 texture now goes end to end with no GPU. | test tier only |
|
|
831
842
|
| 6 | **Landed.** Device features, `gpu_texture_compression_support`, `TextureRole`, `texture_format_preference`; §6.2 and §6.4 guards (§3.5, §9.7) | none until a compressed texture exists |
|
|
832
843
|
| 7 | **Landed.** `TextureVariantSet` (the manifest) and `texture_variant_select`; **not** in `AssetManager` (§5.1, §9.9) | additive — an unbuilt format falls through to the fallback, and nothing consumes this until step 8 |
|
|
833
|
-
| 8 | **Landed.** KTX2 reader in [`src/ktx2/`](../../../ktx2/ktx2_read.js) — container to `ShadeTexelData`, for files already in a device format; ZLIB supercompression read rather than refused (§9.10) | additive — nothing imports it yet, and nothing existing changed except the cursor it reuses |
|
|
834
|
-
| 9 | CPU Basis transcoder (
|
|
835
|
-
|
|
|
844
|
+
| 8 | **Landed.** KTX2 reader in [`src/ktx2/`](../../../format/texture/ktx2/ktx2_read.js) — container to `ShadeTexelData`, for files already in a device format; ZLIB supercompression read rather than refused (§9.10) | additive — nothing imports it yet, and nothing existing changed except the cursor it reuses |
|
|
845
|
+
| 9 | **Landed.** CPU Basis transcoder in [`src/basis/`](../../../format/texture/basis/transcode_basis.js) — ETC1S to BC7 and BC1, implemented from the specification; `ktx2_read` accepts BasisLZ; `KHR_texture_basisu` read at both glTF sites (§4.3, §9.11) | the expensive one, and sequenced last deliberately |
|
|
846
|
+
| 9b | **Landed.** UASTC to BC7 and BC5 — the other Basis encoding, and the one normal maps use; every UASTC mode carried into the BC7 mode the specification pairs it with, partitions included; the glTF loader picks a target from the material slot, so a normal map reaches BC5; Zstandard read from RFC 8878, which is what real UASTC is wrapped in (§9.12) | additive, and within a few tenths of a decibel of the reference transcoder on every fixture |
|
|
847
|
+
| 9c | **Landed.** [`playground/basis_textures`](../../playground/basis_textures/README.md) — tier 8, and the first GPU to see any of this. Sponza at **4.00x** less texture memory, 69/69 textures accepted. Found the `GenerateMipMaps` refusal and the cumulative-total misreading (§9.13) | fixes one real defect in `load_gltf`; the playground itself is additive |
|
|
848
|
+
| 9d | **Landed.** `rgba8unorm` from both transcoders, and the glTF loader falls to it when the device can sample no compressed target — closing §9.13's refusal. ETC1S's uncompressed output is byte-exact against the reference (§9.15) | removes a refusal; costs 4x the memory, and only where there was no texture before |
|
|
849
|
+
| 9e | **Landed.** ETC1S to ETC2, byte-exact against the reference; EAC alpha fitted. `ktx2_read` takes an ordered target list so alpha can decide. **ASTC written and removed** — the layout was derived but the interpolation could not be verified and no ASTC device was reachable (§9.16) | additive; the target-list change also fixes a live BC1 hazard |
|
|
850
|
+
| 9f | **Landed.** ETC1S to ASTC 4x4, from the specification: exact interpolation, the CEM 8 endpoint ordering rule, placement search and endpoint refinement. **48.81 dB against the reference's 48.28** (§9.17), and §9.16's removal is retracted | additive; ASTC leads every role's preference where the device has it |
|
|
851
|
+
| 9g | **Landed.** The ordered target list falls through on *encoding* as well as alpha — an ASTC-first device went from 24 failures on Sponza to none. **UASTC to ASTC measured and declined**: 34.9 dB on real normal maps against an exact floor (§9.18) | bug fix; the decline leaves UASTC on the floor where it already was |
|
|
852
|
+
| 9h | **Landed.** UASTC to ASTC by repack — partition seeds searched, trit/quint packings inverted from the spec's decode, block modes assembled from the layout. Byte-identical to the reference on 2320 of 2352 blocks and provably equivalent on the rest. **Mobile reaches desktop parity: 173.1 -> 83.8 MiB** (§9.19) | additive; closes the last gap for third-party UASTC content |
|
|
853
|
+
| 10 | GPU transcoder (§4.4) — Basis payload to BC on the device | an optimization of step 9, not a prerequisite |
|
|
854
|
+
| 11 | **Landed, in part.** GPU block encoder (§4.5) — any sampleable texture to a named block format, on the device: the framework, the padded layout, the per-level copies, the format registry and the test harness, carried by `bc4-r-unorm`, then `bc5-rg-unorm`, `bc1-rgba-unorm`, `bc7-rgba-unorm` in mode 6, the two signed formats, `bc6h-rgb-ufloat` in mode 11 and `astc-4x4-unorm` in the one-partition block of step 9f; the engine's first real `copyBufferToTexture`. Found `texture_write_level` refusing every BC chain's tail on hardware since step 3, and fixed it (§9.20) | additive; `astc-6x6` and `astc-8x8` are refused by name until each lands |
|
|
836
855
|
|
|
837
856
|
Steps 1–6 introduce **no new capability and no new branch** — they are the refactor that makes
|
|
838
857
|
everything after them a data change rather than a second code path. If the project stops after step
|
|
@@ -881,9 +900,868 @@ recompute it.
|
|
|
881
900
|
had no `mipLevelCount` or `dimension`; every real one has both, and the primitive reads them. The
|
|
882
901
|
fake was wrong, not the test.
|
|
883
902
|
|
|
903
|
+
### 9.20 The GPU block encoder, and what the first real `copyBufferToTexture` found
|
|
904
|
+
|
|
905
|
+
§4.5 said runtime compression was "the same shape as §4.4 with a different shader" and that
|
|
906
|
+
everything in §4.4's numbered list applied unchanged. It is, and it did — with one item of that list
|
|
907
|
+
wrong in a way only a device could show, and one older step wrong the same way.
|
|
908
|
+
|
|
909
|
+
**What landed.** [`texture_encode`](encode/texture_encode.js): a sampleable texture in, a
|
|
910
|
+
block-compressed texture out, the target named by the caller and nothing else known — not the role,
|
|
911
|
+
not the preference list, not the material. One compute dispatch over every level of the chain, one
|
|
912
|
+
`copyBufferToTexture` per level, the block buffer laid out with 256-byte rows by
|
|
913
|
+
[`texture_encode_layout`](encode/texture_encode_layout.js) before anything runs. The shader carries no
|
|
914
|
+
immediates and no uniforms: a flat level table in a storage buffer is the whole of its parameters,
|
|
915
|
+
which is what lets one dispatch cover a chain and what lets it run on a browser build with no
|
|
916
|
+
immediate data. Fifteen targets are listed; `bc4-r-unorm` is implemented and the other fourteen are
|
|
917
|
+
refused by name, each as "planned, not implemented" rather than approximated by a neighbour.
|
|
918
|
+
|
|
919
|
+
**The encoder** is a fixed budget: extremes, two rounds of least squares, then a five-by-five search
|
|
920
|
+
of integer endpoint pairs at spacings of eight, two and one, in both of BC4's palette modes with the
|
|
921
|
+
six-value line seeded over the interior texels alone. Measured in the emulator against an exhaustive
|
|
922
|
+
search over every endpoint pair, it is within 0.5 dB on every fixture; the least-squares answer alone
|
|
923
|
+
was 3 dB short on the mask fixture, because the optimum sits in a basin no rounding of the
|
|
924
|
+
least-squares line reaches. The reading behind those choices, source by source, is in
|
|
925
|
+
[`encode/ENCODE_NOTES_2026_09_02.md`](encode/ENCODE_NOTES_2026_09_02.md).
|
|
926
|
+
|
|
927
|
+
**§4.4's item 2 was wrong.** "Origin and extent must be block multiples — trivially satisfied for a
|
|
928
|
+
whole-level copy, since the physical extent of a mip is its size rounded up to whole blocks." The
|
|
929
|
+
first half is right and the conclusion did not follow from it: a whole-level copy at the level's
|
|
930
|
+
*logical* size is not a block multiple for the 2×2 and 1×1 tail, and Dawn refuses it —
|
|
931
|
+
`copySize.width (2) is not a multiple of compressed texture format block width (4)`. The copy is
|
|
932
|
+
sized in whole blocks against the physical mip size, which
|
|
933
|
+
[`gpu_texture_format_physical_size`](../../descriptor/texture/format/gpu_texture_format_info.js) now
|
|
934
|
+
states in one place. The software device had implemented Vulkan's allowance instead — a partial
|
|
935
|
+
extent is fine where it reaches the edge — and so could not have caught it; it now implements
|
|
936
|
+
WebGPU's rule, refuses a compressed texture whose base size is not whole blocks, requires the
|
|
937
|
+
compression feature a block format needs, and validates a copy's row stride, offset and view formats.
|
|
938
|
+
|
|
939
|
+
**Which means step 3 had been failing on hardware all along.** `texture_write_level` wrote every
|
|
940
|
+
level at its logical extent, so `writeTexture` of a BC chain's last two levels was refused on every
|
|
941
|
+
device — silently, since a validation error does not throw, and §9.13's "69 of 69 accepted" counted
|
|
942
|
+
exceptions. Its spec asserted `[1, 1, 1]` for the 1×1 mip of a BC7 texture and passed. Fixed: the
|
|
943
|
+
extent is the physical size, the spec asserts `[4, 4, 1]`, and the stricter software device would
|
|
944
|
+
fail the old code.
|
|
945
|
+
|
|
946
|
+
**What the device said about the picture.** 2048² with twelve levels, 349,527 blocks, in 8.6 ms
|
|
947
|
+
wall from record to done; every level's blocks read back from the texture identical to the buffer;
|
|
948
|
+
the device choosing the same block as the f64 emulator on 83% of blocks and a block of equal error on
|
|
949
|
+
almost all the rest. And the hardware's BC4 decoder, read at full precision over every endpoint pair,
|
|
950
|
+
is not the specification's arithmetic: a palette entry is `A + (B − A) · c / 257` over 16-bit
|
|
951
|
+
endpoints with `c = 36, 72, 113, 144, 185, 221` for the eight-value mode and `48, 96, 161, 209` for
|
|
952
|
+
the six — within a level of the CPU decoder on 85% of entries and up to seven off on the widest
|
|
953
|
+
six-value spans, which on real content is 0.6 dB between what the specification decoder predicts and
|
|
954
|
+
what the GPU shows. The encoder keeps fitting against the specification's palette: a vendor's weights
|
|
955
|
+
would be wrong on the next vendor.
|
|
956
|
+
|
|
957
|
+
**Then BC5 and BC1.** BC5 is the BC4 chunk twice, red then green, and the kernel spec holds it to
|
|
958
|
+
exactly that: each level's blocks must equal the BC4 encoder over the red channel followed by the
|
|
959
|
+
BC4 encoder over the green, block for block. BC1 is the RGB line fit BC7 builds on — principal axis
|
|
960
|
+
by power iteration from the box diagonal, least squares with the thirds shared across channels,
|
|
961
|
+
5:6:5 quantisation and coordinate descent against the decoder's truncated palette, with a flat
|
|
962
|
+
block's stored pair searched per channel for the one-third mix nearest its colour. Measured in the
|
|
963
|
+
emulator: 40.3 dB on a correlated colour fixture and 30.6 on three unrelated channels, against 25.3
|
|
964
|
+
and 24.3 for the 2007 inset bounding box; BC5 38.0 dB on a rough heightfield's normal map. On the
|
|
965
|
+
device: BC1 41.5 dB on the correlated source with the hardware decode within 0.02 dB of the CPU
|
|
966
|
+
decoder's, BC5 45.2 dB, both texture-equals-buffer on every level, and the device choosing the
|
|
967
|
+
emulator's BC1 block on 16,380 of 16,384. One thing the emulator taught: it aliases a vector on
|
|
968
|
+
assignment, so writing one component of a copy changed the original and broke both BC1 searches
|
|
969
|
+
silently; the chunk now builds the altered vector through `select`, which means the same on both.
|
|
970
|
+
|
|
971
|
+
**Then BC7, mode 6.** The same fit in four dimensions with sixteen points on the line and
|
|
972
|
+
eight-bit ends: the parity bit each end carries is chosen by rounding to all four combinations and
|
|
973
|
+
scoring each against the decoder's own palette, and the anchor is honoured by writing a block the
|
|
974
|
+
other way up when texel 0 lands in the upper half. The pack is held byte for byte against
|
|
975
|
+
`bc7_write_block`, the writer the transcoders use. 44.9 dB on correlated colour in the emulator,
|
|
976
|
+
3.6 dB over BC1 on the channels they share; and on the device the cleanest result of the day — the
|
|
977
|
+
hardware decode identical to the CPU decoder on every sample of every level, because BC7's
|
|
978
|
+
interpolation is fully specified where BC4's is not. 46.0 dB at 512², 8.2 ms for a 2048² chain.
|
|
979
|
+
Mode 6 alone; the partitioned modes are where the rest of BC7's quality is, and a mode search is a
|
|
980
|
+
separate chunk for a later day.
|
|
981
|
+
|
|
982
|
+
**Then the signed formats**, which the brief called a path and not a tag, and which turned out to
|
|
983
|
+
be a domain: the BC4 fit takes its bounds as arguments and the signed entry point calls it over
|
|
984
|
+
`[-127, 127]` with the six-value mode's hard entries at the extremes, the pack taking the two's
|
|
985
|
+
complement. Two shaders, no new fitting code. On the device, a normal map as signed bytes encodes
|
|
986
|
+
to `bc5-rg-snorm` at exactly the unsigned figure less the 6.02 dB a halved peak costs, which is
|
|
987
|
+
what "the same fit" has to come out as.
|
|
988
|
+
|
|
989
|
+
**Then BC6H, mode 11.** The same line fitted in the half-float bit domain, because that is where
|
|
990
|
+
the format's decoder interpolates: an endpoint is a half's bit pattern quantised to ten bits, and
|
|
991
|
+
the palette is linear in bit patterns — a log-like scale, so the error the fit minimises is a
|
|
992
|
+
relative one. 45.1 dB over half bits and 0.078 stops RMS log error on an HDR fixture spanning
|
|
993
|
+
fourteen stops with a sun; on the device the hardware decode identical to the CPU decoder on every
|
|
994
|
+
sample of every level, which the format requires of a decoder and this was the first chance to see.
|
|
995
|
+
Mode 11 alone: a block holding the sun and its surround wants the two-region modes.
|
|
996
|
+
|
|
997
|
+
**Then ASTC 4×4**, in the one corner of the format §9.17 derived and §9.19 repacked into: block
|
|
998
|
+
mode `0x53`, one partition, colour endpoint mode 8, eight-bit ends and three-bit weights — the BC1
|
|
999
|
+
line under ASTC's own interpolation and its endpoint-order rule, both of which cost a level if
|
|
1000
|
+
ignored and both of which those steps already had in JavaScript. 43.3 dB on correlated colour in
|
|
1001
|
+
the emulator, between BC1 and BC7 mode 6 as eight levels over eight-bit ends should be. Not seen on
|
|
1002
|
+
hardware: nothing in reach samples ASTC, and the section says so rather than implying otherwise.
|
|
1003
|
+
The 6×6 and 8×8 footprints wait on block modes and partition seeds the tree does not hold.
|
|
1004
|
+
|
|
1005
|
+
**Testing, and the discipline §9.11 set.** The block layout is written twice, in JavaScript under
|
|
1006
|
+
`format/texture/bc/` — which the UASTC→BC5 and ETC1S→BC1 transcoders now pack through — and in
|
|
1007
|
+
WGSL, and the emulator specs require the same bytes from both five hundred times over. The kernel's per-level
|
|
1008
|
+
output must equal the encoder run directly over each level's image, byte for byte. Quality floors are
|
|
1009
|
+
in the spec, from measurement: 51.5, 42 and 54 dB on the three fixtures, and the fit must strictly
|
|
1010
|
+
beat the bounding line it starts from, which is the guard against the refinement's absence. On the
|
|
1011
|
+
software device the copies execute over host-written bytes, so the padded layout landing as tight
|
|
1012
|
+
rows in the right mip is asserted without a shader. Full suite: 15,583 passed.
|
|
1013
|
+
|
|
1014
|
+
### 9.19 UASTC to ASTC, repacked — mobile reaches parity
|
|
1015
|
+
|
|
1016
|
+
§9.18 declined a *re-encode* at 34.9 dB and costed the repack. This is the repack, and it lands where
|
|
1017
|
+
the format intended: **mobile now costs exactly what desktop costs**.
|
|
1018
|
+
|
|
1019
|
+
| Sponza | before | after |
|
|
1020
|
+
|---|---|---|
|
|
1021
|
+
| desktop (BC) | 83.8 MiB | 83.8 MiB |
|
|
1022
|
+
| mobile (ASTC + ETC2, no BC) | 173.1 MiB | **83.8 MiB** |
|
|
1023
|
+
|
|
1024
|
+
The 24 UASTC normal maps that were falling to the uncompressed floor are now `astc-4x4-unorm`, and
|
|
1025
|
+
the scene is 66 ASTC plus 3 ETC2 for the textures with alpha.
|
|
1026
|
+
|
|
1027
|
+
**Nothing is fitted and nothing is lost.** UASTC's fields *are* ASTC's fields — endpoints already
|
|
1028
|
+
quantized at a range ASTC names, weights already ASTC weights, patterns taken from ASTC's own hash.
|
|
1029
|
+
The work is arithmetic on bit positions: ASTC interleaves its integer sequences where UASTC keeps
|
|
1030
|
+
them in two plain runs, and puts its weights at the top of the block in reverse.
|
|
1031
|
+
|
|
1032
|
+
**Verified by byte equality with the reference transcoder, which a re-encode could never be.**
|
|
1033
|
+
|
|
1034
|
+
| fixture | identical | equivalent | different |
|
|
1035
|
+
|---|---|---|---|
|
|
1036
|
+
| `uastc_gradient_64x64` | 256 | 0 | 0 |
|
|
1037
|
+
| `uastc_partitions_32x24` | 48 | 0 | 0 |
|
|
1038
|
+
| `uastc_subsets_128x128` | 1016 | 8 | 0 |
|
|
1039
|
+
| `uastc_zoo_128x128` | 1000 | 24 | 0 |
|
|
1040
|
+
|
|
1041
|
+
"Equivalent" is not a hedge. ASTC's integer sequence encoding is *redundant* — 256 packed trit groups
|
|
1042
|
+
carry 243 tuples and 128 quint groups carry 125 — so two correct encoders can differ bit for bit. The
|
|
1043
|
+
32 such blocks are required to decode to identical endpoint values, and do; the spec reads both
|
|
1044
|
+
sequences back rather than accepting the difference.
|
|
1045
|
+
|
|
1046
|
+
**Three things were derived rather than copied**, and each is checked by its own failure mode:
|
|
1047
|
+
|
|
1048
|
+
- **The partition seeds.** ASTC computes patterns from a ten-bit seed through a hash rather than
|
|
1049
|
+
storing them, so UASTC's pattern indices have to be matched to seeds. The reference has that table;
|
|
1050
|
+
this searches all 1024 seeds for one whose grouping agrees texel for texel. All 60 patterns across
|
|
1051
|
+
the three tables resolve — which a wrong hash could not do — and dropping the small-block coordinate
|
|
1052
|
+
doubling fails five tests.
|
|
1053
|
+
- **The trit and quint packings.** The specification gives the decode only, saying outright that
|
|
1054
|
+
encoding is the implementation's business. So the decode is written and inverted by enumeration:
|
|
1055
|
+
256 groups yield exactly 243 distinct trit tuples and 128 yield exactly 125 quint tuples, which is
|
|
1056
|
+
the check that the decode is right.
|
|
1057
|
+
- **The block modes.** Assembled from the layout — `D` at bit 10, `H` at 9, height at 8:7, width at
|
|
1058
|
+
6:5, `R0` at 4, `R2` and `R1` at 1:0 — rather than tabulated. Swapping `R1` and `R2` fails four
|
|
1059
|
+
tests.
|
|
1060
|
+
|
|
1061
|
+
**Two rules with no flag, both caught by the byte comparison.** Endpoint modes 8 and 12 swap their
|
|
1062
|
+
pair and blue-contract when the second endpoint's channel sum falls below the first's, and UASTC
|
|
1063
|
+
orders its endpoints for BC7's rules instead — so a subset that would trip it has its pair exchanged
|
|
1064
|
+
and its weights inverted, which is the same block the other way up. And a void-extent block's bits 10
|
|
1065
|
+
and 11 are reserved and set; leaving them clear produced solid blocks that differed from the
|
|
1066
|
+
reference in nothing else.
|
|
1067
|
+
|
|
1068
|
+
**One thing that cannot be tested and is kept anyway.** A seed found by search need only *group* the
|
|
1069
|
+
texels as UASTC does; which group it calls subset 0 is the hash's business, and an encoder would in
|
|
1070
|
+
general have to reorder its endpoint pairs. No UASTC pattern actually needs it — all 60 come back as
|
|
1071
|
+
the identity, which follows from UASTC having taken its patterns from ASTC. Rather than carry
|
|
1072
|
+
reordering code that never runs and therefore is never right, the identity is asserted and a
|
|
1073
|
+
violation refused. Removing that assertion fails nothing, and the file says so.
|
|
1074
|
+
|
|
1075
|
+
**Still not written:** ETC2 from UASTC. An ETC2-capable device without ASTC would take the floor for
|
|
1076
|
+
UASTC content — a population the availability figures suggest is close to empty, since the two
|
|
1077
|
+
features report 29% and 30% with identical per-browser splits.
|
|
1078
|
+
|
|
1079
|
+
#### What the adversarial pass over §9.19 found
|
|
1080
|
+
|
|
1081
|
+
**Five of nineteen modes were never decoded by any fixture** — 5, 10, 15, 16 and 18. Everything the
|
|
1082
|
+
repack claims is per-mode, so those were untested bit layouts that happened to compile. Mode 18 was
|
|
1083
|
+
the one that mattered: the only user of the 32-level weight range *and* the 32-level endpoint range,
|
|
1084
|
+
and the tightest budget of any mode at 127 bits of 128.
|
|
1085
|
+
|
|
1086
|
+
Three fixtures were built to reach them, by giving `basisu` content shaped for the modes rather than
|
|
1087
|
+
for the eye: a luminance ramp with noise (15), a high-precision colour and alpha field (5, 10), and a
|
|
1088
|
+
single long smooth ramp at encoder level 4 (18). Coverage is now 18 of 19, and misreading mode 18's
|
|
1089
|
+
weight range now fails a test where it used to pass. **Mode 16 — two-subset luminance — remains
|
|
1090
|
+
unreached**: pure greyscale with a hard split inside every block, at every encoder level, produced
|
|
1091
|
+
single-subset modes every time. That is asserted as a known gap rather than left implicit, so a
|
|
1092
|
+
future fixture that happens to contain it will fail and shorten the list.
|
|
1093
|
+
|
|
1094
|
+
**A bit-budget scare that turned out to be sound.** Counting header, endpoints and weights suggested
|
|
1095
|
+
five modes overrun 128 bits — and four of those are in the fixtures and match the reference byte for
|
|
1096
|
+
byte. The size arithmetic was wrong, not the encoder: ASTC charges a partial trailing group only the
|
|
1097
|
+
bits it needs, where the naive count charges a whole one. The writer pads such a group with zeros and
|
|
1098
|
+
formally advances its cursor past where the weights begin, which raised the real question of whether
|
|
1099
|
+
a padded group's high bits could ever land in the weight field. Swept exhaustively over every mode
|
|
1100
|
+
and every value of every trailing group: they cannot, because zero digits give zero high bits. The
|
|
1101
|
+
unused size helper that started the scare is gone, with a note where it stood.
|
|
1102
|
+
|
|
1103
|
+
**Two pieces of dead logic removed.** The seed-table choice carried a `pat_bits === 4` branch and a
|
|
1104
|
+
repeated `subsets === 3` test, neither of which can be true where they were tested — no two-subset
|
|
1105
|
+
mode has four pattern bits. And the literal `7` selecting mode 7's borrowed pattern table is now the
|
|
1106
|
+
named constant the decoder already had.
|
|
1107
|
+
|
|
1108
|
+
Checked and found sound: `partition` is a full sixteen-entry array of zeros for single-subset blocks,
|
|
1109
|
+
so the per-subset weight inversion does reach them.
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
### 9.18 The list did not fall through, and UASTC to ASTC does not pay
|
|
1113
|
+
|
|
1114
|
+
Two findings from taking every Sponza texture through an ASTC-first preference, which is what a
|
|
1115
|
+
modern phone would ask for.
|
|
1116
|
+
|
|
1117
|
+
**A bug §9.16's list resolution introduced.** Handing `ktx2_read` an ordered list was meant to stop a
|
|
1118
|
+
target being committed to and then refused. It only ever filtered on *alpha*, and returned the head
|
|
1119
|
+
of the list unchanged for UASTC — so a list headed by `astc-4x4-unorm` threw on all 24 of Sponza's
|
|
1120
|
+
normal maps, because ASTC is a format ETC1S reaches and UASTC does not. The comment even said so:
|
|
1121
|
+
"UASTC carries its alpha in the block ... so its first choice always stands". It does not stand when
|
|
1122
|
+
the first choice is a format that encoding cannot write at all.
|
|
1123
|
+
|
|
1124
|
+
The resolution now filters on both, against the writing transcoder's own format list. The ASTC-first
|
|
1125
|
+
run goes from 24 failures to none: **42 ASTC, 3 ETC2 for the alpha textures, 24 falling to the
|
|
1126
|
+
uncompressed floor**.
|
|
1127
|
+
|
|
1128
|
+
**Why those 24 stay on the floor: UASTC to ASTC was written, measured, and not shipped.** Not for the
|
|
1129
|
+
reasons §9.16 gave — this time the measurement is sound and it says the approach is wrong.
|
|
1130
|
+
|
|
1131
|
+
Decoding a UASTC block to texels and fitting one ASTC partition to them gives, over Sponza's 24
|
|
1132
|
+
normal maps, **34.9 dB mean with a worst channel error of 140**. That is not a fitting failure. The
|
|
1133
|
+
adversarial block is legible: a 4x4 where red and blue vary along x while green varies along y — two
|
|
1134
|
+
independent gradients, which a single pair of endpoints and one weight plane cannot represent at any
|
|
1135
|
+
precision. Normal maps are made of exactly that, which is why `texture_format_preference` leads with
|
|
1136
|
+
`bc5-rg-unorm` for the role and why UASTC itself spends dual-plane and multi-subset modes on 46% of
|
|
1137
|
+
the blocks in the zoo fixture.
|
|
1138
|
+
|
|
1139
|
+
So the trade on offer was a quarter of the memory for a visibly wrong normal, against an uncompressed
|
|
1140
|
+
floor that is exact. Taken on those terms it is a regression, and the floor wins.
|
|
1141
|
+
|
|
1142
|
+
**What the real path costs.** UASTC's modes were laid out to map onto ASTC's, endpoints and weights
|
|
1143
|
+
already in ASTC's quantized space — a repack that loses nothing. Reaching it needs three things this
|
|
1144
|
+
tree does not have: the full block-mode table rather than the two single-plane 4x4 rows in
|
|
1145
|
+
`astc_block.js`, integer sequence encoding for endpoints and weights at trit and quint ranges, and
|
|
1146
|
+
ASTC's partition-seed function. Dual plane alone would fix the block above, and does not fit at eight
|
|
1147
|
+
bits an endpoint: 64 weight bits and two selector bits leave 45, so it needs the endpoint
|
|
1148
|
+
quantization too. That is the next piece of work, and it is a real one.
|
|
1149
|
+
|
|
1150
|
+
**What did land:** `astc_block.js`, holding the block mode derivation, the weight unquantization, the
|
|
1151
|
+
mode 8 endpoint ordering rule and the writer, shared by whatever encodes into it.
|
|
1152
|
+
|
|
1153
|
+
### 9.17 ASTC, finished — and what §9.16 got wrong
|
|
1154
|
+
|
|
1155
|
+
§9.16 pulled ASTC on the grounds that its decode could not be verified. **That conclusion was
|
|
1156
|
+
wrong, and wrong in a way worth recording.**
|
|
1157
|
+
|
|
1158
|
+
The measurement it rested on was this: decoding `basisu`'s own ASTC blocks and comparing against the
|
|
1159
|
+
ETC1S texels gave 748 exact, 1938 off by one, and a tail to five. That was read as *this decoder is
|
|
1160
|
+
inaccurate*. It is not what the number says. Those are the reference encoder's blocks and its
|
|
1161
|
+
endpoint choices, so the gap is **`basisu`'s ASTC encoding loss against the ETC1S source** — the
|
|
1162
|
+
lossy step everyone expects, attributed to the wrong side. The right control was never run: compare
|
|
1163
|
+
the two decode formulas against *each other* on the same blocks. They disagree on 160 samples of
|
|
1164
|
+
2928, all by one level. That is what a wrong interpolation model looks like, and five is not it.
|
|
1165
|
+
|
|
1166
|
+
With the specification in hand the remaining pieces were small.
|
|
1167
|
+
|
|
1168
|
+
**The interpolation is not the direct form.** ASTC widens each 8-bit endpoint to sixteen bits by
|
|
1169
|
+
replication, interpolates there with a `+32` round, and takes the top eight bits —
|
|
1170
|
+
`((c << 8 | c) * (64 - w) + ... + 32) / 64 >> 8`. Against `c0 + (c1 - c0) * w / 64` that is one texel
|
|
1171
|
+
in twenty, always by a level. Both the encoder's scoring and the test decoder now use the real one;
|
|
1172
|
+
fitting against one and decoding with the other would have put that disagreement into the output for
|
|
1173
|
+
nothing.
|
|
1174
|
+
|
|
1175
|
+
**Colour endpoint mode 8 has a rule about which way round the endpoints go.** With the second
|
|
1176
|
+
endpoint's channel sum below the first's, a decoder *swaps them and blue-contracts both* —
|
|
1177
|
+
`r = (r + b) >> 1`, `g = (g + b) >> 1`. That is a different picture rather than an inverted one, and
|
|
1178
|
+
no bit in the block records that it happened. §9.16 suspected this from the evidence that `basisu`
|
|
1179
|
+
never emits such a block in 61 tries, and was right to. `order_endpoints` now guarantees it, swapping
|
|
1180
|
+
the pair and inverting the weight levels, which leaves the decoded block identical where it does
|
|
1181
|
+
nothing.
|
|
1182
|
+
|
|
1183
|
+
**The block mode was already right.** `0x42` is the low-precision row `D H 0 B A R0 0 0 R2 R1` with
|
|
1184
|
+
`A = B = 2` for a 4x4 grid and `R = 4` for four weight levels on one plane — derived empirically in
|
|
1185
|
+
§9.16, confirmed against the layout table here.
|
|
1186
|
+
|
|
1187
|
+
**Quality, measured against the reference on both axes.** Over the 61 blocks `basisu` also writes
|
|
1188
|
+
single-plane it reaches 48.28 dB with a worst channel error of 4. This reaches **48.81 dB over all
|
|
1189
|
+
64**, with a worst of 5. Better on the whole and marginally worse at the peak, and the reason is
|
|
1190
|
+
visible in one block: block 12, where both encoders pick identical weights and the endpoints differ
|
|
1191
|
+
by two in one channel. This pair has the lower summed squared error and the reference's has the lower
|
|
1192
|
+
maximum. Least squares is what the fit optimises and what PSNR rewards, so the trade is deliberate.
|
|
1193
|
+
`etc1s_antidiag_64x64` comes back exact.
|
|
1194
|
+
|
|
1195
|
+
Two things earn that: the placement search from §9.16 — spreading a block's *used* selectors over all
|
|
1196
|
+
four weight levels rather than mapping them one to one, worth nine decibels — and a bounded
|
|
1197
|
+
refinement of the winning placement's endpoints, since the rounded least-squares pair is usually but
|
|
1198
|
+
not always the best integer pair once `interpolate`'s own rounding is applied.
|
|
1199
|
+
|
|
1200
|
+
**Still not written:** ETC2 and ASTC from UASTC. A UASTC normal map on a device with neither BC nor
|
|
1201
|
+
ASTC still falls to the uncompressed floor.
|
|
1202
|
+
|
|
1203
|
+
**The lesson, which is §9.11's again.** A number that looks like evidence of a bug in your own code
|
|
1204
|
+
is worth attributing before acting on it. The control that would have settled it — the two formulas
|
|
1205
|
+
against each other — costs nothing and was not run, and the cost of not running it was deleting a
|
|
1206
|
+
working encoder.
|
|
1207
|
+
|
|
1208
|
+
### 9.16 ETC2 landed; ASTC was written, could not be verified, and was removed
|
|
1209
|
+
|
|
1210
|
+
Asked for both. One shipped.
|
|
1211
|
+
|
|
1212
|
+
**ETC2 is a repack, and is checked byte for byte.** ETC1S is a constrained ETC1 and ETC1 is a subset
|
|
1213
|
+
of ETC2, so a Basis block is ETC1's differential mode with both subblocks given the same colour:
|
|
1214
|
+
deltas zero, both table codewords the block's intensity. Nothing is fitted and nothing is lost. All
|
|
1215
|
+
64 blocks of the noise fixture come out identical to `basisu -unpack`'s own ETC1 output, and the
|
|
1216
|
+
RGBA8 spelling matches its ETC2_RGBA byte for byte too. Eight bits a texel against the uncompressed
|
|
1217
|
+
floor's thirty-two, at no cost in quality at all.
|
|
1218
|
+
|
|
1219
|
+
Two things that were not free:
|
|
1220
|
+
|
|
1221
|
+
- **The selector remap.** `INTENSITY_MODIFIER` is ordered darkest to brightest and ETC1 indexes the
|
|
1222
|
+
same four modifiers as `+a, +b, -a, -b`, so a selector written through unchanged mirrors every
|
|
1223
|
+
block through its own mid-grey. `[3, 2, 0, 1]`.
|
|
1224
|
+
- **EAC's alpha block**, the only encoded part. A payload with no alpha slice is written exactly
|
|
1225
|
+
opaque through table row 13, the one row containing a zero modifier — an opaque texture has to come
|
|
1226
|
+
back 255 and not 254, and `basisu` uses the same trick, which is why those blocks match bit for bit.
|
|
1227
|
+
A real alpha slice is fitted by searching all sixteen rows against sixteen multipliers, landing at
|
|
1228
|
+
54.4 dB with a worst error of 1 against the payload's own alpha.
|
|
1229
|
+
|
|
1230
|
+
**The bug the opaque fixture hid.** EAC numbers its texels down each column like ETC1, and the first
|
|
1231
|
+
version wrote them in raster order. A constant block takes the exact path and never touches the
|
|
1232
|
+
fitter, so every opaque fixture agreed with the reference perfectly while every non-constant block was
|
|
1233
|
+
transposed — worth ten levels. The mutation pass caught it a second time after the fix, because the
|
|
1234
|
+
only ETC2 RGBA test at that point still used an opaque fixture; a test over the alpha fixture is what
|
|
1235
|
+
now holds it.
|
|
1236
|
+
|
|
1237
|
+
**ASTC: written, measured, and taken back out.** The block layout was derived empirically from the
|
|
1238
|
+
reference transcoder rather than from the specification's mode tables — block mode `0x42`, one
|
|
1239
|
+
partition, colour endpoint mode 8, six eight-bit endpoints at bit 17, thirty-two weight bits at the
|
|
1240
|
+
top of the block with the field's bit order mirrored. That much is real: decoding `basisu`'s own
|
|
1241
|
+
blocks with it reproduces the ETC1S texels. An encoder on top of it reached 47.6 dB with a
|
|
1242
|
+
placement search over which weight levels a block's used selectors take.
|
|
1243
|
+
|
|
1244
|
+
It was removed anyway, for two reasons that together make it unverifiable here:
|
|
1245
|
+
|
|
1246
|
+
1. **The interpolation model is wrong by up to five levels.** Reading the reference's blocks back
|
|
1247
|
+
gives 748 texels exact, 1938 off by one, and a tail to five. Whatever hardware does with the
|
|
1248
|
+
endpoints — expansions and shifts at some width — is not the weighted average this computes, and
|
|
1249
|
+
the encoder was fitting against the same approximation, so the error on a real device is unknown
|
|
1250
|
+
rather than bounded.
|
|
1251
|
+
2. **CEM 8 appears to carry an endpoint-swap rule this does not implement.** Across 61 reference
|
|
1252
|
+
blocks, `basisu` never once emits endpoints whose first sum exceeds the second — exactly what a
|
|
1253
|
+
swap-and-blue-contract rule would punish. This encoder could emit such a block, and the result
|
|
1254
|
+
would be wrong colours rather than slightly wrong ones.
|
|
1255
|
+
|
|
1256
|
+
No ASTC hardware was reachable to test on: the device here reports fourteen compressed formats, all
|
|
1257
|
+
BC. Shipping a colour path to every iOS device that could not be checked, on a format where the
|
|
1258
|
+
failure mode is "wrong colours, silently", is worse than not shipping it. What would unblock it is
|
|
1259
|
+
the ASTC specification's Table C.2.8, its endpoint unquantization, and the CEM 8 rule — or an ASTC
|
|
1260
|
+
decoder from real tooling to test against, which is the same standard every other transcoder here was
|
|
1261
|
+
held to.
|
|
1262
|
+
|
|
1263
|
+
**A hazard ASTC surfaced, which was kept.** ASTC cannot hold an ETC1S payload's alpha — the colour
|
|
1264
|
+
and alpha slices have their own selectors, and the dual-plane block mode that would separate them
|
|
1265
|
+
cannot also hold eight endpoints and thirty-two weight bits in 128 bits. Being first in every colour
|
|
1266
|
+
role's preference, it would have been committed to and then refused, after the point where another
|
|
1267
|
+
format could still have been chosen. The same hazard was already live for BC1.
|
|
1268
|
+
|
|
1269
|
+
The fix outlives ASTC: `ktx2_read` now accepts an **ordered list** of acceptable targets and picks
|
|
1270
|
+
from it, because the container's descriptor is the only thing that knows whether the file carries
|
|
1271
|
+
alpha, and the caller is the only thing that knows what the device can sample. The loader hands over
|
|
1272
|
+
its whole preference order ending in the uncompressed floor. `transcode_basis_carries_alpha` is what
|
|
1273
|
+
the reader asks.
|
|
1274
|
+
|
|
1275
|
+
**Still not written:** ASTC, and both ETC2 and ASTC from UASTC. A UASTC normal map on a device with
|
|
1276
|
+
neither BC nor a verified ASTC path falls to the uncompressed floor, which costs memory rather than
|
|
1277
|
+
correctness.
|
|
1278
|
+
|
|
1279
|
+
### 9.15 The uncompressed target, and the end of the "no BC" refusal
|
|
1280
|
+
|
|
1281
|
+
§9.13 recorded a gap: a device advertising no compressed format got a named refusal rather than a
|
|
1282
|
+
picture. That is now closed. `transcode_basis` and `transcode_uastc` both write `rgba8unorm`, and the
|
|
1283
|
+
glTF loader falls to it when the device can sample none of the compressed targets.
|
|
1284
|
+
|
|
1285
|
+
**Why it had to exist.** Every compressed format in WebGPU is an optional feature —
|
|
1286
|
+
`texture-compression-bc`, `-etc2` and `-astc` alike — so a device exposing none of them is legal, and
|
|
1287
|
+
so is one exposing only the family this transcoder does not write. `rgba8unorm` is mandatory. Four
|
|
1288
|
+
bytes a texel against BC7's one is a poor outcome and no texture at all is a worse one.
|
|
1289
|
+
|
|
1290
|
+
Measured on the same scene, forcing the support set empty: 69 textures at **335.3 MiB**, which is
|
|
1291
|
+
exactly what the JPEG path costs, split `rgba8unorm-srgb` for the 25 albedo maps and `rgba8unorm` for
|
|
1292
|
+
the other 44 — the same sRGB split §9.14 fixed, arrived at through a different branch. It also loads
|
|
1293
|
+
in 11.4 s against the compressed path's ~19 s, because the BC re-encode is the expensive half and
|
|
1294
|
+
this skips it.
|
|
1295
|
+
|
|
1296
|
+
**The ETC1S path is byte-exact and the specs say so.** Every other target re-encodes the decoded
|
|
1297
|
+
texels and is therefore compared against a PSNR bound; `rgba8unorm` *is* the decode and nothing more,
|
|
1298
|
+
so it must equal the reference transcoder's own texels exactly. It does, across four fixtures and
|
|
1299
|
+
seven mip levels. That makes it the strictest check in the file, and it is only possible because
|
|
1300
|
+
there is no lossy step to hide behind. UASTC is bounded instead, against the reference's BC7, since
|
|
1301
|
+
the reference publishes no uncompressed output to compare with — what that bound really tests is
|
|
1302
|
+
arrangement rather than fidelity, because a row-order or crop error moves every texel at once.
|
|
1303
|
+
|
|
1304
|
+
Against the source JPEGs the whole chain lands at 31 to 49 dB, which is the ETC1S encode's own loss.
|
|
1305
|
+
|
|
1306
|
+
**One thing the mutation pass found, worth writing down.** Removing either bounds check in the two
|
|
1307
|
+
writers changes no output, and the tests were right not to fail. The index is row-major, so a write
|
|
1308
|
+
past the right edge of row `y` lands at the start of row `y + 1`, which is written afterwards and
|
|
1309
|
+
overwrites it; the only spill nothing corrects runs past the end of the buffer, where a typed array
|
|
1310
|
+
drops it silently. The guards are therefore unobservable — and they stay, because they are
|
|
1311
|
+
unobservable only while the iteration order holds, which is a coincidence and not a contract. Both
|
|
1312
|
+
files now say so, so that nobody removes them on the evidence of a green suite.
|
|
1313
|
+
|
|
1314
|
+
**Still not implemented:** ETC2 and ASTC. An ETC1S block already *is* an ETC1 block and UASTC was
|
|
1315
|
+
designed to transcode to ASTC nearly for free, so both remain much cheaper than the BC7 path already
|
|
1316
|
+
written, and both would beat four bytes a texel on the mobile devices that expose them. The
|
|
1317
|
+
difference is that failing to write them is now a memory cost rather than a refusal.
|
|
1318
|
+
|
|
1319
|
+
### 9.14 The albedo maps were never decoded as sRGB
|
|
1320
|
+
|
|
1321
|
+
Reported by eye — "they feel colder than the JPEGs" — and true. All 25 of Sponza's albedo textures
|
|
1322
|
+
were created as `bc7-rgba-unorm` while the same model's JPEGs reached `rgba8unorm-srgb`, so the GPU
|
|
1323
|
+
skipped the sRGB-to-linear decode and the shader read sRGB-encoded values as though they were linear.
|
|
1324
|
+
|
|
1325
|
+
Measured over one 1024x1024 albedo map, comparing what the shader saw against what it should have:
|
|
1326
|
+
|
|
1327
|
+
| | correct | as sampled | change |
|
|
1328
|
+
|---|---|---|---|
|
|
1329
|
+
| mean saturation | 0.2712 | 0.1488 | **-45.1%** |
|
|
1330
|
+
| mean luminance | 0.1316 | 0.3575 | **+171.7%** |
|
|
1331
|
+
| warmth (R-B) relative to luminance | 0.242 | 0.116 | **-52.4%** |
|
|
1332
|
+
|
|
1333
|
+
Both halves of the report fall out of that. The decode is a power curve, so it *stretches* the gap
|
|
1334
|
+
between channels; skipping it compresses them, which is the lost saturation. And warm surfaces have
|
|
1335
|
+
the widest R-to-B gap, so they lose the most — absolute R-B rises with everything else, but as a
|
|
1336
|
+
fraction of brightness it halves, which is what reads as cold.
|
|
1337
|
+
|
|
1338
|
+
**The cause was a pinned decision, not an oversight.** `texture_format_from_shade_image` returned a
|
|
1339
|
+
texel payload's format verbatim, and a test asserted it: *"a texel payload states its own format,
|
|
1340
|
+
whatever the colour space says"*, reasoning that "there is nothing to infer from, so nothing to be
|
|
1341
|
+
overridden by". That conflates two things. Channel count and data type are inference, and a payload
|
|
1342
|
+
does state them. sRGB-ness is not inference at all — `bc7-rgba-unorm` and `bc7-rgba-unorm-srgb` are
|
|
1343
|
+
the same bytes, so a transcoder targeting either does identical work and a payload *cannot* express
|
|
1344
|
+
the choice. Naming one leaves the question open rather than answering it.
|
|
1345
|
+
|
|
1346
|
+
The test immediately above it already states the correct rule, for the other branch: a format decided
|
|
1347
|
+
before `color_space` is assigned "would leave every glTF albedo map on `rgba8unorm` and silently drop
|
|
1348
|
+
its sRGB decode". The texel branch did exactly that. Both branches now read `color_space`, and a
|
|
1349
|
+
payload with no sRGB counterpart under an sRGB image is refused by name rather than quietly returning
|
|
1350
|
+
the linear format — the silent wrong answer being the whole failure mode here.
|
|
1351
|
+
|
|
1352
|
+
`gpu_texture_format_srgb` is new and derives its pairs from the format table by suffix rather than
|
|
1353
|
+
listing them, so a format added to the table brings its own pairing.
|
|
1354
|
+
|
|
1355
|
+
**Two notes for the next person.** VRAM is unchanged: sRGB-ness is a decode, not a size, so nothing
|
|
1356
|
+
about §9.13's 4.00x moves. And the playground reported the *payload's* format, which is why its own
|
|
1357
|
+
table showed `bc7-rgba-unorm` for albedo and looked right while the render did not; it now reports
|
|
1358
|
+
what `texture_format_from_shade_image` returns, so the two paths' albedo rows can be compared.
|
|
1359
|
+
|
|
1360
|
+
**Separately checked and not a problem:** whether ETC1S itself desaturates. Across the opaque JPEGs
|
|
1361
|
+
it is within about 3%, rising to 9% only on near-pure primaries where quantization lifts a
|
|
1362
|
+
near-zero channel by roughly 2/255. That is ordinary lossy behaviour and not what was visible.
|
|
1363
|
+
|
|
1364
|
+
### 9.13 What tier 8 found — the first GPU to see any of this
|
|
1365
|
+
|
|
1366
|
+
Run 2026-09-02 on an NVIDIA Lovelace device, through
|
|
1367
|
+
[`playground/basis_textures`](../../playground/basis_textures/README.md): Sponza twice, once as JPEG
|
|
1368
|
+
and once re-encoded by `basisu` to KTX2 with UASTC normals and ETC1S everything else.
|
|
1369
|
+
|
|
1370
|
+
| | textures | GPU memory | formats |
|
|
1371
|
+
|---|---|---|---|
|
|
1372
|
+
| JPEG | 69 | 335.3 MiB | 69 x `rgba8` |
|
|
1373
|
+
| Basis | 69 | 83.8 MiB | 45 x `bc7-rgba-unorm`, 24 x `bc5-rg-unorm` |
|
|
1374
|
+
|
|
1375
|
+
**4.00x**, both sides counted through `TextureDescriptor.memory_footprint` and both including their
|
|
1376
|
+
full mip chain. All 69 textures were accepted by the device. The 24 BC5 textures are exactly the 24
|
|
1377
|
+
normal maps, which is §3b's role-driven choice arriving where it was aimed.
|
|
1378
|
+
|
|
1379
|
+
Two defects, and both are §9.11's lesson a third time — a rule that held everywhere it had been
|
|
1380
|
+
checked, and had never been checked here.
|
|
1381
|
+
|
|
1382
|
+
1. **Mip *generation* was requested for formats that cannot generate mips.** `ShadeTexture` sets
|
|
1383
|
+
`GenerateMipMaps` by default, which is right for a decoded JPEG and impossible for a transcoded
|
|
1384
|
+
payload: the generator renders between levels and no BC format can be a render attachment.
|
|
1385
|
+
`texture_descriptor_from_texture_shade` refuses that combination by name (§9.7 made it refuse
|
|
1386
|
+
rather than reinterpret, which is why this surfaced as a legible message instead of a black
|
|
1387
|
+
texture) — but nothing cleared the flag, so **every compressed texture in the scene was refused at
|
|
1388
|
+
upload**. `load_gltf` now clears it when the image's format cannot generate them, and the chain
|
|
1389
|
+
the container already carries is used. Every device-free test had built its textures directly and
|
|
1390
|
+
never went through the glTF loader's default flags.
|
|
1391
|
+
2. **`TextureManager.gpu_memory_usage` is a running total, and removing a scene evicts nothing.**
|
|
1392
|
+
Reading it after each load reported the sum of every load so far, which inflated whichever variant
|
|
1393
|
+
was measured second — the one being argued for. It read 5.00x before this was noticed. The
|
|
1394
|
+
playground measures the difference across its own uploads instead. Worth recording as a property
|
|
1395
|
+
of the manager rather than of the playground: there is no eviction API, and a long-running editor
|
|
1396
|
+
that swaps scenes will accumulate.
|
|
1397
|
+
|
|
1398
|
+
**Then a third, which the numbers could not have found — every texture was upside down.** The
|
|
1399
|
+
converter passed `-y_flip` to `basisu`. glTF puts UV (0,0) at the top-left, and a KTX2 with no
|
|
1400
|
+
`KTXorientation` key means exactly that, so `KHR_texture_basisu` requires a top-down payload;
|
|
1401
|
+
`basisu` writes no such key either way, so the flag bakes a vertical mirror into the pixels and
|
|
1402
|
+
records nothing a reader could detect or undo. Confirmed by encoding a top-white/bottom-black image
|
|
1403
|
+
both ways and transcoding each: with the flag the top row decodes black, without it white. Then on
|
|
1404
|
+
the re-converted model itself, comparing each texture's top-band luminance against its bottom-band in
|
|
1405
|
+
the browser: all six asymmetric enough to judge agree in sign with the JPEG they came from, one to 0.3
|
|
1406
|
+
out of 143. The bug was in the dev tool and not in the engine — the container reader and both
|
|
1407
|
+
transcoders preserve orientation, which the fixture comparisons against reference-decoded output
|
|
1408
|
+
already pin, and nothing on the upload path flips either (`createImageBitmap` is left at the default
|
|
1409
|
+
`from-image`, `copyExternalImageToTexture` sets no `flipY`), so the JPEG and KTX2 paths agree.
|
|
1410
|
+
|
|
1411
|
+
Worth separating from the two above: those were found by *running* it, and this one only by
|
|
1412
|
+
*looking* at it. The VRAM table was correct in every particular while the scene was upside down,
|
|
1413
|
+
which is the caveat below arriving in practice rather than in principle.
|
|
1414
|
+
|
|
1415
|
+
**Still not seen — and that turned out to matter.** The renderer needs `maxImmediateSize` >= 24 and
|
|
1416
|
+
assumes the 64-byte floor; the Chrome build available here reports 0, so the frame loop dies in
|
|
1417
|
+
`GPUTypedTable/Upload elements` for every playground in the directory. The measurements above are
|
|
1418
|
+
taken through `TextureManager.obtain` — the same call the renderer makes, and the same moment the
|
|
1419
|
+
device accepts a format or does not — so what is proven is that the device takes these textures.
|
|
1420
|
+
That the sampled result *looks* like the picture is established only on the CPU side, against the
|
|
1421
|
+
reference decoder, and the `-y_flip` defect is what that gap costs: an asset bug that every number
|
|
1422
|
+
on the page was blind to, and that a single glance caught.
|
|
1423
|
+
|
|
1424
|
+
**The gap tier 8 made concrete.** There is no uncompressed transcode target, so a device advertising
|
|
1425
|
+
no BC at all gets a named refusal. No real WebGPU device is in that position, but the two cheap
|
|
1426
|
+
fillers should be recorded: an ETC1S block already *is* an ETC1 block, and UASTC was designed to
|
|
1427
|
+
transcode to ASTC nearly for free. Both are far cheaper than the BC7 path already written.
|
|
1428
|
+
|
|
1429
|
+
### 9.12 What step 9b actually shipped — UASTC, and the one thing it still cannot open
|
|
1430
|
+
|
|
1431
|
+
**UASTC is the encoding normal maps use, and that is why it stopped being optional.** ETC1S puts a
|
|
1432
|
+
block's four colours on a line through the grey axis, which is a good model of a photograph and a bad
|
|
1433
|
+
model of a direction — a normal map encoded as ETC1S bands visibly. `gltf-transform uastc` and
|
|
1434
|
+
`toktx --uastc` exist for that, and any pipeline that cares about normals emits it.
|
|
1435
|
+
|
|
1436
|
+
Nineteen modes, 128-bit blocks, varying in subset count, endpoint precision, weight precision and
|
|
1437
|
+
whether one channel is interpolated separately, with the endpoints trit- or quint-coded in most modes
|
|
1438
|
+
and the weights packed a bit short at each subset's anchor texel. Implemented from the UASTC LDR 4x4
|
|
1439
|
+
specification.
|
|
1440
|
+
|
|
1441
|
+
**The tables were transcribed mechanically, not typed.** Sixty partition patterns, sixty anchor
|
|
1442
|
+
tables, eleven dequantisation tables and nineteen mode descriptors were extracted from the
|
|
1443
|
+
specification's own listings into
|
|
1444
|
+
[`uastc_tables.js`](../../../format/texture/basis/uastc/uastc_tables.js). The only thing computed is each mode's
|
|
1445
|
+
field offsets, and those are checked against the offsets the specification prints for every mode.
|
|
1446
|
+
|
|
1447
|
+
#### What it transcodes to, and the one that matters
|
|
1448
|
+
|
|
1449
|
+
**BC5, which is the point.** §11.1 established that a tangent-space normal's Z is reconstructed in
|
|
1450
|
+
the shader, so `bc5-rg-unorm` spends its whole budget on the two channels that carry something —
|
|
1451
|
+
and `texture_format_preference` has led with it for the normal role since step 3b with nothing able
|
|
1452
|
+
to produce one. Two independent scalar channels means no line through colour space to place, so the
|
|
1453
|
+
encode is near-optimal: worst channel error of **1** on the gradient fixture.
|
|
1454
|
+
|
|
1455
|
+
**BC7, by carrying the block across rather than re-encoding it.** A UASTC block already *is* two
|
|
1456
|
+
endpoints and a weight per texel, which is what BC7 stores, so the transcode is a change of
|
|
1457
|
+
representation. Decoding to RGBA and fitting a fresh line instead — which is what this did first —
|
|
1458
|
+
costs **eighteen decibels**, and the measurement is worth keeping because the wrong version looked
|
|
1459
|
+
entirely reasonable. Dual plane blocks go to BC7 mode 5, whose second index set is exactly what their
|
|
1460
|
+
separately-interpolated channel needs; everything else single-subset goes to mode 6, whose four-bit
|
|
1461
|
+
weight table is ASTC's. Where those two cover every block the output matches the reference
|
|
1462
|
+
transcoder's own figures: **55.68 dB with a worst channel of 1**, against its 55.68 and 1.
|
|
1463
|
+
|
|
1464
|
+
#### The role finally reaches the format choice
|
|
1465
|
+
|
|
1466
|
+
§9.11 recorded that the texture's role did not enter the target choice and that this would start
|
|
1467
|
+
mattering "the moment ETC1S→BC5 lands". It landed as UASTC→BC5 instead, and the rest followed:
|
|
1468
|
+
[`gltf_image_roles`](../loader/gltf/gltf_image_roles.js) reads the materials to learn which image is
|
|
1469
|
+
the normal map, and the loader orders its candidates by `texture_format_preference(role, ...)`.
|
|
1470
|
+
|
|
1471
|
+
**Ordering, not filtering.** A role's preference lists what is *good*, not what is acceptable — BC1
|
|
1472
|
+
is in no role's list — so a device that can sample only BC1 still gets a texture. The role moves a
|
|
1473
|
+
format to the front and never removes one.
|
|
1474
|
+
|
|
1475
|
+
#### Partitioned blocks, and what closing that gap turned up
|
|
1476
|
+
|
|
1477
|
+
The first version of this flattened every two- and three-subset block onto one BC7 line, because BC7's
|
|
1478
|
+
partitioned modes were not written. That cost **more than twenty decibels** on partitioned content —
|
|
1479
|
+
the subsets fixture scored 25.8 dB then and 52.0 now — and it is closed: every UASTC mode goes to the
|
|
1480
|
+
BC7 mode the specification pairs it with, including mode 7's oddity of being two subsets in UASTC and
|
|
1481
|
+
three in BC7, written with two of BC7's endpoint pairs alike.
|
|
1482
|
+
|
|
1483
|
+
One writer serves all six modes, because the specification says the fields are in the same order for
|
|
1484
|
+
every mode and only their widths change. Against the reference transcoder, colour only: identical on
|
|
1485
|
+
two fixtures, +0.14 dB on a third, and 0.21 and 0.44 dB behind on the other two.
|
|
1486
|
+
|
|
1487
|
+
**Two defects surfaced while closing it, and both were about alpha nobody authored.** Mode 1 was
|
|
1488
|
+
mapped to BC7 mode 6 rather than mode 3 — and the specification's choice is not arbitrary: mode 3 is
|
|
1489
|
+
the only mode holding eight-bit endpoints *without* an alpha channel, and mode 6's alpha parity bit is
|
|
1490
|
+
shared with colour, so it must be traded against it. That trade was the second defect: choosing the
|
|
1491
|
+
parity by total error over all four channels let a constant alpha outvote colour, and on an RGB source
|
|
1492
|
+
that alpha is 255 by construction rather than by authorship. Forcing it kept alpha exact and cost
|
|
1493
|
+
**1.66 dB of colour**; excluding it from the vote is right, because §9.2 already settled that a
|
|
1494
|
+
texture's alpha mode is declared rather than inferred from its texels. The reference makes the same
|
|
1495
|
+
trade — its own output carries 181,026 texels at alpha 254 on the same opaque file.
|
|
1496
|
+
|
|
1497
|
+
#### The mutation harness was lying, which is the more useful finding
|
|
1498
|
+
|
|
1499
|
+
The checks ran through `sed`, and `sed` reports nothing when it matches nothing — so a mutation whose
|
|
1500
|
+
pattern had the wrong indentation silently tested the *unmodified* code and was recorded as caught.
|
|
1501
|
+
Three of them had. The harness now fails loudly on a no-op and every mutation claimed for this work
|
|
1502
|
+
was re-run through it.
|
|
1503
|
+
|
|
1504
|
+
Two real holes appeared once they ran for real, and both are the §9.11 lesson again — a guard checked
|
|
1505
|
+
against its own absence says nothing about code no fixture reaches:
|
|
1506
|
+
|
|
1507
|
+
- **BC7's anchor tables were untested.** The anchor is texel 15 for the first seventeen partitions and
|
|
1508
|
+
something else after that, and every fixture happened to land in the first seventeen — so the table
|
|
1509
|
+
could have been replaced by the constant 15. `uastc_partitions_32x24` reaches anchors 2 and 8: one
|
|
1510
|
+
block per partition pattern, each subset ramping in its own direction, because two flat colours are
|
|
1511
|
+
collinear and an encoder answers them with a single subset.
|
|
1512
|
+
- **The three-subset permutation was untested by any bound that could see it.** Only seven blocks use
|
|
1513
|
+
a non-identity one, which moves an average by under a decibel while moving the worst texel by a
|
|
1514
|
+
hundred. The transcode tests now carry a per-channel bound beside the PSNR one — the same division
|
|
1515
|
+
§9.11 settled for ETC1S, arrived at a second time by getting it wrong.
|
|
1516
|
+
|
|
1517
|
+
#### Zstandard, which turned out not to be optional
|
|
1518
|
+
|
|
1519
|
+
`basisu -uastc -ktx2` compresses with Zstandard *by default*, and so do `gltf-transform` and
|
|
1520
|
+
`toktx` — so almost all UASTC in the wild sits behind it, and a UASTC transcoder without a Zstandard
|
|
1521
|
+
decompressor reads only files written with `-ktx2_no_zstandard`, which is not what anyone writes by
|
|
1522
|
+
accident. It was going to be step 9c and became part of this one, because the feature was not real
|
|
1523
|
+
without it.
|
|
1524
|
+
|
|
1525
|
+
**Implemented from RFC 8878**, in [`core/binary/zstd/`](../../../core/binary/zstd/zstd_decompress.js)
|
|
1526
|
+
beside `lz4/` and `meshopt/`, on the same argument that put those there. §9.10 read ZLIB rather than
|
|
1527
|
+
refusing it because `pako` was already present; this is the same conclusion reached the other way,
|
|
1528
|
+
by writing the decompressor rather than taking one.
|
|
1529
|
+
|
|
1530
|
+
It is Lempel-Ziv with two entropy stages over it, both read *backwards* — Finite State Entropy
|
|
1531
|
+
carries a state between symbols, so decoding runs opposite to encoding. Two details cost a debugging
|
|
1532
|
+
session each and are commented where they bit:
|
|
1533
|
+
|
|
1534
|
+
- **The normalised-count field width shrinks with a running threshold** rather than being recomputed
|
|
1535
|
+
from the probability that remains. The two readings look equivalent and are not: the halving lags
|
|
1536
|
+
behind the remainder, so a decoder that recomputes reads most distributions correctly and a few
|
|
1537
|
+
wrongly.
|
|
1538
|
+
- **The interleaved two-state weight decode emits, then advances**, and stops when an advance runs
|
|
1539
|
+
past the start of the stream — not when the *other* state could not advance. The wrong version
|
|
1540
|
+
produced weight sets right for most of their length, which surfaced as two literals swapped.
|
|
1541
|
+
|
|
1542
|
+
No dictionaries, and the content checksum is skipped rather than verified: the containers carrying
|
|
1543
|
+
these streams check their own payload sizes, and XXH64 to re-check a length is not worth a file.
|
|
1544
|
+
|
|
1545
|
+
Tested against `node:zlib`'s Zstandard — the reference library, so the oracle is somebody else's
|
|
1546
|
+
implementation and not this one's own output. Three thousand fuzz cases over six input shapes and
|
|
1547
|
+
every compression level, thirteen committed cases, and five mutations all caught. A
|
|
1548
|
+
Zstandard-wrapped UASTC file now transcodes byte-identically to the same file written uncompressed.
|
|
1549
|
+
|
|
1550
|
+
#### Testing
|
|
1551
|
+
|
|
1552
|
+
**17 of the 19 modes are exercised and verified** — every one an encoder could be made to emit.
|
|
1553
|
+
Modes 10 and 18 are not selected by `basisu` at any quality level or content tried, so they are
|
|
1554
|
+
implemented from the specification and unproven, which is stated here rather than left to be assumed.
|
|
1555
|
+
Getting the coverage took building content to provoke modes rather than to look like anything: solid
|
|
1556
|
+
blocks, sharply partitioned blocks, blocks with alpha independent of colour.
|
|
1557
|
+
|
|
1558
|
+
The ground truth is the reference transcoder's BC7 output, which the specification itself calls lossy
|
|
1559
|
+
by 0.75 to 1.5 dB — so it is a bound rather than an equality, and at a worst channel error of **6**
|
|
1560
|
+
across every fixture it is a decisive one: misreading a mode, a partition, an endpoint range or an
|
|
1561
|
+
anchor moves a block by tens or hundreds. UASTC→ASTC is the lossless transcode and would give an
|
|
1562
|
+
exact check; nothing here can decode an ASTC block to make use of it.
|
|
1563
|
+
|
|
1564
|
+
**And the test decoder now shares its tables with the writer**, which means it cannot disagree with
|
|
1565
|
+
it — a transcription error in a partition, anchor or mode table would be invisible to every
|
|
1566
|
+
comparison between the two. What breaks that symmetry is decoding blocks this repository did not
|
|
1567
|
+
write: the reference's output for these fixtures spans BC7 modes 1, 2, 3, 5, 6 and 7, and reproducing
|
|
1568
|
+
the texels it published for them is exact. That check runs before any other in the file, and it is
|
|
1569
|
+
what makes sharing the tables safe rather than circular.
|
|
1570
|
+
|
|
1571
|
+
Twelve mutations across the decoder and both transcoders, all caught — after the harness was fixed to
|
|
1572
|
+
report the ones that had silently applied to nothing.
|
|
1573
|
+
|
|
1574
|
+
### 9.11 What step 9 actually shipped, and the two places §4.3 was optimistic
|
|
1575
|
+
|
|
1576
|
+
[`transcode_basis`](../../../format/texture/basis/transcode_basis.js) is the public surface, with §4.3's contract
|
|
1577
|
+
intact: bytes in, texels out, no device and no queue. `src/basis/` sits beside `src/ktx2/` and
|
|
1578
|
+
`src/avif/` for the same reason those do — a worker, a node tool and the offline encoder will each
|
|
1579
|
+
want it, and none should have to import a graphics API to get it.
|
|
1580
|
+
|
|
1581
|
+
**ETC1S only.** Both Basis encodings were in scope and one landed. UASTC is a different bitstream —
|
|
1582
|
+
mode-switched 128-bit blocks with BISE-coded weights, sharing nothing with ETC1S but the file it
|
|
1583
|
+
arrives in — and it is refused by name rather than half-implemented. ETC1S is the common case in the
|
|
1584
|
+
wild and the whole of what `basisu` and `gltf-transform` emit at their default settings, so the
|
|
1585
|
+
capability is useful without it; step 9b is the rest.
|
|
1586
|
+
|
|
1587
|
+
`ktx2_read` accepts BasisLZ, and `KHR_texture_basisu` is read at both glTF sites.
|
|
1588
|
+
|
|
1589
|
+
#### Where §4.3 was optimistic
|
|
1590
|
+
|
|
1591
|
+
**1. `payload` is not a byte array.** The signature reads `transcode_basis(payload, target_format)`,
|
|
1592
|
+
which suggests one buffer. An ETC1S texture is not stored that way: its endpoint and selector
|
|
1593
|
+
codebooks and its four Huffman tables live in KTX2's *supercompression global data*, its slices live
|
|
1594
|
+
in the mip levels, and which bytes are which is a question about the container. So `payload` is a
|
|
1595
|
+
`BasisEtc1sPayload` — the sections, already located — and finding them is
|
|
1596
|
+
[`ktx2_read_basis_lz_global_data`](../../../format/texture/ktx2/ktx2_read_basis_lz_global_data.js), which is KTX2
|
|
1597
|
+
Appendix C and therefore container code. A `.basis` reader would build the same payload from a
|
|
1598
|
+
different layout. Nothing about "no device, no queue, no engine" changes.
|
|
1599
|
+
|
|
1600
|
+
**2. "Block-to-block transforms with no cross-block dependencies" is true of the structure and badly
|
|
1601
|
+
understates the work.** The transform really is per block with no neighbours involved. But the
|
|
1602
|
+
obvious mapping — take the ETC1S palette's darkest and brightest colours as the destination's two
|
|
1603
|
+
endpoints — lands **8 to 10 dB below the reference transcoder**, and a texture that far down is
|
|
1604
|
+
visibly banded on saturated content. Three things close it, none of them evident from the format
|
|
1605
|
+
descriptions:
|
|
1606
|
+
|
|
1607
|
+
- **Clamping breaks the collinearity the transform depends on.** An ETC1S block is a base colour plus
|
|
1608
|
+
one modifier applied to all three channels, so its four colours are collinear *before* clamping.
|
|
1609
|
+
A base near white with a large modifier gives red `{67, 203, 255, 255}` beside green
|
|
1610
|
+
`{0, 0, 57, 193}` — still ordered, no longer on a line, because red saturated and green did not.
|
|
1611
|
+
Endpoints have to be **fitted** (least squares, alternating with the weight assignment), not read
|
|
1612
|
+
off the ends.
|
|
1613
|
+
- **The fit has to know which selectors the block actually uses.** That is a property of its
|
|
1614
|
+
*selector* codebook entry, not of the endpoint entry, so the tables are keyed on the **pairing** of
|
|
1615
|
+
the two. A block spanning only the darkest two colours is a line those two define exactly, and
|
|
1616
|
+
fitting it against colours it never samples throws that away.
|
|
1617
|
+
- **For BC1, which colour goes at which of the four positions has to be enumerated.** The best pair
|
|
1618
|
+
frequently lies **outside** the colours it encodes: three evenly spaced colours have no endpoints
|
|
1619
|
+
putting them at weights 0, something and 64, but a pair extended past both ends puts them at 64,
|
|
1620
|
+
43 and 21 almost exactly. There are at most fifteen such assignments, so they are tried rather than
|
|
1621
|
+
searched for. BC1's pair is then searched in 5:6:5 space rather than rounded into it, because five-
|
|
1622
|
+
and six-bit endpoints are coarse enough that the best representable pair is not always the rounding
|
|
1623
|
+
of the best real-valued one.
|
|
1624
|
+
|
|
1625
|
+
All of it is per (endpoint entry, selector span) pairing — a few hundred to a few thousand — rather
|
|
1626
|
+
than per block, of which a texture has tens of thousands.
|
|
1627
|
+
|
|
1628
|
+
**Which of those is worth what, measured, because the first write-up of this got it wrong.** On the
|
|
1629
|
+
noise fixture, against 48.0 dB for BC7 and 44.1 for BC1:
|
|
1630
|
+
|
|
1631
|
+
| removed | BC7 | BC1 |
|
|
1632
|
+
|---|---|---|
|
|
1633
|
+
| selector-span conditioning | 38.8 dB, worst channel 30 | 38.1 dB, worst channel 36 |
|
|
1634
|
+
| BC1's assignment enumeration | — | 37.6 dB, worst channel 30 |
|
|
1635
|
+
| the least-squares solve | 48.0 dB, worst channel 2 | — |
|
|
1636
|
+
| BC1's 5:6:5 search | — | 43.9 dB |
|
|
1637
|
+
|
|
1638
|
+
So **span conditioning is the whole of it for BC7, and span conditioning plus the assignment
|
|
1639
|
+
enumeration are the whole of it for BC1.** The least-squares solve on top contributes nothing
|
|
1640
|
+
measurable on that fixture and about a decibel on the harder mip levels of the gradient and
|
|
1641
|
+
non-power-of-two files; the 5:6:5 search contributes 0.2 to 1.3 dB. The commit that landed this
|
|
1642
|
+
credited the 5:6:5 search with 9 dB, which was the assignment enumeration's — the two were written
|
|
1643
|
+
at the same time and never ablated apart until afterwards.
|
|
1644
|
+
|
|
1645
|
+
The result matches the reference transcoder: BC7 at 48.0 / 52.1 / 49.1 dB against its
|
|
1646
|
+
46.6 / 51.7 / 51.8, BC1 at 44.1 / 49.7 against 44.0 / 49.8.
|
|
1647
|
+
|
|
1648
|
+
**And it is not fast.** A 1024×1024 texture takes **127 ms** to reach BC7 and **389 ms** to reach
|
|
1649
|
+
BC1, on the main thread, of which the codebooks and the slice decode are 22 ms together and the rest
|
|
1650
|
+
is building the templates — 18,620 pairings for that file, of which 71% are actually referenced.
|
|
1651
|
+
§4.2 said transcoding "pays CPU time on load"; this is what that costs, and a model with a dozen
|
|
1652
|
+
textures pays it a dozen times. The obvious places to go next are running it in the worker pool
|
|
1653
|
+
`avif/threaded_image_encoder.js` already has, building templates lazily for the pairings a slice
|
|
1654
|
+
actually names, and §4.4's GPU transcoder — which is step 10 and was always the answer to this.
|
|
1655
|
+
|
|
1656
|
+
#### The judgement calls
|
|
1657
|
+
|
|
1658
|
+
**BC7 needs two modes, and the plan assumed one transform.** Mode 6 gives every texel one four-bit
|
|
1659
|
+
index shared by all four channels; mode 5 gives colour and alpha their own indices, two bits each. An
|
|
1660
|
+
ETC1S file's alpha lives in a **second slice with its own selectors**, unrelated to the colour
|
|
1661
|
+
slice's, so mode 6's single index set cannot express an alpha payload at all. Opaque payloads take
|
|
1662
|
+
mode 6 for the finer index; alpha payloads take mode 5. Mode 6 additionally fixes its parity bit at
|
|
1663
|
+
one rather than fitting it, because that bit is shared between an endpoint's colour channels and its
|
|
1664
|
+
alpha, and an opaque texture decoding to alpha 254 is a bug nothing notices until something blends.
|
|
1665
|
+
|
|
1666
|
+
**`ktx2_read` gained a parameter, and it is not defaulted.** An ETC1S payload has no format of its
|
|
1667
|
+
own — what it should become depends on the device and on the material slot — so `transcode_target` is
|
|
1668
|
+
the caller's to state. Absent, an ETC1S file is refused naming `texture_format_preference` as where
|
|
1669
|
+
one comes from. Every other file ignores it, so no existing caller changed.
|
|
1670
|
+
|
|
1671
|
+
**BC1 refuses an alpha payload rather than dropping it.** BC1 has no alpha channel in the mode this
|
|
1672
|
+
writes. A payload carries alpha slices because something needed them, and a texture arriving opaque
|
|
1673
|
+
surfaces far away as a cutout that does not cut out.
|
|
1674
|
+
|
|
1675
|
+
**Both glTF sites now share one function rather than agreeing by inspection.**
|
|
1676
|
+
`gltf_texture_image_index` is the preference order, written once:
|
|
1677
|
+
`KHR_texture_basisu`, then `EXT_texture_webp`, then `source`. §9.10's neighbouring incident — the two
|
|
1678
|
+
disagreeing, and not one model in the level loading — is not fixed by being careful, it is fixed by
|
|
1679
|
+
there being one decision.
|
|
1680
|
+
|
|
1681
|
+
#### What this did not build, and why
|
|
1682
|
+
|
|
1683
|
+
**Device support does not reach the asset layer.** §3.5 divides capability (the engine's) from
|
|
1684
|
+
selection (the asset layer's), and the asset layer here is the glTF loader — which has an
|
|
1685
|
+
`assetManager` and a `scope` and **no device**. `load_gltf` gains a `texture_support` option and
|
|
1686
|
+
nothing passes it, because opening a channel from the renderer to every asset loader is a change of
|
|
1687
|
+
its own shape. Absent one, the loader targets BC7: an assumption about the hardware meep aims at,
|
|
1688
|
+
stated as one, and a caller that knows better passes its device's support and gets a named refusal
|
|
1689
|
+
instead of a texture the device cannot hold. `gpu_texture_compression_support` still has no
|
|
1690
|
+
non-test caller.
|
|
1691
|
+
|
|
1692
|
+
**The texture's role does not enter the choice.** Every format this transcoder writes is a
|
|
1693
|
+
four-channel BC colour format, so a normal map and an albedo map get the same answer and asking
|
|
1694
|
+
`texture_format_preference` for the role would be ceremony. It stops being ceremony the moment
|
|
1695
|
+
ETC1S→BC5 lands — BC5 is what §11.1 already established normals want, and an ETC1S file with an alpha
|
|
1696
|
+
slice carries exactly the two channels it needs.
|
|
1697
|
+
|
|
1698
|
+
#### Testing, and what §9.10's gap became
|
|
1699
|
+
|
|
1700
|
+
**Step 8's fixtures were synthesised and this one's are not.** §9.10 named that as its gap — "first
|
|
1701
|
+
contact with a real file is the test that has not been run" — and these are files from
|
|
1702
|
+
`basisu 1.16.4`, so for the ETC1S path the byte offsets are now known rather than believed. That
|
|
1703
|
+
includes the level index and the global data layout the KTX2 reader had only ever read from its own
|
|
1704
|
+
writer.
|
|
1705
|
+
|
|
1706
|
+
Three things make the specs load-bearing rather than self-confirming:
|
|
1707
|
+
|
|
1708
|
+
1. **The ground truth is the encoder's own decode.** `basisu` unpacks each file to ETC1, which *is*
|
|
1709
|
+
the ETC1S texels; every level of every fixture comes out of this decoder byte-identical to it.
|
|
1710
|
+
That covers the global data, four Huffman tables, both codebooks, the endpoint predictor and the
|
|
1711
|
+
selector history in one assertion.
|
|
1712
|
+
2. **The block decoder the transcode tests judge with is validated before it is trusted.** A decoder
|
|
1713
|
+
written beside an encoder can share the encoder's misreading and agree with it perfectly, so it is
|
|
1714
|
+
first pointed at blocks the *reference* transcoder produced and checked against the texels the
|
|
1715
|
+
reference published for them.
|
|
1716
|
+
3. **Every guard was checked against its own absence.** Fourteen mutations, all caught — among them
|
|
1717
|
+
dropping the move-to-front promotion, misreading the upper-left predictor as the upper, floating
|
|
1718
|
+
the parity bit, skipping the anchor flip, starting the endpoint codebook from black instead of
|
|
1719
|
+
`(16, 16, 16)`, dropping the selector DPCM, shifting a five-bit channel instead of replicating it,
|
|
1720
|
+
dropping the endpoint index wraparound, reading alpha presence as always absent, and the three
|
|
1721
|
+
glTF ones. One found a real hole: **no fixture reached the upper-left endpoint predictor**, so
|
|
1722
|
+
that branch could have been deleted silently. `etc1s_antidiag_64x64` exists to exercise it, and
|
|
1723
|
+
diagonal structure is what made an encoder want it.
|
|
1724
|
+
|
|
1725
|
+
**What is still untested.** Alpha has no exact reference — `basisu` never emits the alpha slice in a
|
|
1726
|
+
form that is not already re-encoded — so that one path is bounded rather than exact.
|
|
1727
|
+
|
|
1728
|
+
**Tier 8 has now been run** — see §9.13.
|
|
1729
|
+
|
|
1730
|
+
#### What an adversarial pass over the above then found
|
|
1731
|
+
|
|
1732
|
+
Worth recording because two of the four were defects that the tests as written could not have caught,
|
|
1733
|
+
and both were of the same kind: a rule read once and then assumed.
|
|
1734
|
+
|
|
1735
|
+
1. **`KHR_texture_basisu` images were identified by MIME type, and the extension does not require
|
|
1736
|
+
one.** `image/ktx2` is mandatory only inside a GLB, where the image comes from a bufferView; an
|
|
1737
|
+
image referenced by URI is merely *permitted* to declare it. So an ordinary `.gltf` carrying
|
|
1738
|
+
`{"uri": "wood.ktx2"}` went to `createImageBitmap` — which is precisely the failure
|
|
1739
|
+
`gltf_used_image_indices` exists to prevent, reintroduced by the change that cited it. The
|
|
1740
|
+
extension's own reference is now the authority and the MIME type a supplementary signal.
|
|
1741
|
+
2. **A corrupt slice produced silent wrong texels rather than a refusal.** The three reuse predictors
|
|
1742
|
+
each name a neighbour that does not exist at an edge; the specification asserts an encoder never
|
|
1743
|
+
does this, and the decoder trusted that. Reading past the start of the previous row's array yields
|
|
1744
|
+
`undefined`, which compares false against every bound and stores as endpoint zero. Now refused,
|
|
1745
|
+
naming the predictor and the position.
|
|
1746
|
+
3. **Two more branches had no fixture reaching them**, exactly as the upper-left predictor had none:
|
|
1747
|
+
the **grayscale endpoint codebook**, which sends one channel and means three — deletable with
|
|
1748
|
+
every test still passing — and **non-power-of-two** dimensions, where every mip tail is square in
|
|
1749
|
+
the fixtures that existed. Both work; neither was proven. `gray_64x64` and `npot_100x60` are here
|
|
1750
|
+
now. The lesson is that "verify a guard against its own absence" catches broken code and says
|
|
1751
|
+
nothing about code no test reaches, and only counting which branches a fixture set actually
|
|
1752
|
+
executes finds those.
|
|
1753
|
+
4. **The quality attribution in the commit message was wrong**, as the table above records. Two
|
|
1754
|
+
optimisations written in the same sitting were credited by measuring their sum.
|
|
1755
|
+
|
|
1756
|
+
The non-power-of-two fixture is also the one place a bound had to be *loosened* rather than a bug
|
|
1757
|
+
fixed: its first form used a pattern with wrapping discontinuities, on which the transcode's worst
|
|
1758
|
+
channel error is 59 — and the reference transcoder's is 69, because no two-endpoint format holds four
|
|
1759
|
+
colours that far off a line. That is a fact about the format pair, so the fixture was re-made with
|
|
1760
|
+
smooth content, leaving the geometry under test and the thin per-channel bound intact.
|
|
1761
|
+
|
|
884
1762
|
### 9.10 What step 8 actually shipped
|
|
885
1763
|
|
|
886
|
-
[`ktx2_read`](../../../ktx2/ktx2_read.js) is the whole public surface: `bytes -> ShadeTexelData`, one
|
|
1764
|
+
[`ktx2_read`](../../../format/texture/ktx2/ktx2_read.js) is the whole public surface: `bytes -> ShadeTexelData`, one
|
|
887
1765
|
free function, no device and no queue. It lives at `src/ktx2/`, beside `src/avif/` rather than inside
|
|
888
1766
|
the renderer, which is §2's "living with its container" taken literally — the same function is what a
|
|
889
1767
|
worker, a node tool and the offline encoder will each want, and none of them should have to import a
|
|
@@ -901,7 +1779,7 @@ it, and two of them are changes to existing code:
|
|
|
901
1779
|
|
|
902
1780
|
- **`ByteCursor` moved to [`core/binary/`](../../../core/binary/ByteCursor.js) and takes its byte
|
|
903
1781
|
order at `init`.** It was exactly the cursor this needed — bounds-checked, zero-copy, a named error
|
|
904
|
-
per truncated field — and it was big-endian and living in `avif/
|
|
1782
|
+
per truncated field — and it was big-endian and living in `format/image/avif/isobmff/`. The alternatives
|
|
905
1783
|
were both worse: `BinaryBuffer` is a growable stream whose reads throw `RangeError` from a
|
|
906
1784
|
`DataView` rather than naming the field that ran out, and a second cursor in `ktx2/` would have
|
|
907
1785
|
been the fourth copy of bounds-checked reading in this tree. **Endianness is a property of the
|
|
@@ -909,7 +1787,7 @@ it, and two of them are changes to existing code:
|
|
|
909
1787
|
which is also why no AVIF accessor call site changed, only the ten places that construct a
|
|
910
1788
|
cursor, two of them outside tests. (The commit message says "four". It is wrong; this is the
|
|
911
1789
|
count.)
|
|
912
|
-
[D10](../../../avif/
|
|
1790
|
+
[D10](../../../format/image/avif/DECISIONS.md) is amended to record this; the decision it made — read
|
|
913
1791
|
with a cursor, write with `BinaryBuffer` — is untouched.
|
|
914
1792
|
- **`gpu_texture_format_is_block_compressed` exists, and not where §2 put it.** §2 listed it under
|
|
915
1793
|
`renderer/texture/format/`. That was wrong twice over: it is a fact about the format table, so it
|
|
@@ -945,8 +1823,13 @@ than uploading garbage. Zstandard stays refused because there is no decompressor
|
|
|
945
1823
|
BasisLZ stays refused because it is not a wrapper — it is an encoding with its own codebooks, and
|
|
946
1824
|
undoing it is a transcoder.
|
|
947
1825
|
|
|
1826
|
+
> **Both of those refusals are gone now.** BasisLZ became step 9's transcoder, and step 9b wrote the
|
|
1827
|
+
> Zstandard decompressor this section said did not exist — see §9.12 for why that stopped being
|
|
1828
|
+
> optional. The reasoning above is left as it was written: it was right about the *kind* of thing
|
|
1829
|
+
> each is, and being right about that is what made both of them tractable when the time came.
|
|
1830
|
+
|
|
948
1831
|
**`pako.inflate` directly rather than
|
|
949
|
-
[`png_inflate`](../../../
|
|
1832
|
+
[`png_inflate`](../../../format/image/png/png_inflate.js).** What that function adds
|
|
950
1833
|
over the bare call is PNG's two peculiarities: a stream split across `IDAT` chunks, and a fallback
|
|
951
1834
|
that abandons the adler32 check because real encoders get it wrong. A KTX2 level is one stream, and a
|
|
952
1835
|
texture payload whose checksum fails should fail. Reusing it would have meant a KTX2 reader importing
|