ris-ktx2-api 0.1.0-dev.2.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.
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Flags that select options for Basis Universal transcoding.
3
+ *
4
+ * Numeric values match the libktx `ktx_transcode_flag_bits_e` enumerators.
5
+ * Combine them with bitwise OR when more than one option applies.
6
+ */
7
+ export enum KtxTranscodeFlags {
8
+ /** No special transcoding options. */
9
+ NONE = 0,
10
+
11
+ /**
12
+ * For PVRTC1, decode a non-power-of-two ETC1S level to the next larger
13
+ * power of two.
14
+ *
15
+ * libktx still documents this option as not implemented. It is ignored
16
+ * when the slice dimensions are already powers of two.
17
+ */
18
+ PVRTC_DECODE_TO_NEXT_POW2 = 2,
19
+
20
+ /**
21
+ * When transcoding to an opaque format, decode the alpha slice instead of
22
+ * the color slice if the Basis data has alpha. Has no effect when there
23
+ * is no alpha data.
24
+ */
25
+ TRANSCODE_ALPHA_DATA_TO_OPAQUE_FORMATS = 4,
26
+
27
+ /**
28
+ * Request a higher-quality transcode of UASTC to BC1, BC3, ETC2 EAC R11,
29
+ * or ETC2 EAC RG11. Unused by other UASTC transcode targets.
30
+ */
31
+ HIGH_QUALITY = 32,
32
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Target formats for transcoding a Basis Universal (ETC1S or UASTC) texture.
3
+ *
4
+ * Numeric values match the libktx `ktx_transcode_fmt_e` enumerators.
5
+ * Gaps in the numbering are formats libktx does not expose (there is no
6
+ * equivalent `VkFormat` for the omitted targets).
7
+ */
8
+ export enum KtxTranscodeFormat {
9
+ /**
10
+ * Opaque ETC1 RGB. Returns alpha data instead when
11
+ * {@link KtxTranscodeFlags.TRANSCODE_ALPHA_DATA_TO_OPAQUE_FORMATS} is set.
12
+ */
13
+ KTX_TTF_ETC1_RGB = 0,
14
+
15
+ /**
16
+ * ETC2 RGBA. An EAC alpha block followed by an ETC1 block.
17
+ * Textures without alpha get an opaque alpha channel.
18
+ */
19
+ ETC2_RGBA = 1,
20
+
21
+ /**
22
+ * Opaque BC1 RGB. Returns alpha data instead when
23
+ * {@link KtxTranscodeFlags.TRANSCODE_ALPHA_DATA_TO_OPAQUE_FORMATS} is set.
24
+ */
25
+ KTX_TTF_BC1_RGB = 2,
26
+
27
+ /**
28
+ * BC3 compressed RGBA.
29
+ * Common on desktop devices. Widely supported block compression for color textures.
30
+ */
31
+ BC3_RGBA = 3,
32
+
33
+ /**
34
+ * Single-channel BC4. The red channel is the opaque or alpha green component,
35
+ * depending on {@link KtxTranscodeFlags.TRANSCODE_ALPHA_DATA_TO_OPAQUE_FORMATS}.
36
+ */
37
+ KTX_TTF_BC4_R = 4,
38
+
39
+ /**
40
+ * Two-channel BC5 (red and green). Intended for tangent-space normal maps.
41
+ * The texture should have an alpha channel; otherwise green is 255.
42
+ */
43
+ KTX_TTF_BC5_RG = 5,
44
+
45
+ /**
46
+ * BC7 compressed RGBA.
47
+ * High quality block compression for color textures.
48
+ * Supports an alpha channel and is suitable for diffuse and physically based textures.
49
+ */
50
+ BC7_RGBA = 6,
51
+
52
+ /**
53
+ * Opaque PVRTC1 4bpp RGB. Returns alpha data instead when
54
+ * {@link KtxTranscodeFlags.TRANSCODE_ALPHA_DATA_TO_OPAQUE_FORMATS} is set.
55
+ */
56
+ KTX_TTF_PVRTC1_4_RGB = 8,
57
+
58
+ /**
59
+ * PVRTC1 4bpp RGBA. Useful for simple opacity maps.
60
+ * If the texture has no alpha channel, PVRTC1 4bpp RGB is used instead.
61
+ */
62
+ KTX_TTF_PVRTC1_4_RGBA = 9,
63
+
64
+ /**
65
+ * ASTC 4×4 RGBA.
66
+ * Common on mobile devices, especially Apple. High quality block compression
67
+ * for color textures, including an alpha channel.
68
+ */
69
+ ASTC_4X4_RGBA = 10,
70
+
71
+ /**
72
+ * Uncompressed 32bpp RGBA in raster order (R, G, B, A).
73
+ * Supported on all devices.
74
+ */
75
+ RGBA32 = 13,
76
+
77
+ /** Uncompressed 16bpp RGB565 in raster order, with red in the high bits. */
78
+ KTX_TTF_RGB565 = 14,
79
+
80
+ /** Uncompressed 16bpp BGR565 in raster order, with red in the low bits. */
81
+ KTX_TTF_BGR565 = 15,
82
+
83
+ /** Uncompressed 16bpp RGBA4444 in raster order. */
84
+ KTX_TTF_RGBA4444 = 16,
85
+
86
+ /**
87
+ * Opaque PVRTC2 4bpp RGB. Supports arbitrary dimensions, unlike PVRTC1.
88
+ */
89
+ KTX_TTF_PVRTC2_4_RGB = 18,
90
+
91
+ /** PVRTC2 4bpp RGBA. Premultiplied alpha is recommended. */
92
+ KTX_TTF_PVRTC2_4_RGBA = 19,
93
+
94
+ /**
95
+ * Unsigned ETC2 EAC R11. The red channel is the opaque or alpha green
96
+ * component, depending on
97
+ * {@link KtxTranscodeFlags.TRANSCODE_ALPHA_DATA_TO_OPAQUE_FORMATS}.
98
+ */
99
+ KTX_TTF_ETC2_EAC_R11 = 20,
100
+
101
+ /**
102
+ * Unsigned ETC2 EAC RG11. Intended for tangent-space normal maps.
103
+ * The texture should have an alpha channel; otherwise green is 255.
104
+ */
105
+ KTX_TTF_ETC2_EAC_RG11 = 21,
106
+
107
+ /**
108
+ * Selects {@link KtxTranscodeFormat.KTX_TTF_ETC1_RGB} or
109
+ * {@link KtxTranscodeFormat.ETC2_RGBA} according to whether the texture has alpha.
110
+ */
111
+ KTX_TTF_ETC = 22,
112
+
113
+ /**
114
+ * Selects {@link KtxTranscodeFormat.KTX_TTF_BC1_RGB} or
115
+ * {@link KtxTranscodeFormat.BC3_RGBA} according to whether the texture has alpha.
116
+ */
117
+ BC1_OR_3 = 23,
118
+
119
+ /** No transcode format selected. */
120
+ NO_SELECTION = 2147483647,
121
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * UASTC encoding configuration flags.
3
+ *
4
+ * Packed bitfield matching libktx `ktx_pack_uastc_flag_bits_e`.
5
+ * Bits 0–3 hold the compression level ({@link KtxUastcFlags.LEVEL_MASK}).
6
+ * {@link KtxUastcFlags.FAVOR_UASTC_ERROR} is `8`, so it sits inside that mask:
7
+ * combining it with a level changes the value `LEVEL_MASK` extracts.
8
+ * Hints at bit 4 and above (`16`, `64`, `128`, `256`) combine with a level
9
+ * with bitwise OR and leave bits 0–3 unchanged.
10
+ */
11
+ export enum KtxUastcFlags {
12
+ /**
13
+ * Fastest compression (lowest quality, highest speed). About 43.45 dB.
14
+ */
15
+ LEVEL_FASTEST = 0,
16
+
17
+ /**
18
+ * Faster compression. About 46.49 dB.
19
+ */
20
+ LEVEL_FASTER = 1,
21
+
22
+ /**
23
+ * Default compression level. About 47.47 dB.
24
+ */
25
+ LEVEL_DEFAULT = 2,
26
+
27
+ /**
28
+ * Slower compression (higher quality). About 48.01 dB.
29
+ */
30
+ LEVEL_SLOWER = 3,
31
+
32
+ /**
33
+ * Very slow compression (highest quality). About 48.24 dB.
34
+ */
35
+ LEVEL_VERY_SLOW = 4,
36
+
37
+ /**
38
+ * Mask for the compression level in bits 0–3.
39
+ */
40
+ LEVEL_MASK = 15,
41
+
42
+ /**
43
+ * Optimize encoding for the lowest UASTC reconstruction error.
44
+ */
45
+ FAVOR_UASTC_ERROR = 8,
46
+
47
+ /**
48
+ * Optimize encoding for the lowest BC7 decode error.
49
+ */
50
+ FAVOR_BC7_ERROR = 16,
51
+
52
+ /**
53
+ * Hint to optimize for faster ETC1 transcoding.
54
+ */
55
+ ETC1_FASTER_HINTS = 64,
56
+
57
+ /**
58
+ * Hint to optimize for the fastest ETC1 transcoding.
59
+ */
60
+ ETC1_FASTEST_HINTS = 128,
61
+
62
+ /**
63
+ * Disables flip-and-individual optimizations for ETC1 transcoding.
64
+ */
65
+ ETC1_DISABLE_FLIP_AND_INDIVIDUAL = 256,
66
+ }
@@ -0,0 +1,275 @@
1
+ import {VkFormat} from "./VkFormat.ts";
2
+
3
+ /**
4
+ * Describes how a texture format is laid out in memory, in blocks.
5
+ *
6
+ * For uncompressed formats a block is one pixel:
7
+ * `blockWidth` and `blockHeight` are `1`, and `bytesPerBlock` is the bytes per pixel.
8
+ *
9
+ * For compressed formats such as BC7, a block is a group of pixels
10
+ * (typically 4×4) stored in a fixed number of bytes.
11
+ */
12
+ export class TextureFormatInfo {
13
+ /** Width of one block, in pixels. */
14
+ public readonly blockWidth: number;
15
+
16
+ /** Height of one block, in pixels. */
17
+ public readonly blockHeight: number;
18
+
19
+ /** Depth of one block, in pixels. */
20
+ public readonly blockDepth: number;
21
+
22
+ /** Size of one block, in bytes. */
23
+ public readonly bytesPerBlock: number;
24
+
25
+ /**
26
+ * Average number of bytes used per pixel.
27
+ *
28
+ * For uncompressed formats this is the bytes per pixel.
29
+ * For compressed formats this is the average storage cost per pixel.
30
+ */
31
+ public get pixelSize(): number {
32
+ return this.bytesPerBlock /
33
+ (this.blockWidth * this.blockHeight * this.blockDepth);
34
+ }
35
+
36
+ /**
37
+ * Creates a block-layout description.
38
+ *
39
+ * @param blockWidth - Block width, in pixels.
40
+ * @param blockHeight - Block height, in pixels.
41
+ * @param blockDepth - Block depth, in pixels.
42
+ * @param bytesPerBlock - Bytes stored in one block.
43
+ */
44
+ public constructor(
45
+ blockWidth: number,
46
+ blockHeight: number,
47
+ blockDepth: number,
48
+ bytesPerBlock: number
49
+ ) {
50
+ this.blockWidth = blockWidth;
51
+ this.blockHeight = blockHeight;
52
+ this.blockDepth = blockDepth;
53
+ this.bytesPerBlock = bytesPerBlock;
54
+ }
55
+
56
+ /**
57
+ * Number of blocks needed to cover `width` pixels.
58
+ *
59
+ * @param width - Texture width, in pixels.
60
+ * @returns Block count, rounded up to a whole block.
61
+ */
62
+ public getBlocksPerRow(width: number): number {
63
+ return Math.ceil(width / this.blockWidth);
64
+ }
65
+
66
+ /**
67
+ * Number of block rows needed to cover `height` pixels.
68
+ *
69
+ * @param height - Texture height, in pixels.
70
+ * @returns Block-row count, rounded up to a whole block.
71
+ */
72
+ public getBlocksPerColumn(height: number): number {
73
+ return Math.ceil(height / this.blockHeight);
74
+ }
75
+
76
+ /**
77
+ * Number of block slices needed to cover `depth` pixels.
78
+ *
79
+ * @param depth - Texture depth, in pixels.
80
+ * @returns Block-slice count, rounded up to a whole block.
81
+ */
82
+ public getBlocksPerSlice(depth: number): number {
83
+ return Math.ceil(depth / this.blockDepth);
84
+ }
85
+
86
+ /**
87
+ * Unaligned number of bytes in one row of blocks.
88
+ *
89
+ * @param width - Texture width, in pixels.
90
+ * @returns Bytes per row, without a 256-byte alignment.
91
+ */
92
+ public getBytesPerRow(width: number): number {
93
+ return this.getBlocksPerRow(width) * this.bytesPerBlock;
94
+ }
95
+
96
+ /**
97
+ * WebGPU `bytesPerRow` for `width`.
98
+ *
99
+ * WebGPU requires `bytesPerRow` to be a multiple of 256.
100
+ *
101
+ * @param width - Texture width, in pixels.
102
+ * @returns `getBytesPerRow(width)` rounded up to a multiple of 256.
103
+ */
104
+ public getAlignedBytesPerRow(width: number): number {
105
+ const bytesPerRow = this.getBytesPerRow(width);
106
+ return Math.ceil(bytesPerRow / 256) * 256;
107
+ }
108
+
109
+ /**
110
+ * Byte size of one 2D mip level.
111
+ *
112
+ * @param width - Level width, in pixels.
113
+ * @param height - Level height, in pixels.
114
+ * @returns Level size, in bytes.
115
+ */
116
+ public getDataSize(width: number, height: number): number {
117
+ const blocksX = this.getBlocksPerRow(width);
118
+ const blocksY = this.getBlocksPerColumn(height);
119
+
120
+ return blocksX * blocksY * this.bytesPerBlock;
121
+ }
122
+
123
+ /**
124
+ * Byte size of one 3D mip level.
125
+ *
126
+ * @param width - Level width, in pixels.
127
+ * @param height - Level height, in pixels.
128
+ * @param depth - Level depth, in pixels.
129
+ * @returns Level size, in bytes.
130
+ */
131
+ public getDataSize3D(
132
+ width: number,
133
+ height: number,
134
+ depth: number
135
+ ): number {
136
+ const blocksX = this.getBlocksPerRow(width);
137
+ const blocksY = this.getBlocksPerColumn(height);
138
+ const blocksZ = this.getBlocksPerSlice(depth);
139
+
140
+ return blocksX * blocksY * blocksZ * this.bytesPerBlock;
141
+ }
142
+
143
+ /**
144
+ * BC7 layout: 4×4 blocks, 16 bytes per block.
145
+ *
146
+ * @returns The BC7 {@link TextureFormatInfo}.
147
+ */
148
+ public static bc7(): TextureFormatInfo {
149
+ return new TextureFormatInfo(4, 4, 1, 16);
150
+ }
151
+
152
+ /**
153
+ * BC3 layout: 4×4 blocks, 16 bytes per block.
154
+ *
155
+ * @returns The BC3 {@link TextureFormatInfo}.
156
+ */
157
+ public static bc3(): TextureFormatInfo {
158
+ return new TextureFormatInfo(4, 4, 1, 16);
159
+ }
160
+
161
+ /**
162
+ * ETC2 RGBA layout: 4×4 blocks, 16 bytes per block.
163
+ *
164
+ * @returns The ETC2 RGBA {@link TextureFormatInfo}.
165
+ */
166
+ public static etc2rgba(): TextureFormatInfo {
167
+ return new TextureFormatInfo(4, 4, 1, 16);
168
+ }
169
+
170
+ /**
171
+ * ASTC 4×4 RGBA layout: 4×4 blocks, 16 bytes per block.
172
+ *
173
+ * @returns The ASTC 4×4 RGBA {@link TextureFormatInfo}.
174
+ */
175
+ public static astc4x4rgba(): TextureFormatInfo {
176
+ return new TextureFormatInfo(4, 4, 1, 16);
177
+ }
178
+
179
+ /**
180
+ * Uncompressed 8-bit 4-channel layout: 1×1 blocks, 4 bytes per pixel.
181
+ *
182
+ * Channel order does not change the size. `B8G8R8A8_*` and
183
+ * `A8B8G8R8_*_PACK32` use this same layout.
184
+ *
185
+ * @returns The 4-byte {@link TextureFormatInfo}.
186
+ */
187
+ public static rgba32(): TextureFormatInfo {
188
+ return new TextureFormatInfo(1, 1, 1, 4);
189
+ }
190
+
191
+ /**
192
+ * `D24_UNORM_S8_UINT` layout: 4 bytes per pixel.
193
+ *
194
+ * @returns The depth/stencil {@link TextureFormatInfo}.
195
+ */
196
+ public static depth24Stencil8(): TextureFormatInfo {
197
+ return new TextureFormatInfo(1, 1, 1, 4);
198
+ }
199
+
200
+ /**
201
+ * `D32_SFLOAT` layout: 4 bytes per pixel.
202
+ *
203
+ * @returns The 32-bit float depth {@link TextureFormatInfo}.
204
+ */
205
+ public static depth32float(): TextureFormatInfo {
206
+ return new TextureFormatInfo(1, 1, 1, 4);
207
+ }
208
+
209
+ /**
210
+ * Block layout for a Vulkan format this package knows how to size.
211
+ *
212
+ * sRGB, signed, integer, and scaled variants share the block size of the
213
+ * matching unsigned normalized format. Channel order does not change the
214
+ * byte size.
215
+ *
216
+ * - `R8G8B8A8_*`, `B8G8R8A8_*`, and `A8B8G8R8_*_PACK32` use {@link TextureFormatInfo.rgba32}.
217
+ * - `D24_UNORM_S8_UINT` uses {@link TextureFormatInfo.depth24Stencil8}.
218
+ * - `D32_SFLOAT` uses {@link TextureFormatInfo.depth32float}.
219
+ * - `BC3_UNORM_BLOCK` and `BC3_SRGB_BLOCK` use {@link TextureFormatInfo.bc3}.
220
+ * - `BC7_UNORM_BLOCK` and `BC7_SRGB_BLOCK` use {@link TextureFormatInfo.bc7}.
221
+ * - `ETC2_R8G8B8A8_UNORM_BLOCK` and `ETC2_R8G8B8A8_SRGB_BLOCK` use {@link TextureFormatInfo.etc2rgba}.
222
+ * - `ASTC_4X4_UNORM_BLOCK`, `ASTC_4X4_SRGB_BLOCK`, and `ASTC_4X4_SFLOAT_BLOCK`
223
+ * use {@link TextureFormatInfo.astc4x4rgba}. `ASTC_4X4_SFLOAT_BLOCK_EXT`
224
+ * is the same value as `ASTC_4X4_SFLOAT_BLOCK`.
225
+ *
226
+ * @param vkFormat - Vulkan format.
227
+ * @returns The matching layout.
228
+ * @throws {Error} When `vkFormat` has no layout in this package.
229
+ */
230
+ public static fromVkFormat(vkFormat: VkFormat): TextureFormatInfo {
231
+ switch (vkFormat) {
232
+ case VkFormat.R8G8B8A8_UNORM:
233
+ case VkFormat.R8G8B8A8_SNORM:
234
+ case VkFormat.R8G8B8A8_USCALED:
235
+ case VkFormat.R8G8B8A8_SSCALED:
236
+ case VkFormat.R8G8B8A8_UINT:
237
+ case VkFormat.R8G8B8A8_SINT:
238
+ case VkFormat.R8G8B8A8_SRGB:
239
+ case VkFormat.B8G8R8A8_UNORM:
240
+ case VkFormat.B8G8R8A8_SNORM:
241
+ case VkFormat.B8G8R8A8_USCALED:
242
+ case VkFormat.B8G8R8A8_SSCALED:
243
+ case VkFormat.B8G8R8A8_UINT:
244
+ case VkFormat.B8G8R8A8_SINT:
245
+ case VkFormat.B8G8R8A8_SRGB:
246
+ case VkFormat.A8B8G8R8_UNORM_PACK32:
247
+ case VkFormat.A8B8G8R8_SNORM_PACK32:
248
+ case VkFormat.A8B8G8R8_USCALED_PACK32:
249
+ case VkFormat.A8B8G8R8_SSCALED_PACK32:
250
+ case VkFormat.A8B8G8R8_UINT_PACK32:
251
+ case VkFormat.A8B8G8R8_SINT_PACK32:
252
+ case VkFormat.A8B8G8R8_SRGB_PACK32:
253
+ return this.rgba32();
254
+ case VkFormat.D24_UNORM_S8_UINT:
255
+ return this.depth24Stencil8();
256
+ case VkFormat.D32_SFLOAT:
257
+ return this.depth32float();
258
+ case VkFormat.ASTC_4X4_UNORM_BLOCK:
259
+ case VkFormat.ASTC_4X4_SRGB_BLOCK:
260
+ case VkFormat.ASTC_4X4_SFLOAT_BLOCK:
261
+ return this.astc4x4rgba();
262
+ case VkFormat.BC7_UNORM_BLOCK:
263
+ case VkFormat.BC7_SRGB_BLOCK:
264
+ return this.bc7();
265
+ case VkFormat.BC3_UNORM_BLOCK:
266
+ case VkFormat.BC3_SRGB_BLOCK:
267
+ return this.bc3();
268
+ case VkFormat.ETC2_R8G8B8A8_UNORM_BLOCK:
269
+ case VkFormat.ETC2_R8G8B8A8_SRGB_BLOCK:
270
+ return this.etc2rgba();
271
+ default:
272
+ throw new Error(`TextureFormatInfo.fromVkFormat has no layout for VkFormat ${vkFormat}.`);
273
+ }
274
+ }
275
+ }