gputex 0.4.0 → 0.6.0
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/README.md +121 -31
- package/dist/index.d.ts +330 -29
- package/dist/index.js +1815 -522
- package/dist/testing.d.ts +52 -15
- package/dist/testing.js +935 -109
- package/dist/three.d.ts +19 -69
- package/dist/three.js +1743 -666
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ declare const TextureFormat: {
|
|
|
6
6
|
readonly BC7_SRGB: "BC7_SRGB";
|
|
7
7
|
readonly ASTC_4x4: "ASTC_4x4";
|
|
8
8
|
readonly ASTC_4x4_SRGB: "ASTC_4x4_SRGB";
|
|
9
|
+
readonly ETC2_RGB8: "ETC2_RGB8";
|
|
10
|
+
readonly ETC2_RGB8_SRGB: "ETC2_RGB8_SRGB";
|
|
9
11
|
};
|
|
10
12
|
type TextureFormat = (typeof TextureFormat)[keyof typeof TextureFormat];
|
|
11
13
|
declare const WebGPUFeature: {
|
|
@@ -33,6 +35,31 @@ interface Capabilities {
|
|
|
33
35
|
}
|
|
34
36
|
declare function detectCapabilities(adapter: FeatureProvider): Capabilities;
|
|
35
37
|
|
|
38
|
+
/** One level of a mip chain. 4 bytes per pixel (RGBA8). */
|
|
39
|
+
interface MipLevel {
|
|
40
|
+
data: Uint8ClampedArray;
|
|
41
|
+
width: number;
|
|
42
|
+
height: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Produce the full mip chain from a level-0 image. The chain goes down
|
|
46
|
+
* to a 1×1 level — the standard OpenGL / WebGPU convention — so the
|
|
47
|
+
* caller gets `floor(log2(max(w, h))) + 1` levels total.
|
|
48
|
+
*
|
|
49
|
+
* Levels whose logical dimensions are below the encoder's 4×4 block
|
|
50
|
+
* grid are still produced here at their true logical size; padding up
|
|
51
|
+
* to a single block is the encoder's job, not ours.
|
|
52
|
+
*/
|
|
53
|
+
declare function generateMipChain(level0: MipLevel): MipLevel[];
|
|
54
|
+
/**
|
|
55
|
+
* Pad a mip level up to a multiple of 4 in each dimension using clamp-
|
|
56
|
+
* to-edge sampling. Used before handing sub-4×4 levels to a block-
|
|
57
|
+
* compression encoder, which requires at least one full block per level.
|
|
58
|
+
*
|
|
59
|
+
* If the input is already block-aligned this returns the input unchanged.
|
|
60
|
+
*/
|
|
61
|
+
declare function padToBlockMultiple(level: MipLevel): MipLevel;
|
|
62
|
+
|
|
36
63
|
/**
|
|
37
64
|
* Anything `GPUQueue.copyExternalImageToTexture` accepts. Matches the
|
|
38
65
|
* WebGPU spec's CopyExternalImageSource set.
|
|
@@ -54,17 +81,21 @@ interface EncodeCallOptions {
|
|
|
54
81
|
colorSpace?: 'srgb' | 'linear';
|
|
55
82
|
}
|
|
56
83
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* you like, or use
|
|
84
|
+
* One level of encoded output: the compressed block bytes plus logical and
|
|
85
|
+
* block-aligned dimensions. This is the encoder's native output shape, with
|
|
86
|
+
* no Three.js (or any engine) involvement — feed `data` into whatever
|
|
87
|
+
* renderer's compressed-texture upload you like, or use
|
|
88
|
+
* `buildCompressedTexture()` from `gputex/three`.
|
|
61
89
|
*/
|
|
62
|
-
interface
|
|
90
|
+
interface EncodedLevelBytes {
|
|
63
91
|
width: number;
|
|
64
92
|
height: number;
|
|
65
93
|
paddedWidth: number;
|
|
66
94
|
paddedHeight: number;
|
|
67
95
|
data: Uint8Array;
|
|
96
|
+
}
|
|
97
|
+
/** Result of a raw bytes-only single-image encode. */
|
|
98
|
+
interface EncodeBytesResult extends EncodedLevelBytes {
|
|
68
99
|
encodeMs: number;
|
|
69
100
|
/**
|
|
70
101
|
* GPU-side compute-pass time in ms, measured with timestamp queries.
|
|
@@ -75,6 +106,16 @@ interface EncodeBytesResult {
|
|
|
75
106
|
*/
|
|
76
107
|
gpuMs?: number;
|
|
77
108
|
}
|
|
109
|
+
/** Result of a whole-chain encode — see `Encoder.encodeMipChainToBytes()`. */
|
|
110
|
+
interface EncodeMipChainResult {
|
|
111
|
+
/** Encoded levels in the order given; `levels[0]` is the base level. */
|
|
112
|
+
levels: EncodedLevelBytes[];
|
|
113
|
+
/** Wall-clock time for the whole chain: uploads → dispatches → readback. */
|
|
114
|
+
encodeMs: number;
|
|
115
|
+
/** GPU compute time for the whole chain's single compute pass (see
|
|
116
|
+
* `EncodeBytesResult.gpuMs` for caveats). */
|
|
117
|
+
gpuMs?: number;
|
|
118
|
+
}
|
|
78
119
|
interface FormatVariant {
|
|
79
120
|
colorSpace: 'srgb' | 'linear';
|
|
80
121
|
}
|
|
@@ -116,16 +157,34 @@ declare abstract class Encoder {
|
|
|
116
157
|
readonly adapter?: GPUAdapter;
|
|
117
158
|
readonly ownsDevice: boolean;
|
|
118
159
|
readonly disableF16: boolean;
|
|
119
|
-
protected
|
|
160
|
+
protected _pipelineReady: Promise<GPUComputePipeline>;
|
|
161
|
+
protected _prepPipelineReady: Promise<GPUComputePipeline> | null;
|
|
120
162
|
private _cachedSrcTex;
|
|
121
163
|
private _cachedSrcW;
|
|
122
164
|
private _cachedSrcH;
|
|
165
|
+
private _cachedSrcSource;
|
|
166
|
+
private _cachedSrcFlipY;
|
|
123
167
|
private _cachedDst;
|
|
124
168
|
private _cachedStaging;
|
|
125
169
|
private _cachedParams;
|
|
126
170
|
private _lastParams;
|
|
127
171
|
private _cachedBindGroup;
|
|
172
|
+
private _cachedPrepPlanes;
|
|
173
|
+
private _cachedPrepBindGroup;
|
|
128
174
|
private _resourcesBusy;
|
|
175
|
+
/** Set when the active shader declares a @binding(3) sampler (the BC5
|
|
176
|
+
* kernels read texels through textureGather + clamp-to-edge). */
|
|
177
|
+
private _usesSampler;
|
|
178
|
+
private _sampler;
|
|
179
|
+
private _chainSig;
|
|
180
|
+
private _chainTextures;
|
|
181
|
+
private _chainPrepPlanes;
|
|
182
|
+
private _chainPrepBindGroups;
|
|
183
|
+
private _chainParams;
|
|
184
|
+
private _chainBindGroups;
|
|
185
|
+
private _chainDst;
|
|
186
|
+
private _chainStaging;
|
|
187
|
+
private _chainBusy;
|
|
129
188
|
constructor({ device, adapter, ownsDevice, disableF16 }: EncoderOptions);
|
|
130
189
|
protected _buildPipeline(): void;
|
|
131
190
|
destroy(): void;
|
|
@@ -133,10 +192,27 @@ declare abstract class Encoder {
|
|
|
133
192
|
abstract get label(): string;
|
|
134
193
|
/** 8 for BC1/BC4, 16 for BC5/BC7/ASTC 4×4. */
|
|
135
194
|
abstract get bytesPerBlock(): number;
|
|
195
|
+
/**
|
|
196
|
+
* Pipeline-creation override constants for the active shader, or
|
|
197
|
+
* undefined for none. Subclasses expose quality/behaviour toggles this
|
|
198
|
+
* way so the OFF state is dead-coded by the shader compiler instead of
|
|
199
|
+
* branched at runtime.
|
|
200
|
+
*/
|
|
201
|
+
protected pipelineConstants(): Record<string, number> | undefined;
|
|
136
202
|
/** WGSL `@workgroup_size` dimensions. Default 8×8×1. */
|
|
137
203
|
get workgroupSize(): readonly [number, number, number];
|
|
138
204
|
/** Whether this format has an sRGB variant. Default true. */
|
|
139
205
|
get supportsSrgb(): boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Format of the single-shot source texture the encode pass samples.
|
|
208
|
+
* Encoders that read only a channel subset can narrow it to cut DRAM
|
|
209
|
+
* traffic on the bandwidth-bound compute pass (BC5 reads rg8unorm — half
|
|
210
|
+
* the bytes of rgba8). Must be valid as a copyExternalImageToTexture
|
|
211
|
+
* destination and renderable. Chain encodes keep rgba8unorm regardless
|
|
212
|
+
* (their inputs are RGBA mip levels / texture views); the WGSL is
|
|
213
|
+
* format-agnostic (`texture_2d<f32>`), so mixing is byte-identical.
|
|
214
|
+
*/
|
|
215
|
+
protected get srcTextureFormat(): GPUTextureFormat;
|
|
140
216
|
/**
|
|
141
217
|
* Optional f16 WGSL variant. Used only when the device reports the
|
|
142
218
|
* `shader-f16` feature; the format's f32 `wgslSource()` is the automatic
|
|
@@ -147,6 +223,21 @@ declare abstract class Encoder {
|
|
|
147
223
|
protected get _useF16(): boolean;
|
|
148
224
|
/** WGSL compute-shader source (f32; the fallback when f16 is unavailable). */
|
|
149
225
|
abstract wgslSource(): string;
|
|
226
|
+
/** WGSL for the preparation pass, or null when the encoder reads the
|
|
227
|
+
* RGBA8 source directly. */
|
|
228
|
+
protected wgslPrepSource(): string | null;
|
|
229
|
+
/** Formats and sizes of the prepared planes for a padded source size. */
|
|
230
|
+
protected prepPlanes(paddedWidth: number, paddedHeight: number): {
|
|
231
|
+
format: GPUTextureFormat;
|
|
232
|
+
width: number;
|
|
233
|
+
height: number;
|
|
234
|
+
}[];
|
|
235
|
+
/** Workgroup counts for the prep dispatch. */
|
|
236
|
+
protected prepDispatch(blocksX: number, blocksY: number): [number, number];
|
|
237
|
+
/** Create the prepared-plane textures for one padded source size. */
|
|
238
|
+
private _createPrepPlanes;
|
|
239
|
+
/** Bind group for one prep dispatch. */
|
|
240
|
+
private _createPrepBindGroup;
|
|
150
241
|
/** e.g. 'bc1-rgba-unorm-srgb'. */
|
|
151
242
|
abstract gpuTextureFormat(opts: FormatVariant): GPUTextureFormat;
|
|
152
243
|
/**
|
|
@@ -166,6 +257,55 @@ declare abstract class Encoder {
|
|
|
166
257
|
flipY?: boolean;
|
|
167
258
|
withGpuTime?: boolean;
|
|
168
259
|
}): Promise<EncodeBytesResult>;
|
|
260
|
+
/**
|
|
261
|
+
* Encode a whole mip chain in ONE GPU submission. A per-level
|
|
262
|
+
* `encodeToBytes()` loop costs a full CPU↔GPU round trip per level (a
|
|
263
|
+
* 1024² chain is 11 levels → 11 `mapAsync` waits with the GPU idle in
|
|
264
|
+
* between); this path uploads every level, records one dispatch per level
|
|
265
|
+
* into a single compute pass, copies all outputs into one staging buffer
|
|
266
|
+
* and maps it once.
|
|
267
|
+
*
|
|
268
|
+
* `levels` are raw RGBA8 pixels in base-to-tail order; sizes don't have to
|
|
269
|
+
* halve level-to-level (each level is padded and clamped independently,
|
|
270
|
+
* exactly like `encodeToBytes`). Uploads use `writeTexture` — the direct
|
|
271
|
+
* raw-bytes path, which also sidesteps the broken
|
|
272
|
+
* `copyExternalImageToTexture` devices (see workarounds.ts). There is no
|
|
273
|
+
* flip option: bake any vertical flip into level 0 before generating the
|
|
274
|
+
* chain, as `compressTexture()` does.
|
|
275
|
+
*/
|
|
276
|
+
encodeMipChainToBytes(levels: readonly MipLevel[], { withGpuTime }?: {
|
|
277
|
+
withGpuTime?: boolean;
|
|
278
|
+
}): Promise<EncodeMipChainResult>;
|
|
279
|
+
/**
|
|
280
|
+
* Encode every mip level of a GPU-resident texture in one submission —
|
|
281
|
+
* the zero-CPU-pixels counterpart of `encodeMipChainToBytes()`. Pair it
|
|
282
|
+
* with `generateGpuMipChain()` (gpuMipgen.ts): upload the image once,
|
|
283
|
+
* box-filter the chain on the GPU, then encode straight from the
|
|
284
|
+
* texture's mip views. Pixels never transit the CPU between the source
|
|
285
|
+
* image and the compressed-bytes readback.
|
|
286
|
+
*
|
|
287
|
+
* `srcTex` must be `rgba8unorm` with TEXTURE_BINDING usage; level 0's
|
|
288
|
+
* dimensions are taken from the texture and lower levels follow the
|
|
289
|
+
* standard floor-halving chain. Encoded output is identical to feeding
|
|
290
|
+
* the equivalent CPU chain to `encodeMipChainToBytes()`.
|
|
291
|
+
*/
|
|
292
|
+
encodeMipChainFromTexture(srcTex: GPUTexture, { withGpuTime }?: {
|
|
293
|
+
withGpuTime?: boolean;
|
|
294
|
+
}): Promise<EncodeMipChainResult>;
|
|
295
|
+
/** Block-grid geometry + packed output offsets for a chain of levels.
|
|
296
|
+
* `byteSpan` is both the dst buffer size and the readback copy size (a
|
|
297
|
+
* multiple of 4: byteLen is a multiple of bytesPerBlock ≥ 8, offsets are
|
|
298
|
+
* CHAIN_ALIGN-ed). */
|
|
299
|
+
private _chainGeometry;
|
|
300
|
+
/** Shared chain-encode tail: one compute pass with a dispatch per level,
|
|
301
|
+
* one submit, one staging readback sliced into per-level byte arrays. */
|
|
302
|
+
private _submitChainAndRead;
|
|
303
|
+
/** Create the query set + resolve/staging buffers for one timed
|
|
304
|
+
* submission, or null when the device lacks 'timestamp-query'. */
|
|
305
|
+
private _createTiming;
|
|
306
|
+
/** Read back a timed submission's pass duration (ms) and destroy the
|
|
307
|
+
* timing objects. Timestamps are u64 nanoseconds. */
|
|
308
|
+
private _readTimingMs;
|
|
169
309
|
}
|
|
170
310
|
|
|
171
311
|
declare class BC1Encoder extends Encoder {
|
|
@@ -185,14 +325,26 @@ declare class BC5Encoder extends Encoder {
|
|
|
185
325
|
get label(): string;
|
|
186
326
|
get bytesPerBlock(): number;
|
|
187
327
|
get supportsSrgb(): boolean;
|
|
328
|
+
protected get srcTextureFormat(): GPUTextureFormat;
|
|
188
329
|
wgslSource(): string;
|
|
189
330
|
wgslSourceFastF16(): string;
|
|
190
331
|
gpuTextureFormat(): GPUTextureFormat;
|
|
191
332
|
}
|
|
192
333
|
|
|
334
|
+
interface BC7EncoderOptions extends EncoderOptions {
|
|
335
|
+
/**
|
|
336
|
+
* Emit BC7 mode 4 on decorrelated blocks (normal maps, channel-packed
|
|
337
|
+
* atlases): a large quality win there, at up to ~1.5× encode time on
|
|
338
|
+
* exactly that content. See the header note for the measurements.
|
|
339
|
+
*/
|
|
340
|
+
adaptiveMode4?: boolean;
|
|
341
|
+
}
|
|
193
342
|
declare class BC7Encoder extends Encoder {
|
|
194
343
|
static readonly requiredFeature: GPUFeatureName;
|
|
195
344
|
static readonly textureFormats: readonly TextureFormat[];
|
|
345
|
+
private readonly adaptiveMode4;
|
|
346
|
+
constructor(opts: BC7EncoderOptions);
|
|
347
|
+
protected pipelineConstants(): Record<string, number> | undefined;
|
|
196
348
|
get label(): string;
|
|
197
349
|
get bytesPerBlock(): number;
|
|
198
350
|
get supportsSrgb(): boolean;
|
|
@@ -212,6 +364,17 @@ declare class ASTC4x4Encoder extends Encoder {
|
|
|
212
364
|
gpuTextureFormat({ colorSpace }: FormatVariant): GPUTextureFormat;
|
|
213
365
|
}
|
|
214
366
|
|
|
367
|
+
declare class ETC2Encoder extends Encoder {
|
|
368
|
+
static readonly requiredFeature: GPUFeatureName;
|
|
369
|
+
static readonly textureFormats: readonly TextureFormat[];
|
|
370
|
+
get label(): string;
|
|
371
|
+
get bytesPerBlock(): number;
|
|
372
|
+
get supportsSrgb(): boolean;
|
|
373
|
+
wgslSource(): string;
|
|
374
|
+
wgslSourceFastF16(): string;
|
|
375
|
+
gpuTextureFormat({ colorSpace }: FormatVariant): GPUTextureFormat;
|
|
376
|
+
}
|
|
377
|
+
|
|
215
378
|
/** Raw RGBA8 pixel data (e.g. a CPU-generated mip level). */
|
|
216
379
|
interface RawPixelSource {
|
|
217
380
|
data: ArrayBufferView;
|
|
@@ -358,16 +521,26 @@ type TextureHint = 'color' | 'colorWithAlpha' | 'normal';
|
|
|
358
521
|
/**
|
|
359
522
|
* Optional format preference — a wish, not a demand. Applied when the
|
|
360
523
|
* device supports the format and the hint is compatible; otherwise
|
|
361
|
-
* selection proceeds normally (BC7 → ASTC → null). Currently only
|
|
524
|
+
* selection proceeds normally (BC7 → ASTC → ETC2 → null). Currently only
|
|
362
525
|
* 'bc1': half the memory of BC7 (0.5 vs 1 byte/pixel) for opaque
|
|
363
526
|
* colour, at visibly lower quality on smooth content.
|
|
364
527
|
*/
|
|
365
528
|
type PreferredFormat = 'bc1';
|
|
529
|
+
/**
|
|
530
|
+
* Memory/fidelity trade-off for opaque colour textures. 'high' (default)
|
|
531
|
+
* picks the 8-bpp formats (BC7 / ASTC 4×4); 'low' picks the 4-bpp ones
|
|
532
|
+
* (BC1 / ETC2 RGB8) when the adapter supports one. Hints that the 4-bpp
|
|
533
|
+
* formats can't carry ('colorWithAlpha', 'normal') ignore this and keep
|
|
534
|
+
* the 'high' selection.
|
|
535
|
+
*/
|
|
536
|
+
type FormatQuality = 'high' | 'low';
|
|
366
537
|
interface SelectFormatOptions {
|
|
367
538
|
/** Pick the sRGB variant when the format has one. Default 'srgb'. */
|
|
368
539
|
colorSpace?: 'srgb' | 'linear';
|
|
369
540
|
/** Prefer a specific format when supported. See `PreferredFormat`. */
|
|
370
541
|
preferredFormat?: PreferredFormat;
|
|
542
|
+
/** Memory/fidelity trade-off. See `FormatQuality`. Default 'high'. */
|
|
543
|
+
quality?: FormatQuality;
|
|
371
544
|
}
|
|
372
545
|
interface FormatSelection {
|
|
373
546
|
/** null = no compressed path on this adapter; caller should fall back. */
|
|
@@ -393,30 +566,21 @@ interface WebGLFormatSelection {
|
|
|
393
566
|
}
|
|
394
567
|
declare function selectWebGLFormat(caps: WebGLCapabilities, hint: TextureHint, options?: SelectFormatOptions): WebGLFormatSelection;
|
|
395
568
|
|
|
396
|
-
/**
|
|
397
|
-
|
|
398
|
-
data: Uint8ClampedArray;
|
|
399
|
-
width: number;
|
|
400
|
-
height: number;
|
|
401
|
-
}
|
|
569
|
+
/** Matches mipgen's chain length: floor(log2(max(w, h))) + 1 levels. */
|
|
570
|
+
declare function gpuMipLevelCount(width: number, height: number): number;
|
|
402
571
|
/**
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
572
|
+
* Upload `source` and generate its full mip chain on the GPU. Returns an
|
|
573
|
+
* `rgba8unorm` texture with `gpuMipLevelCount` levels whose dimensions
|
|
574
|
+
* follow the standard floor-halving chain; feed it to
|
|
575
|
+
* `Encoder.encodeMipChainFromTexture()`. The caller owns the texture —
|
|
576
|
+
* destroy it after encoding.
|
|
406
577
|
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
* to a single block is the encoder's job, not ours.
|
|
578
|
+
* The returned promise resolves once the work is submitted (not completed);
|
|
579
|
+
* queue ordering makes the levels visible to any later submission.
|
|
410
580
|
*/
|
|
411
|
-
declare function
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
* to-edge sampling. Used before handing sub-4×4 levels to a block-
|
|
415
|
-
* compression encoder, which requires at least one full block per level.
|
|
416
|
-
*
|
|
417
|
-
* If the input is already block-aligned this returns the input unchanged.
|
|
418
|
-
*/
|
|
419
|
-
declare function padToBlockMultiple(level: MipLevel): MipLevel;
|
|
581
|
+
declare function generateGpuMipChain(device: GPUDevice, source: ImageBitmap | ImageData | HTMLCanvasElement | OffscreenCanvas, { flipY }?: {
|
|
582
|
+
flipY?: boolean;
|
|
583
|
+
}): Promise<GPUTexture>;
|
|
420
584
|
|
|
421
585
|
/**
|
|
422
586
|
* Target raster size for an SVG source. A number scales the SVG so its
|
|
@@ -441,4 +605,141 @@ interface RasterizeSvgOptions {
|
|
|
441
605
|
*/
|
|
442
606
|
declare function rasterizeSvg(source: string | Blob, options?: RasterizeSvgOptions): Promise<ImageBitmap>;
|
|
443
607
|
|
|
444
|
-
|
|
608
|
+
/**
|
|
609
|
+
* Everything `compressTexture()` can take as an image source. A superset
|
|
610
|
+
* of `EncoderImageSource` (see Encoder.ts) that also accepts URL strings
|
|
611
|
+
* and Blob / File objects — the common cases in a web app.
|
|
612
|
+
*
|
|
613
|
+
* SVG works through all of these: a URL to an `.svg` file, a string of
|
|
614
|
+
* inline SVG markup (detected by a leading `<`), an SVG Blob/File, or an
|
|
615
|
+
* HTMLImageElement whose src is SVG. Vector sources are rasterised to RGBA
|
|
616
|
+
* before encoding — see the `svgSize` option.
|
|
617
|
+
*/
|
|
618
|
+
type CompressTextureSource = string | Blob | File | ImageBitmap | HTMLImageElement | HTMLCanvasElement | OffscreenCanvas | ImageData;
|
|
619
|
+
interface CompressOptions {
|
|
620
|
+
/** How the texture will be used. Drives format selection. Default 'color'. */
|
|
621
|
+
hint?: TextureHint;
|
|
622
|
+
/**
|
|
623
|
+
* Prefer a specific format over the default choice when the device
|
|
624
|
+
* supports it; falls back to the normal selection (BC7 → ASTC → ETC2 →
|
|
625
|
+
* RGBA8) when it doesn't. Currently only 'bc1': half the memory of BC7
|
|
626
|
+
* for opaque colour textures, at lower quality. Only honoured with
|
|
627
|
+
* `hint: 'color'` — BC1 can't carry real alpha or normal maps.
|
|
628
|
+
*/
|
|
629
|
+
preferredFormat?: PreferredFormat;
|
|
630
|
+
/**
|
|
631
|
+
* Memory/fidelity trade-off for opaque colour textures. Default 'high'
|
|
632
|
+
* (BC7 / ASTC 4×4, 1 byte/pixel). 'low' picks the 4-bpp formats when the
|
|
633
|
+
* device has one — BC1 on desktop-class GPUs, ETC2 RGB8 on mobile-class
|
|
634
|
+
* ones — halving GPU memory at visibly lower quality on smooth content.
|
|
635
|
+
* Ignored for `hint: 'colorWithAlpha'` and `hint: 'normal'` (the 4-bpp
|
|
636
|
+
* formats can't carry them). On the WebGL fallback tier only BC1 is
|
|
637
|
+
* available at 'low'.
|
|
638
|
+
*/
|
|
639
|
+
quality?: FormatQuality;
|
|
640
|
+
/** Pick the sRGB or linear variant of the chosen format. Default 'srgb'. */
|
|
641
|
+
colorSpace?: 'srgb' | 'linear';
|
|
642
|
+
/**
|
|
643
|
+
* Rasterisation size for SVG sources. A number scales the SVG so its
|
|
644
|
+
* longest side matches (aspect ratio preserved); `{ width, height }`
|
|
645
|
+
* rasterises at exactly that size. Default: the SVG's intrinsic size
|
|
646
|
+
* (absolute width/height attributes, else the viewBox dimensions).
|
|
647
|
+
* Ignored for non-SVG sources.
|
|
648
|
+
*/
|
|
649
|
+
svgSize?: SvgRasterSize;
|
|
650
|
+
/** Flip the image vertically before encoding. Default true (matches Three.js convention). */
|
|
651
|
+
flipY?: boolean;
|
|
652
|
+
/** Generate a full mip chain down to 1×1 on the CPU, encode every level. */
|
|
653
|
+
mipmaps?: boolean;
|
|
654
|
+
/** Reuse an existing device (e.g. Three.js's renderer device) instead
|
|
655
|
+
* of creating a new one. WebGPU path only. When provided, the encoder
|
|
656
|
+
* never destroys it. */
|
|
657
|
+
device?: GPUDevice;
|
|
658
|
+
adapter?: GPUAdapter;
|
|
659
|
+
/**
|
|
660
|
+
* Keep the compressed bytes in a session-scoped in-memory LRU and reuse
|
|
661
|
+
* them on repeat calls, skipping BOTH the image decode and the encode —
|
|
662
|
+
* the dominant costs. Re-loading a texture later in the session (e.g.
|
|
663
|
+
* two worlds sharing an atlas) becomes a few ms. Keyed by source
|
|
664
|
+
* identity + selected format + encode options; capped at 256 MiB of
|
|
665
|
+
* compressed bytes by default (`setTranscodeCacheLimit()` to tune) and
|
|
666
|
+
* never touches persistent storage. Default false.
|
|
667
|
+
*
|
|
668
|
+
* URL and Blob/File sources get an identity automatically (URL string or
|
|
669
|
+
* content hash). Pixel sources (ImageBitmap, canvas, ImageData) are only
|
|
670
|
+
* cached when `cacheKey` is provided.
|
|
671
|
+
*/
|
|
672
|
+
cache?: boolean;
|
|
673
|
+
/**
|
|
674
|
+
* Explicit cache identity for the source, overriding the derived one.
|
|
675
|
+
* Use when you already know a stable name (e.g. an asset path) and want
|
|
676
|
+
* to skip content hashing, or to make pixel sources cacheable.
|
|
677
|
+
*/
|
|
678
|
+
cacheKey?: string;
|
|
679
|
+
}
|
|
680
|
+
interface CompressResult {
|
|
681
|
+
/**
|
|
682
|
+
* Encoded compressed mip levels (`levels[0]` is the base level), ready to
|
|
683
|
+
* upload to a compressed texture. Null on the RGBA8 fallback path — use
|
|
684
|
+
* `fallbackBitmap` instead.
|
|
685
|
+
*/
|
|
686
|
+
levels: EncodedLevelBytes[] | null;
|
|
687
|
+
/**
|
|
688
|
+
* Decoded RGBA8 bitmap, set only when `fallbackUncompressed` (no compressed
|
|
689
|
+
* format was available on either backend). Upload it as a plain RGBA8
|
|
690
|
+
* texture; the caller applies colour space / flipY at the texture level.
|
|
691
|
+
*/
|
|
692
|
+
fallbackBitmap: ImageBitmap | null;
|
|
693
|
+
/** The compressed format selected, or null when we fell back to RGBA8. */
|
|
694
|
+
format: TextureFormat | null;
|
|
695
|
+
/** True iff we fell back to an uncompressed RGBA8 bitmap because no encoder fit. */
|
|
696
|
+
fallbackUncompressed: boolean;
|
|
697
|
+
/**
|
|
698
|
+
* Which backend produced the result. 'webgpu' = compute path, 'webgl' =
|
|
699
|
+
* fragment-shader fallback, 'none' = uncompressed RGBA8.
|
|
700
|
+
*/
|
|
701
|
+
backend: 'webgpu' | 'webgl' | 'none';
|
|
702
|
+
/**
|
|
703
|
+
* True iff the chosen format is ASTC and the hint was 'normal'. The
|
|
704
|
+
* caller must apply the (R, W) → (x, y) swizzle in the material — ASTC
|
|
705
|
+
* has no 2-channel mode, so normal maps ride the RGBA path.
|
|
706
|
+
*/
|
|
707
|
+
astcNormalRemap: boolean;
|
|
708
|
+
width: number;
|
|
709
|
+
height: number;
|
|
710
|
+
mipLevels: number;
|
|
711
|
+
/** Wall-clock time of GPU encoding, summed across mip levels. */
|
|
712
|
+
encodeMs: number;
|
|
713
|
+
/**
|
|
714
|
+
* Wall-clock time to turn the source into decoded RGBA pixels: fetch /
|
|
715
|
+
* base64 decode, image decode, SVG rasterisation. Usually the dominant
|
|
716
|
+
* cost for large images — when a load feels slower than `encodeMs`
|
|
717
|
+
* suggests, this is where the time went.
|
|
718
|
+
*/
|
|
719
|
+
decodeMs: number;
|
|
720
|
+
/** Wall-clock time of the whole `compressTexture()` call: decode + CPU
|
|
721
|
+
* mip generation + encode + texture assembly. */
|
|
722
|
+
totalMs: number;
|
|
723
|
+
/** True when the result came from the in-memory transcode cache (the
|
|
724
|
+
* `cache` option) — no decode or encode ran; decodeMs/encodeMs are 0. */
|
|
725
|
+
cacheHit: boolean;
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Destroy the WebGPU device and encoders that `compressTexture()` shares
|
|
729
|
+
* across calls (created lazily when neither the `device` nor the `adapter`
|
|
730
|
+
* option is passed). Safe to call at any time — in-flight encodes on the
|
|
731
|
+
* shared device will fail, and the next `compressTexture()` call recreates
|
|
732
|
+
* everything. No-op when nothing is cached.
|
|
733
|
+
*/
|
|
734
|
+
declare function releaseSharedGpuResources(): void;
|
|
735
|
+
declare function compressTextureToBytes(source: CompressTextureSource, options?: CompressOptions): Promise<CompressResult>;
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Cap the cache's total compressed payload in bytes (default 256 MiB).
|
|
739
|
+
* Lower it to evict immediately; 0 disables caching entirely.
|
|
740
|
+
*/
|
|
741
|
+
declare function setTranscodeCacheLimit(bytes: number): void;
|
|
742
|
+
/** Drop every cached transcode. Textures already built from entries are unaffected. */
|
|
743
|
+
declare function clearTranscodeCache(): void;
|
|
744
|
+
|
|
745
|
+
export { ASTC4x4Encoder, ASTC4x4WebGLEncoder, BC1Encoder, BC1WebGLEncoder, BC5Encoder, BC5WebGLEncoder, BC7Encoder, type BC7EncoderOptions, BC7WebGLEncoder, type Capabilities, type CompressOptions, type CompressResult, type CompressTextureSource, ETC2Encoder, type EncodeBytesResult, type EncodeCallOptions, type EncodeMipChainResult, type EncodedLevelBytes, Encoder, type EncoderConstructor, type EncoderImageSource, type EncoderOptions, type ExtensionProvider, type FeatureProvider, type FormatQuality, type FormatSelection, type FormatVariant, type MipLevel, type PreferredFormat, type RasterizeSvgOptions, type RawPixelSource, type SelectFormatOptions, type SvgRasterSize, TextureFormat, type TextureHint, WebGLBlockEncoder, type WebGLCapabilities, type WebGLEncodeBytesResult, type WebGLEncoderConstructor, type WebGLEncoderImageSource, type WebGLEncoderOptions, type WebGLFormatSelection, WebGPUFeature, clearTranscodeCache, compressTextureToBytes, createWebGLContext, detectCapabilities, detectWebGLCapabilities, generateGpuMipChain, generateMipChain, getSharedWebGLContext, gpuMipLevelCount, isWebGLAvailable, padToBlockMultiple, rasterizeSvg, releaseSharedGpuResources, selectFormat, selectWebGLFormat, setTranscodeCacheLimit };
|