@forgeax/engine-codec 0.0.0-dev.8d955ade1c79
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/LICENSE +202 -0
- package/README.md +261 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/__tests__/basis-encode-fast-preset.unit.test.d.ts +2 -0
- package/dist/__tests__/basis-encode-fast-preset.unit.test.d.ts.map +1 -0
- package/dist/__tests__/basis-encode-lifecycle.unit.test.d.ts +2 -0
- package/dist/__tests__/basis-encode-lifecycle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/basis-transcoder.unit.test.d.ts +2 -0
- package/dist/__tests__/basis-transcoder.unit.test.d.ts.map +1 -0
- package/dist/__tests__/block-format.unit.test.d.ts +2 -0
- package/dist/__tests__/block-format.unit.test.d.ts.map +1 -0
- package/dist/__tests__/byte-identical-falsification.test.d.ts +2 -0
- package/dist/__tests__/byte-identical-falsification.test.d.ts.map +1 -0
- package/dist/__tests__/codec-errors.test-d.d.ts +2 -0
- package/dist/__tests__/codec-errors.test-d.d.ts.map +1 -0
- package/dist/__tests__/codec-errors.unit.test.d.ts +2 -0
- package/dist/__tests__/codec-errors.unit.test.d.ts.map +1 -0
- package/dist/__tests__/compression-field.unit.test.d.ts +19 -0
- package/dist/__tests__/compression-field.unit.test.d.ts.map +1 -0
- package/dist/__tests__/encode-pixel-limit.unit.test.d.ts +2 -0
- package/dist/__tests__/encode-pixel-limit.unit.test.d.ts.map +1 -0
- package/dist/__tests__/encode-roundtrip.unit.test.d.ts +2 -0
- package/dist/__tests__/encode-roundtrip.unit.test.d.ts.map +1 -0
- package/dist/__tests__/ktx2-basis-capability-matrix.unit.test.d.ts +2 -0
- package/dist/__tests__/ktx2-basis-capability-matrix.unit.test.d.ts.map +1 -0
- package/dist/__tests__/ktx2-errors.test.d.ts +2 -0
- package/dist/__tests__/ktx2-errors.test.d.ts.map +1 -0
- package/dist/__tests__/ktx2-parse-scheme0.test.d.ts +2 -0
- package/dist/__tests__/ktx2-parse-scheme0.test.d.ts.map +1 -0
- package/dist/__tests__/ktx2-parse-scheme2.test.d.ts +2 -0
- package/dist/__tests__/ktx2-parse-scheme2.test.d.ts.map +1 -0
- package/dist/__tests__/ktx2-scheme1-and-transcode-errors.unit.test.d.ts +2 -0
- package/dist/__tests__/ktx2-scheme1-and-transcode-errors.unit.test.d.ts.map +1 -0
- package/dist/__tests__/ktx2-to-texture.integration.test.d.ts +2 -0
- package/dist/__tests__/ktx2-to-texture.integration.test.d.ts.map +1 -0
- package/dist/__tests__/transcode-select-target.unit.test.d.ts +2 -0
- package/dist/__tests__/transcode-select-target.unit.test.d.ts.map +1 -0
- package/dist/__tests__/wasm-init-smoke.test.d.ts +2 -0
- package/dist/__tests__/wasm-init-smoke.test.d.ts.map +1 -0
- package/dist/__tests__/zstd-deterministic.unit.test.d.ts +2 -0
- package/dist/__tests__/zstd-deterministic.unit.test.d.ts.map +1 -0
- package/dist/__tests__/zstd-encode-singleton.unit.test.d.ts +2 -0
- package/dist/__tests__/zstd-encode-singleton.unit.test.d.ts.map +1 -0
- package/dist/__tests__/zstd-roundtrip.unit.test.d.ts +2 -0
- package/dist/__tests__/zstd-roundtrip.unit.test.d.ts.map +1 -0
- package/dist/__tests__/zstd-singleton.unit.test.d.ts +2 -0
- package/dist/__tests__/zstd-singleton.unit.test.d.ts.map +1 -0
- package/dist/basis-transcoder.d.ts +86 -0
- package/dist/basis-transcoder.d.ts.map +1 -0
- package/dist/block-format.d.ts +41 -0
- package/dist/block-format.d.ts.map +1 -0
- package/dist/encode/basis-encode.d.ts +68 -0
- package/dist/encode/basis-encode.d.ts.map +1 -0
- package/dist/encode/index.d.ts +10 -0
- package/dist/encode/index.d.ts.map +1 -0
- package/dist/encode/index.mjs +207 -0
- package/dist/encode/index.mjs.map +1 -0
- package/dist/encode-impl.d.ts +30 -0
- package/dist/encode-impl.d.ts.map +1 -0
- package/dist/errors.d.ts +61 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +610 -0
- package/dist/index.mjs.map +1 -0
- package/dist/ktx2.d.ts +111 -0
- package/dist/ktx2.d.ts.map +1 -0
- package/dist/transcode.d.ts +55 -0
- package/dist/transcode.d.ts.map +1 -0
- package/dist/wasm/basis-types.d.ts +179 -0
- package/dist/wasm/basis-types.d.ts.map +1 -0
- package/dist/zstd.d.ts +28 -0
- package/dist/zstd.d.ts.map +1 -0
- package/package.json +71 -0
- package/pkg/basis_transcoder.mjs +2 -0
- package/pkg/basis_transcoder.wasm +0 -0
- package/pkg/encode/basis_encoder.mjs +2 -0
- package/pkg/encode/basis_encoder.wasm +0 -0
- package/scripts/build-wasm.mjs +370 -0
- package/scripts/content-key.mjs +85 -0
- package/scripts/ensure-wasm.mjs +38 -0
- package/scripts/fetch-basis.mjs +150 -0
- package/scripts/fetch-wasm.mjs +97 -0
- package/src/__tests__/basis-encode-fast-preset.unit.test.ts +204 -0
- package/src/__tests__/basis-encode-lifecycle.unit.test.ts +249 -0
- package/src/__tests__/basis-transcoder.unit.test.ts +151 -0
- package/src/__tests__/block-format.unit.test.ts +215 -0
- package/src/__tests__/byte-identical-falsification.test.ts +164 -0
- package/src/__tests__/codec-errors.test-d.ts +67 -0
- package/src/__tests__/codec-errors.unit.test.ts +128 -0
- package/src/__tests__/compression-field.unit.test.ts +245 -0
- package/src/__tests__/encode-pixel-limit.unit.test.ts +117 -0
- package/src/__tests__/encode-roundtrip.unit.test.ts +239 -0
- package/src/__tests__/ktx2-basis-capability-matrix.unit.test.ts +241 -0
- package/src/__tests__/ktx2-errors.test.ts +239 -0
- package/src/__tests__/ktx2-parse-scheme0.test.ts +263 -0
- package/src/__tests__/ktx2-parse-scheme2.test.ts +220 -0
- package/src/__tests__/ktx2-scheme1-and-transcode-errors.unit.test.ts +178 -0
- package/src/__tests__/ktx2-to-texture.integration.test.ts +384 -0
- package/src/__tests__/transcode-select-target.unit.test.ts +167 -0
- package/src/__tests__/wasm-init-smoke.test.ts +102 -0
- package/src/__tests__/zstd-deterministic.unit.test.ts +49 -0
- package/src/__tests__/zstd-encode-singleton.unit.test.ts +63 -0
- package/src/__tests__/zstd-roundtrip.unit.test.ts +87 -0
- package/src/__tests__/zstd-singleton.unit.test.ts +105 -0
- package/src/basis-transcoder.ts +315 -0
- package/src/block-format.ts +128 -0
- package/src/encode/basis-encode.ts +264 -0
- package/src/encode/index.ts +19 -0
- package/src/encode-impl.ts +103 -0
- package/src/errors.ts +79 -0
- package/src/index.ts +38 -0
- package/src/ktx2.ts +469 -0
- package/src/transcode.ts +99 -0
- package/src/wasm/basis-types.ts +220 -0
- package/src/zstd.ts +85 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basis-encode-fast-preset.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/basis-encode-fast-preset.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basis-encode-lifecycle.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/basis-encode-lifecycle.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basis-transcoder.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/basis-transcoder.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-format.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/block-format.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"byte-identical-falsification.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/byte-identical-falsification.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec-errors.test-d.d.ts","sourceRoot":"","sources":["../../src/__tests__/codec-errors.test-d.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec-errors.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/codec-errors.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* w9 TDD: compression field type-domain + no-as access (AC-01).
|
|
3
|
+
*
|
|
4
|
+
* Validates that AssetCompression union type = 'none' | 'zstd' appears at all
|
|
5
|
+
* 5 field locations (research Finding 1), and that consumption paths never
|
|
6
|
+
* require `as` assertion.
|
|
7
|
+
*
|
|
8
|
+
* TDD red state: these tests encode the expected structural contract. After
|
|
9
|
+
* w12 adds the real `compression` fields to types/index.ts and asset-registry.ts,
|
|
10
|
+
* the runtime assertions pass (no TS compile errors, field access without `as`).
|
|
11
|
+
*
|
|
12
|
+
* Strategy: define local mirror types matching the expected API shape, then
|
|
13
|
+
* verify that the shape itself is correct. After w12 lands, the real types
|
|
14
|
+
* will match this contract; the test stays structurally green.
|
|
15
|
+
*
|
|
16
|
+
* D-10: all fixtures programmatic, no binary files.
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=compression-field.unit.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compression-field.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/compression-field.unit.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encode-pixel-limit.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/encode-pixel-limit.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encode-roundtrip.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/encode-roundtrip.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ktx2-basis-capability-matrix.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ktx2-basis-capability-matrix.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ktx2-errors.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ktx2-errors.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ktx2-parse-scheme0.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ktx2-parse-scheme0.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ktx2-parse-scheme2.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ktx2-parse-scheme2.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ktx2-scheme1-and-transcode-errors.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ktx2-scheme1-and-transcode-errors.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ktx2-to-texture.integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ktx2-to-texture.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcode-select-target.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/transcode-select-target.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasm-init-smoke.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/wasm-init-smoke.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zstd-deterministic.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/zstd-deterministic.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zstd-encode-singleton.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/zstd-encode-singleton.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zstd-roundtrip.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/zstd-roundtrip.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zstd-singleton.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/zstd-singleton.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basis transcoder glue: lazy-init singleton (D-10) + per-mip KTX2 transcode.
|
|
3
|
+
*
|
|
4
|
+
* `initBasisTranscoder` dynamic-imports the self-built transcoder WASM module on
|
|
5
|
+
* first call and caches it; the second call returns the same instance without
|
|
6
|
+
* re-importing (D-10 main-thread lazy-init -- `Engine.create` does not preload,
|
|
7
|
+
* the first Basis payload triggers this). No worker pool (OOS -- forgeax has no
|
|
8
|
+
* worker infrastructure). Both node and browser can `import` this module: the
|
|
9
|
+
* WASM glue is a MODULARIZE factory whose `.mjs` path resolves in both.
|
|
10
|
+
*
|
|
11
|
+
* `transcodeKtx2` opens a parsed KTX2 container's raw bytes as a basis KTX2File,
|
|
12
|
+
* starts transcoding, and transcodes every mip level (mip-major) into the target
|
|
13
|
+
* `GPUTextureFormat`. It returns the block (or pixel) byte arrays per level; it
|
|
14
|
+
* does not upload -- the runtime upload path (M5) consumes these with the block
|
|
15
|
+
* table.
|
|
16
|
+
*/
|
|
17
|
+
import type { CodecResult } from './errors.js';
|
|
18
|
+
import type { Ktx2Parsed } from './ktx2.js';
|
|
19
|
+
import type { BasisFile, BasisTranscoderModule } from './wasm/basis-types.js';
|
|
20
|
+
/** How the transcoder WASM module is loaded. Overridable in tests. */
|
|
21
|
+
type TranscoderImporter = () => Promise<BasisTranscoderModule>;
|
|
22
|
+
/**
|
|
23
|
+
* Lazy-init the Basis transcoder WASM module (D-10 main-thread singleton).
|
|
24
|
+
* First call dynamic-imports + initializes; subsequent calls return the cache.
|
|
25
|
+
*/
|
|
26
|
+
export declare function initBasisTranscoder(): Promise<BasisTranscoderModule>;
|
|
27
|
+
/**
|
|
28
|
+
* Test-only: number of times the transcoder importer has been invoked. Proves
|
|
29
|
+
* the lazy singleton loads the module at most once (D-10).
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
export declare function _basisTranscoderInitCount(): number;
|
|
33
|
+
/**
|
|
34
|
+
* Test-only: reset the lazy singleton and optionally override the importer.
|
|
35
|
+
* Call with no argument to restore the real WASM importer.
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
export declare function _setBasisTranscoderImporter(next?: TranscoderImporter): void;
|
|
39
|
+
/** One transcoded mip level (mip-major output). */
|
|
40
|
+
export interface TranscodedMip {
|
|
41
|
+
readonly level: number;
|
|
42
|
+
readonly width: number;
|
|
43
|
+
readonly height: number;
|
|
44
|
+
/** Transcoded block (compressed) or pixel (uncompressed) bytes for this level. */
|
|
45
|
+
readonly data: Uint8Array;
|
|
46
|
+
}
|
|
47
|
+
/** Result of transcoding a KTX2 container into a target GPU format. */
|
|
48
|
+
export interface TranscodedTexture {
|
|
49
|
+
readonly format: GPUTextureFormat;
|
|
50
|
+
readonly width: number;
|
|
51
|
+
readonly height: number;
|
|
52
|
+
/** Mip levels, base (level 0 / largest) first. */
|
|
53
|
+
readonly mips: readonly TranscodedMip[];
|
|
54
|
+
}
|
|
55
|
+
export interface BasisSourceMeta {
|
|
56
|
+
readonly colorSpace: 'srgb' | 'linear';
|
|
57
|
+
}
|
|
58
|
+
export interface BasisSourceInspection {
|
|
59
|
+
readonly colorSpace: BasisSourceMeta['colorSpace'];
|
|
60
|
+
readonly profile: 'etc1s' | 'uastc-ldr';
|
|
61
|
+
readonly width: number;
|
|
62
|
+
readonly height: number;
|
|
63
|
+
readonly levelCount: number;
|
|
64
|
+
readonly imageCount: number;
|
|
65
|
+
}
|
|
66
|
+
/** Result of transcoding a raw Basis file into one engine texture format. */
|
|
67
|
+
export interface TranscodedBasisTexture {
|
|
68
|
+
readonly format: GPUTextureFormat;
|
|
69
|
+
readonly width: number;
|
|
70
|
+
readonly height: number;
|
|
71
|
+
readonly mips: readonly TranscodedMip[];
|
|
72
|
+
}
|
|
73
|
+
/** Inspect a raw Basis source without inferring color from the binary payload. */
|
|
74
|
+
export declare function inspectBasisSource(file: BasisFile, meta: Partial<BasisSourceMeta>, profile: BasisSourceInspection['profile']): CodecResult<BasisSourceInspection>;
|
|
75
|
+
/**
|
|
76
|
+
* Transcode every mip level of a parsed KTX2 container into `targetFormat`.
|
|
77
|
+
*
|
|
78
|
+
* Uses `parsed.rawBytes` as the basis KTX2File source. Returns one entry per mip
|
|
79
|
+
* level (base first). On any basis-side failure returns a `transcode-failed`
|
|
80
|
+
* CodecError carrying the source DFD color model and the target format.
|
|
81
|
+
*/
|
|
82
|
+
export declare function transcodeKtx2(parsed: Ktx2Parsed, targetFormat: GPUTextureFormat): Promise<CodecResult<TranscodedTexture>>;
|
|
83
|
+
/** Transcode a raw `.basis` file; source color remains a Meta author fact. */
|
|
84
|
+
export declare function transcodeBasis(bytes: Uint8Array, targetFormat: GPUTextureFormat): Promise<CodecResult<TranscodedBasisTexture>>;
|
|
85
|
+
export {};
|
|
86
|
+
//# sourceMappingURL=basis-transcoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basis-transcoder.d.ts","sourceRoot":"","sources":["../src/basis-transcoder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAsB,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAElG,sEAAsE;AACtE,KAAK,kBAAkB,GAAG,MAAM,OAAO,CAAC,qBAAqB,CAAC,CAAC;AA4B/D;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAQpE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAI3E;AAED,mDAAmD;AACnD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;CAC3B;AAED,uEAAuE;AACvE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,CAAC;CACxC;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;IACnD,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,6EAA6E;AAC7E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,CAAC;CACzC;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,OAAO,CAAC,eAAe,CAAC,EAC9B,OAAO,EAAE,qBAAqB,CAAC,SAAS,CAAC,GACxC,WAAW,CAAC,qBAAqB,CAAC,CAoBpC;AAuCD;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,gBAAgB,GAC7B,OAAO,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC,CA2DzC;AAED,8EAA8E;AAC9E,wBAAsB,cAAc,CAClC,KAAK,EAAE,UAAU,EACjB,YAAY,EAAE,gBAAgB,GAC7B,OAAO,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC,CAmD9C"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Block-compressed texture format parameter table (D-6 shared SSOT).
|
|
3
|
+
*
|
|
4
|
+
* One table maps every WebGPU block-compressed `GPUTextureFormat` to its
|
|
5
|
+
* texel-block dimensions and compressed bytes-per-block. Both the texture
|
|
6
|
+
* upload path and the equirect upload path (M5) derive `bytesPerRow` /
|
|
7
|
+
* `rowsPerImage` from this single table -- block math is defined once
|
|
8
|
+
* (Derive, Don't Duplicate).
|
|
9
|
+
*
|
|
10
|
+
* Format list follows the WebGPU spec "Compressed Texture Formats" section.
|
|
11
|
+
* PVRTC and ASTC-HDR are intentionally absent (OOS-5 / not exposed by WebGPU
|
|
12
|
+
* core). Uncompressed formats are not in the table -- callers branch on
|
|
13
|
+
* `isCompressedFormat` first and handle the linear `width * bytesPerPixel`
|
|
14
|
+
* case themselves.
|
|
15
|
+
*/
|
|
16
|
+
/** Texel-block dimensions + compressed size for one block-compressed format. */
|
|
17
|
+
export interface BlockParams {
|
|
18
|
+
readonly blockW: number;
|
|
19
|
+
readonly blockH: number;
|
|
20
|
+
readonly bytesPerBlock: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Look up the block parameters for a format. Returns `null` for uncompressed
|
|
24
|
+
* formats (the table only holds block-compressed entries).
|
|
25
|
+
*/
|
|
26
|
+
export declare function blockParamsForFormat(format: GPUTextureFormat): BlockParams | null;
|
|
27
|
+
/** Guard: true iff `format` is a block-compressed format in the table. */
|
|
28
|
+
export declare function isCompressedFormat(format: GPUTextureFormat): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Bytes per row for a compressed mip level of the given pixel width:
|
|
31
|
+
* `ceil(width / blockW) * bytesPerBlock`. Tail texels pad up to a full block.
|
|
32
|
+
* Returns `null` for uncompressed formats (no block entry) -- callers branch on
|
|
33
|
+
* `isCompressedFormat` first.
|
|
34
|
+
*/
|
|
35
|
+
export declare function bytesPerRow(format: GPUTextureFormat, width: number): number | null;
|
|
36
|
+
/**
|
|
37
|
+
* Block rows for a compressed mip level of the given pixel height:
|
|
38
|
+
* `ceil(height / blockH)`. Returns `null` for uncompressed formats.
|
|
39
|
+
*/
|
|
40
|
+
export declare function rowsPerImage(format: GPUTextureFormat, height: number): number | null;
|
|
41
|
+
//# sourceMappingURL=block-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-format.d.ts","sourceRoot":"","sources":["../src/block-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAyED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,GAAG,WAAW,GAAG,IAAI,CAEjF;AAED,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIlF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIpF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Low-level basis encoder binding (build-time, D-5): raw pixels -> Basis KTX2.
|
|
3
|
+
*
|
|
4
|
+
* `basisEncode` wraps the self-built encoder WASM (scripts/build-wasm.mjs ->
|
|
5
|
+
* pkg/encode/basis_encoder.{mjs,wasm}) with a Result-returning function over the
|
|
6
|
+
* three delivery encodings this Loop produces (ETC1S / UASTC-LDR-4x4 /
|
|
7
|
+
* UASTC-HDR-4x4). It is the codec-side counterpart of `compressZstd`: it lives
|
|
8
|
+
* in the `@forgeax/engine-codec/encode` subpath (isolation path d guards runtime
|
|
9
|
+
* from statically importing it), and it carries the WASM + enum plumbing so the
|
|
10
|
+
* image-side arm (`encodeTextureToKtx2`, w18) can stay pure image semantics.
|
|
11
|
+
*
|
|
12
|
+
* Determinism (AC-02 / R-11): pthreads are disabled at build time and the
|
|
13
|
+
* per-encode threading is turned off here (`controlThreading(false, 0)`), so the
|
|
14
|
+
* same pixels + same options encode byte-identically. KTX2 carries no timestamp.
|
|
15
|
+
*
|
|
16
|
+
* Lazy-init (D-10, mirrors basis-transcoder): the encoder WASM module is
|
|
17
|
+
* dynamic-imported on the first encode and cached; subsequent encodes reuse the
|
|
18
|
+
* instance. The module .mjs is a MODULARIZE factory, node-legal here (build-time
|
|
19
|
+
* only, never bundled into the browser runtime by the isolation gate).
|
|
20
|
+
*/
|
|
21
|
+
import type { CodecResult } from '../errors.js';
|
|
22
|
+
import type { TranscodeModel } from '../transcode.js';
|
|
23
|
+
import type { BasisEncoderModule } from '../wasm/basis-types.js';
|
|
24
|
+
/** Which delivery encoding to produce. Mirrors the transcode source models (D-3). */
|
|
25
|
+
export type BasisEncodeMode = TranscodeModel;
|
|
26
|
+
/** Encode options -- pixel layout + delivery encoding + transfer / mip flags. */
|
|
27
|
+
export interface BasisEncodeOptions {
|
|
28
|
+
readonly mode: BasisEncodeMode;
|
|
29
|
+
readonly width: number;
|
|
30
|
+
readonly height: number;
|
|
31
|
+
/** Write the sRGB transfer function into the KTX2 + DFD (LDR color only). */
|
|
32
|
+
readonly srgb: boolean;
|
|
33
|
+
/** ETC1S perceptual (sRGB) error metric vs linear PSNR. Ignored for UASTC. */
|
|
34
|
+
readonly perceptual: boolean;
|
|
35
|
+
/** Wrap the UASTC-LDR payload in KTX2 zstd supercompression. Ignored otherwise. */
|
|
36
|
+
readonly uastcSupercompression: boolean;
|
|
37
|
+
/** Generate a mip chain in the encoder. M3 keeps this false (offline mips are w18/M5). */
|
|
38
|
+
readonly mipGen: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** How the encoder WASM module is loaded. Overridable in tests. @internal */
|
|
41
|
+
type EncoderImporter = () => Promise<BasisEncoderModule>;
|
|
42
|
+
/**
|
|
43
|
+
* Lazy-init the Basis encoder WASM module (D-10 main-thread singleton).
|
|
44
|
+
* First call dynamic-imports + initializes; subsequent calls return the cache.
|
|
45
|
+
*/
|
|
46
|
+
export declare function initBasisEncoder(): Promise<BasisEncoderModule>;
|
|
47
|
+
/**
|
|
48
|
+
* Test-only: number of times the encoder importer has been invoked.
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
export declare function _basisEncoderInitCount(): number;
|
|
52
|
+
/**
|
|
53
|
+
* Test-only: reset the lazy singleton and optionally override the importer.
|
|
54
|
+
* Call with no argument to restore the real WASM importer.
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
export declare function _setBasisEncoderImporter(next?: EncoderImporter): void;
|
|
58
|
+
/**
|
|
59
|
+
* Encode raw pixels into a Basis KTX2 container.
|
|
60
|
+
*
|
|
61
|
+
* `pixels` is tight-packed RGBA: 8-bit `R,G,B,A` per texel for LDR modes
|
|
62
|
+
* (`etc1s` / `uastc-ldr`), IEEE-754 binary16 RGBA (rgba16float bytes) for
|
|
63
|
+
* `uastc-hdr`. On any encoder-side failure returns a `ktx2-encode-failed`
|
|
64
|
+
* CodecError carrying the mode + a short reason.
|
|
65
|
+
*/
|
|
66
|
+
export declare function basisEncode(pixels: Uint8Array, options: BasisEncodeOptions): Promise<CodecResult<Uint8Array>>;
|
|
67
|
+
export {};
|
|
68
|
+
//# sourceMappingURL=basis-encode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basis-encode.d.ts","sourceRoot":"","sources":["../../src/encode/basis-encode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAgB,kBAAkB,EAAsB,MAAM,wBAAwB,CAAC;AAEnG,qFAAqF;AACrF,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC;AAoC7C,iFAAiF;AACjF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,mFAAmF;IACnF,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;IACxC,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,6EAA6E;AAC7E,KAAK,eAAe,GAAG,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAwBzD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAQ9D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,CAAC,EAAE,eAAe,GAAG,IAAI,CAIrE;AAeD;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAuGlC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @forgeax/engine-codec/encode
|
|
3
|
+
*
|
|
4
|
+
* Build-time encoding subpath: zstd compression + Basis KTX2 texture encode.
|
|
5
|
+
* Gated from runtime import by `check-image-pipeline-isolation.mjs` path d.
|
|
6
|
+
*/
|
|
7
|
+
export { _setZstdEncoderImporter, _zstdEncodeInitCount, compressZstd, } from '../encode-impl.js';
|
|
8
|
+
export type { BasisEncodeMode, BasisEncodeOptions } from './basis-encode.js';
|
|
9
|
+
export { _basisEncoderInitCount, _setBasisEncoderImporter, basisEncode, initBasisEncoder, } from './basis-encode.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/encode/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,WAAW,EACX,gBAAgB,GACjB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
|
|
3
|
+
// src/encode-impl.ts
|
|
4
|
+
|
|
5
|
+
// src/errors.ts
|
|
6
|
+
function codecError(code, detail) {
|
|
7
|
+
const hints = {
|
|
8
|
+
"decompression-failed": "Check catalog row compression field and asset binary consistency; re-run asset import.",
|
|
9
|
+
"codec-init-failed": "Uncompressed assets are still loadable. Verify the codec module is installed correctly.",
|
|
10
|
+
"ktx2-parse-failed": "Check that the KTX2 file is valid and not truncated. Re-import the texture asset.",
|
|
11
|
+
"ktx2-unsupported-scheme": "This supercompression scheme requires a future codec upgrade. Check the codec README Loop 2 extension points.",
|
|
12
|
+
"transcode-failed": "Basis transcode failed for this source/target format pair. Verify the KTX2 payload is a valid Basis (ETC1S / UASTC) texture and re-import the asset.",
|
|
13
|
+
"ktx2-encode-failed": "Basis encode failed for this compression mode. Verify the source image dimensions / pixel format match the mode (LDR rgba8 vs HDR rgba16float) and retry the asset import."
|
|
14
|
+
};
|
|
15
|
+
return {
|
|
16
|
+
ok: false,
|
|
17
|
+
error: {
|
|
18
|
+
code,
|
|
19
|
+
expected: "valid compressed data or supported compression scheme",
|
|
20
|
+
hint: hints[code],
|
|
21
|
+
detail
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/encode-impl.ts
|
|
27
|
+
var zstdRequire = createRequire(import.meta.url);
|
|
28
|
+
var defaultImporter = () => zstdRequire("@bokuweb/zstd-wasm");
|
|
29
|
+
var importer = defaultImporter;
|
|
30
|
+
var _zstd = null;
|
|
31
|
+
var _initPromise = null;
|
|
32
|
+
var initCount = 0;
|
|
33
|
+
function getZstd() {
|
|
34
|
+
if (_zstd !== null) {
|
|
35
|
+
return Promise.resolve(_zstd);
|
|
36
|
+
}
|
|
37
|
+
if (_initPromise !== null) {
|
|
38
|
+
return _initPromise;
|
|
39
|
+
}
|
|
40
|
+
initCount++;
|
|
41
|
+
_initPromise = Promise.resolve().then(() => {
|
|
42
|
+
const mod = importer();
|
|
43
|
+
return mod.init().then(() => {
|
|
44
|
+
_zstd = mod;
|
|
45
|
+
return mod;
|
|
46
|
+
});
|
|
47
|
+
}).catch((cause) => {
|
|
48
|
+
_initPromise = null;
|
|
49
|
+
throw new Error("codec-init-failed", { cause });
|
|
50
|
+
});
|
|
51
|
+
return _initPromise;
|
|
52
|
+
}
|
|
53
|
+
function _zstdEncodeInitCount() {
|
|
54
|
+
return initCount;
|
|
55
|
+
}
|
|
56
|
+
function _setZstdEncoderImporter(next) {
|
|
57
|
+
importer = next ?? defaultImporter;
|
|
58
|
+
_zstd = null;
|
|
59
|
+
_initPromise = null;
|
|
60
|
+
initCount = 0;
|
|
61
|
+
}
|
|
62
|
+
async function compressZstd(bytes) {
|
|
63
|
+
try {
|
|
64
|
+
const zstd = await getZstd();
|
|
65
|
+
const result = zstd.compress(bytes, 3);
|
|
66
|
+
return { ok: true, value: result };
|
|
67
|
+
} catch (e) {
|
|
68
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
69
|
+
return codecError("decompression-failed", {
|
|
70
|
+
reason: `zstd compression failed: ${reason}`
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/encode/basis-encode.ts
|
|
76
|
+
var ETC1S_COMPRESSION_LEVEL_FASTEST = 0;
|
|
77
|
+
var PACK_UASTC_LDR_LEVEL_FASTEST = 0;
|
|
78
|
+
var UASTC_HDR_QUALITY_LEVEL_FASTEST = 0;
|
|
79
|
+
var ENCODER_GLUE = new URL("../../pkg/encode/basis_encoder.mjs", import.meta.url);
|
|
80
|
+
var ENCODER_WASM = new URL("../../pkg/encode/basis_encoder.wasm", import.meta.url);
|
|
81
|
+
var defaultImporter2 = async () => {
|
|
82
|
+
const factory = (await import(
|
|
83
|
+
/* @vite-ignore */
|
|
84
|
+
ENCODER_GLUE.href
|
|
85
|
+
)).default;
|
|
86
|
+
const mod = await factory({ locateFile: () => ENCODER_WASM.href });
|
|
87
|
+
mod.initializeBasis();
|
|
88
|
+
return mod;
|
|
89
|
+
};
|
|
90
|
+
var importer2 = defaultImporter2;
|
|
91
|
+
var _initPromise2 = null;
|
|
92
|
+
var initCount2 = 0;
|
|
93
|
+
function initBasisEncoder() {
|
|
94
|
+
if (_initPromise2 !== null) return _initPromise2;
|
|
95
|
+
initCount2++;
|
|
96
|
+
_initPromise2 = importer2().catch((cause) => {
|
|
97
|
+
_initPromise2 = null;
|
|
98
|
+
throw new Error("codec-init-failed", { cause });
|
|
99
|
+
});
|
|
100
|
+
return _initPromise2;
|
|
101
|
+
}
|
|
102
|
+
function _basisEncoderInitCount() {
|
|
103
|
+
return initCount2;
|
|
104
|
+
}
|
|
105
|
+
function _setBasisEncoderImporter(next) {
|
|
106
|
+
importer2 = next ?? defaultImporter2;
|
|
107
|
+
_initPromise2 = null;
|
|
108
|
+
initCount2 = 0;
|
|
109
|
+
}
|
|
110
|
+
function formatModeValue(mod, mode) {
|
|
111
|
+
const f = mod.basis_tex_format;
|
|
112
|
+
switch (mode) {
|
|
113
|
+
case "etc1s":
|
|
114
|
+
return f.cETC1S.value;
|
|
115
|
+
case "uastc-ldr":
|
|
116
|
+
return f.cUASTC_LDR_4x4.value;
|
|
117
|
+
case "uastc-hdr":
|
|
118
|
+
return f.cUASTC_HDR_4x4.value;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async function basisEncode(pixels, options) {
|
|
122
|
+
let mod;
|
|
123
|
+
try {
|
|
124
|
+
mod = await initBasisEncoder();
|
|
125
|
+
} catch {
|
|
126
|
+
return codecError("codec-init-failed", { stage: "dynamic-import-basis-encoder" });
|
|
127
|
+
}
|
|
128
|
+
const { mode, width, height, srgb, perceptual, uastcSupercompression, mipGen } = options;
|
|
129
|
+
if (width <= 0 || height <= 0) {
|
|
130
|
+
return codecError("ktx2-encode-failed", {
|
|
131
|
+
mode,
|
|
132
|
+
reason: `invalid dimensions ${width}x${height}`
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
let encoder;
|
|
136
|
+
try {
|
|
137
|
+
encoder = new mod.BasisEncoder();
|
|
138
|
+
} catch {
|
|
139
|
+
return codecError("ktx2-encode-failed", {
|
|
140
|
+
mode,
|
|
141
|
+
reason: "encoder constructor failed"
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
let result = codecError("ktx2-encode-failed", {
|
|
145
|
+
mode,
|
|
146
|
+
reason: "encoder returned 0 bytes"
|
|
147
|
+
});
|
|
148
|
+
try {
|
|
149
|
+
encoder.controlThreading(false, 0);
|
|
150
|
+
let sourceAccepted;
|
|
151
|
+
if (mode === "uastc-hdr") {
|
|
152
|
+
sourceAccepted = encoder.setSliceSourceImageHDR(0, pixels, width, height, 0, false, 1);
|
|
153
|
+
} else {
|
|
154
|
+
sourceAccepted = encoder.setSliceSourceImage(0, pixels, width, height, 0);
|
|
155
|
+
}
|
|
156
|
+
if (!sourceAccepted) {
|
|
157
|
+
result = codecError("ktx2-encode-failed", {
|
|
158
|
+
mode,
|
|
159
|
+
reason: mode === "uastc-hdr" ? "setSliceSourceImageHDR failed" : "setSliceSourceImage failed"
|
|
160
|
+
});
|
|
161
|
+
} else {
|
|
162
|
+
encoder.setCreateKTX2File(true);
|
|
163
|
+
encoder.setFormatMode(formatModeValue(mod, mode));
|
|
164
|
+
encoder.setMipGen(mipGen);
|
|
165
|
+
if (mode === "etc1s") {
|
|
166
|
+
encoder.setQualityLevel(128);
|
|
167
|
+
encoder.setETC1SCompressionLevel(ETC1S_COMPRESSION_LEVEL_FASTEST);
|
|
168
|
+
encoder.setPerceptual(perceptual);
|
|
169
|
+
} else if (mode === "uastc-ldr") {
|
|
170
|
+
encoder.setKTX2UASTCSupercompression(uastcSupercompression);
|
|
171
|
+
encoder.setPackUASTCFlags(PACK_UASTC_LDR_LEVEL_FASTEST);
|
|
172
|
+
encoder.setPerceptual(perceptual);
|
|
173
|
+
} else {
|
|
174
|
+
encoder.setUASTCHDRQualityLevel(UASTC_HDR_QUALITY_LEVEL_FASTEST);
|
|
175
|
+
}
|
|
176
|
+
encoder.setKTX2AndBasisSRGBTransferFunc(srgb);
|
|
177
|
+
let capacity = 1 << 22;
|
|
178
|
+
let out = new Uint8Array(capacity);
|
|
179
|
+
let n = encoder.encode(out);
|
|
180
|
+
if (n === 0) {
|
|
181
|
+
capacity = 1 << 25;
|
|
182
|
+
out = new Uint8Array(capacity);
|
|
183
|
+
n = encoder.encode(out);
|
|
184
|
+
}
|
|
185
|
+
if (n === 0) {
|
|
186
|
+
result = codecError("ktx2-encode-failed", { mode, reason: "encoder returned 0 bytes" });
|
|
187
|
+
} else {
|
|
188
|
+
result = { ok: true, value: out.slice(0, n) };
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
} catch (e) {
|
|
192
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
193
|
+
result = codecError("ktx2-encode-failed", { mode, reason });
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
encoder.delete();
|
|
197
|
+
} catch {
|
|
198
|
+
if (result.ok) {
|
|
199
|
+
result = codecError("ktx2-encode-failed", { mode, reason: "encoder cleanup failed" });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return result;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export { _basisEncoderInitCount, _setBasisEncoderImporter, _setZstdEncoderImporter, _zstdEncodeInitCount, basisEncode, compressZstd, initBasisEncoder };
|
|
206
|
+
//# sourceMappingURL=index.mjs.map
|
|
207
|
+
//# sourceMappingURL=index.mjs.map
|