@woosh/meep-engine 3.14.1 → 3.14.2

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.
Files changed (220) hide show
  1. package/README.md +31 -24
  2. package/package.json +1 -1
  3. package/src/avif/native/DECISIONS.md +544 -536
  4. package/src/avif/native/heif/parse_avif_file.d.ts.map +1 -1
  5. package/src/avif/native/heif/parse_avif_file.js +384 -383
  6. package/src/avif/native/heif/parse_image_grid.d.ts.map +1 -1
  7. package/src/avif/native/heif/parse_image_grid.js +49 -48
  8. package/src/basis/BasisBitReader.d.ts +77 -0
  9. package/src/basis/BasisBitReader.d.ts.map +1 -0
  10. package/src/basis/BasisBitReader.js +231 -0
  11. package/src/basis/BasisHuffmanTable.d.ts +53 -0
  12. package/src/basis/BasisHuffmanTable.d.ts.map +1 -0
  13. package/src/basis/BasisHuffmanTable.js +263 -0
  14. package/src/basis/basis_read_huffman_table.d.ts +20 -0
  15. package/src/basis/basis_read_huffman_table.d.ts.map +1 -0
  16. package/src/basis/basis_read_huffman_table.js +187 -0
  17. package/src/basis/etc1s/Etc1sSelectorHistory.d.ts +50 -0
  18. package/src/basis/etc1s/Etc1sSelectorHistory.d.ts.map +1 -0
  19. package/src/basis/etc1s/Etc1sSelectorHistory.js +89 -0
  20. package/src/basis/etc1s/etc1s_block_colors.d.ts +14 -0
  21. package/src/basis/etc1s/etc1s_block_colors.d.ts.map +1 -0
  22. package/src/basis/etc1s/etc1s_block_colors.js +75 -0
  23. package/src/basis/etc1s/etc1s_decode_slice.d.ts +57 -0
  24. package/src/basis/etc1s/etc1s_decode_slice.d.ts.map +1 -0
  25. package/src/basis/etc1s/etc1s_decode_slice.js +258 -0
  26. package/src/basis/etc1s/etc1s_read_endpoint_codebook.d.ts +48 -0
  27. package/src/basis/etc1s/etc1s_read_endpoint_codebook.d.ts.map +1 -0
  28. package/src/basis/etc1s/etc1s_read_endpoint_codebook.js +111 -0
  29. package/src/basis/etc1s/etc1s_read_selector_codebook.d.ts +42 -0
  30. package/src/basis/etc1s/etc1s_read_selector_codebook.d.ts.map +1 -0
  31. package/src/basis/etc1s/etc1s_read_selector_codebook.js +127 -0
  32. package/src/basis/etc1s/etc1s_read_slice_tables.d.ts +54 -0
  33. package/src/basis/etc1s/etc1s_read_slice_tables.d.ts.map +1 -0
  34. package/src/basis/etc1s/etc1s_read_slice_tables.js +47 -0
  35. package/src/basis/transcode/build_range_plan.js +54 -0
  36. package/src/basis/transcode/etc1s_to_bc1.d.ts +24 -0
  37. package/src/basis/transcode/etc1s_to_bc1.d.ts.map +1 -0
  38. package/src/basis/transcode/etc1s_to_bc1.js +205 -0
  39. package/src/basis/transcode/etc1s_to_bc7.d.ts +30 -0
  40. package/src/basis/transcode/etc1s_to_bc7.d.ts.map +1 -0
  41. package/src/basis/transcode/etc1s_to_bc7.js +496 -0
  42. package/src/basis/transcode/fit_endpoints.d.ts +59 -0
  43. package/src/basis/transcode/fit_endpoints.d.ts.map +1 -0
  44. package/src/basis/transcode/fit_endpoints.js +226 -0
  45. package/src/{avif/native/isobmff → core/binary}/ByteCursor.d.ts +19 -6
  46. package/src/core/binary/ByteCursor.d.ts.map +1 -0
  47. package/src/{avif/native/isobmff → core/binary}/ByteCursor.js +41 -14
  48. package/src/engine/EngineHarness.js +1 -1
  49. package/src/engine/asset/codec/Codec.d.ts.map +1 -0
  50. package/src/engine/asset/codec/CodecWithFallback.d.ts.map +1 -0
  51. package/src/engine/asset/{loaders/image/codec → codec}/CodecWithFallback.js +2 -2
  52. package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +4 -4
  53. package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts +1 -1
  54. package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts.map +1 -1
  55. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +1 -1
  56. package/src/engine/asset/loaders/image/codec/NativeImageDecoder.d.ts +1 -1
  57. package/src/engine/asset/loaders/image/codec/NativeImageDecoder.d.ts.map +1 -1
  58. package/src/engine/asset/loaders/image/codec/NativeImageDecoder.js +1 -1
  59. package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.d.ts +1 -1
  60. package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.d.ts.map +1 -1
  61. package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +1 -1
  62. package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts.map +1 -1
  63. package/src/engine/graphics/texture/atlas/TextureAtlas.js +13 -0
  64. package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
  65. package/src/engine/physics/broadphase/generate_pairs.js +7 -1
  66. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  67. package/src/ktx2/KTX2_IDENTIFIER.d.ts +14 -0
  68. package/src/ktx2/KTX2_IDENTIFIER.d.ts.map +1 -0
  69. package/src/ktx2/KTX2_IDENTIFIER.js +15 -0
  70. package/src/ktx2/KhrDfModel.d.ts +35 -0
  71. package/src/ktx2/KhrDfModel.d.ts.map +1 -0
  72. package/src/ktx2/KhrDfModel.js +49 -0
  73. package/src/ktx2/SupercompressionScheme.d.ts +16 -0
  74. package/src/ktx2/SupercompressionScheme.d.ts.map +1 -0
  75. package/src/ktx2/SupercompressionScheme.js +23 -0
  76. package/src/ktx2/ktx2_read.d.ts +71 -0
  77. package/src/ktx2/ktx2_read.d.ts.map +1 -0
  78. package/src/ktx2/ktx2_read.js +581 -0
  79. package/src/ktx2/ktx2_read_basis_lz_global_data.d.ts +27 -0
  80. package/src/ktx2/ktx2_read_basis_lz_global_data.d.ts.map +1 -0
  81. package/src/ktx2/ktx2_read_basis_lz_global_data.js +189 -0
  82. package/src/ktx2/vk_format_to_texture_format.d.ts +55 -0
  83. package/src/ktx2/vk_format_to_texture_format.d.ts.map +1 -0
  84. package/src/ktx2/vk_format_to_texture_format.js +290 -0
  85. package/src/shade/descriptor/GPUTextureUsage.d.ts +23 -0
  86. package/src/shade/descriptor/GPUTextureUsage.d.ts.map +1 -0
  87. package/src/shade/descriptor/GPUTextureUsage.js +24 -0
  88. package/src/shade/descriptor/WebGPUExtensionType.d.ts +3 -0
  89. package/src/shade/descriptor/WebGPUExtensionType.js +26 -0
  90. package/src/shade/descriptor/texture/TextureDescriptor.d.ts +2 -6
  91. package/src/shade/descriptor/texture/TextureDescriptor.d.ts.map +1 -1
  92. package/src/shade/descriptor/texture/TextureDescriptor.js +24 -40
  93. package/src/shade/descriptor/texture/format/TextureFormat.d.ts +125 -0
  94. package/src/shade/descriptor/texture/format/TextureFormat.d.ts.map +1 -0
  95. package/src/shade/descriptor/texture/format/TextureFormat.js +146 -0
  96. package/src/shade/descriptor/texture/format/gpu_texture_format_info.d.ts +60 -0
  97. package/src/shade/descriptor/texture/format/gpu_texture_format_info.d.ts.map +1 -1
  98. package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +102 -0
  99. package/src/shade/device/graph/TextureResourceDescriptor.d.ts.map +1 -1
  100. package/src/shade/device/graph/TextureResourceDescriptor.js +160 -155
  101. package/src/shade/device/mock/SoftwareGPUQueue.d.ts +11 -4
  102. package/src/shade/device/mock/SoftwareGPUQueue.d.ts.map +1 -1
  103. package/src/shade/device/mock/SoftwareGPUQueue.js +31 -37
  104. package/src/shade/device/mock/SoftwareGPUTexture.d.ts.map +1 -1
  105. package/src/shade/device/mock/SoftwareGPUTexture.js +8 -4
  106. package/src/shade/device/timing/profile/frame_graph_extract_topology.d.ts.map +1 -1
  107. package/src/shade/device/timing/profile/frame_graph_extract_topology.js +164 -174
  108. package/src/shade/playground/ground_seam/README.md +235 -0
  109. package/src/shade/playground/ground_seam/capture_scene_color.d.ts +45 -0
  110. package/src/shade/playground/ground_seam/capture_scene_color.d.ts.map +1 -0
  111. package/src/shade/playground/ground_seam/capture_scene_color.js +242 -0
  112. package/src/shade/playground/ground_seam/depth_step_across_seam.d.ts +11 -0
  113. package/src/shade/playground/ground_seam/depth_step_across_seam.d.ts.map +1 -0
  114. package/src/shade/playground/ground_seam/depth_step_across_seam.js +185 -0
  115. package/src/shade/playground/ground_seam/index.html +195 -0
  116. package/src/shade/playground/ground_seam/main.d.ts +2 -0
  117. package/src/shade/playground/ground_seam/main.d.ts.map +1 -0
  118. package/src/shade/playground/ground_seam/main.js +879 -0
  119. package/src/shade/playground/ground_seam/make_grid_texture.d.ts +29 -0
  120. package/src/shade/playground/ground_seam/make_grid_texture.d.ts.map +1 -0
  121. package/src/shade/playground/ground_seam/make_grid_texture.js +105 -0
  122. package/src/shade/playground/ground_seam/make_ground.d.ts +70 -0
  123. package/src/shade/playground/ground_seam/make_ground.d.ts.map +1 -0
  124. package/src/shade/playground/ground_seam/make_ground.js +161 -0
  125. package/src/shade/playground/ground_seam/measure_flicker.d.ts +71 -0
  126. package/src/shade/playground/ground_seam/measure_flicker.d.ts.map +1 -0
  127. package/src/shade/playground/ground_seam/measure_flicker.js +531 -0
  128. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  129. package/src/shade/renderer/Renderer.js +2519 -2511
  130. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  131. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +275 -274
  132. package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
  133. package/src/shade/renderer/light/GPULightCollection.js +323 -314
  134. package/src/shade/renderer/lightmap/GPULightMap.js +336 -336
  135. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  136. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +12 -2
  137. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
  138. package/src/shade/renderer/material/standard/fragment_gbuffer.js +3 -1
  139. package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
  140. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts.map +1 -1
  141. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js +3 -1
  142. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  143. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -1
  144. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.js +3 -1
  145. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -1
  146. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.js +3 -1
  147. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.d.ts +28 -0
  148. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.d.ts.map +1 -0
  149. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.js +39 -0
  150. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.d.ts +45 -0
  151. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.d.ts.map +1 -1
  152. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.js +94 -61
  153. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.d.ts +24 -0
  154. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.d.ts.map +1 -0
  155. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.js +43 -0
  156. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +1462 -0
  157. package/src/shade/renderer/texture/TextureManager.d.ts.map +1 -1
  158. package/src/shade/renderer/texture/TextureManager.js +20 -8
  159. package/src/shade/renderer/texture/TextureRole.d.ts +19 -0
  160. package/src/shade/renderer/texture/TextureRole.d.ts.map +1 -0
  161. package/src/shade/renderer/texture/TextureRole.js +26 -0
  162. package/src/shade/renderer/texture/TextureVariantSet.d.ts +71 -0
  163. package/src/shade/renderer/texture/TextureVariantSet.d.ts.map +1 -0
  164. package/src/shade/renderer/texture/TextureVariantSet.js +105 -0
  165. package/src/shade/renderer/texture/download_texture_data.d.ts.map +1 -1
  166. package/src/shade/renderer/texture/download_texture_data.js +22 -0
  167. package/src/shade/renderer/texture/format/gpu_texture_compression_support.d.ts +15 -0
  168. package/src/shade/renderer/texture/format/gpu_texture_compression_support.d.ts.map +1 -0
  169. package/src/shade/renderer/texture/format/gpu_texture_compression_support.js +50 -0
  170. package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.d.ts +27 -0
  171. package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.d.ts.map +1 -0
  172. package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.js +65 -0
  173. package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts +11 -0
  174. package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts.map +1 -0
  175. package/src/shade/renderer/texture/format/infer_format_from_parameters.js +88 -0
  176. package/src/shade/renderer/texture/format/texture_format_from_shade_image.d.ts +24 -0
  177. package/src/shade/renderer/texture/format/texture_format_from_shade_image.d.ts.map +1 -0
  178. package/src/shade/renderer/texture/format/texture_format_from_shade_image.js +71 -0
  179. package/src/shade/renderer/texture/format/texture_format_preference.d.ts +22 -0
  180. package/src/shade/renderer/texture/format/texture_format_preference.d.ts.map +1 -0
  181. package/src/shade/renderer/texture/format/texture_format_preference.js +89 -0
  182. package/src/shade/renderer/texture/format/texture_variant_select.d.ts +24 -0
  183. package/src/shade/renderer/texture/format/texture_variant_select.d.ts.map +1 -0
  184. package/src/shade/renderer/texture/format/texture_variant_select.js +38 -0
  185. package/src/shade/renderer/texture/shade_texture_might_have_alpha.d.ts +9 -1
  186. package/src/shade/renderer/texture/shade_texture_might_have_alpha.d.ts.map +1 -1
  187. package/src/shade/renderer/texture/shade_texture_might_have_alpha.js +73 -8
  188. package/src/shade/renderer/texture/source/AlphaMode.d.ts +27 -0
  189. package/src/shade/renderer/texture/source/AlphaMode.d.ts.map +1 -0
  190. package/src/shade/renderer/texture/source/AlphaMode.js +52 -0
  191. package/src/shade/renderer/texture/source/ShadeImage.d.ts +33 -0
  192. package/src/shade/renderer/texture/source/ShadeImage.d.ts.map +1 -1
  193. package/src/shade/renderer/texture/source/ShadeImage.js +74 -0
  194. package/src/shade/renderer/texture/source/ShadeTexelData.d.ts +78 -0
  195. package/src/shade/renderer/texture/source/ShadeTexelData.d.ts.map +1 -0
  196. package/src/shade/renderer/texture/source/ShadeTexelData.js +158 -0
  197. package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.d.ts +0 -10
  198. package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.d.ts.map +1 -1
  199. package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.js +73 -175
  200. package/src/shade/renderer/texture/texture_write_level.d.ts +32 -0
  201. package/src/shade/renderer/texture/texture_write_level.d.ts.map +1 -0
  202. package/src/shade/renderer/texture/texture_write_level.js +77 -0
  203. package/src/shade/renderer/texture/texture_write_to_gpu.d.ts +8 -1
  204. package/src/shade/renderer/texture/texture_write_to_gpu.d.ts.map +1 -1
  205. package/src/shade/renderer/texture/texture_write_to_gpu.js +62 -37
  206. package/src/shade/renderer/texture/virtual/source/VTSourceImage.d.ts +8 -0
  207. package/src/shade/renderer/texture/virtual/source/VTSourceImage.d.ts.map +1 -1
  208. package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +8 -0
  209. package/src/shade/util/texture_mip_extent.d.ts +49 -0
  210. package/src/shade/util/texture_mip_extent.d.ts.map +1 -0
  211. package/src/shade/util/texture_mip_extent.js +87 -0
  212. package/src/avif/native/isobmff/ByteCursor.d.ts.map +0 -1
  213. package/src/engine/asset/loaders/image/codec/Codec.d.ts.map +0 -1
  214. package/src/engine/asset/loaders/image/codec/CodecWithFallback.d.ts.map +0 -1
  215. package/src/shade/util/compute_max_mip_count.d.ts +0 -8
  216. package/src/shade/util/compute_max_mip_count.d.ts.map +0 -1
  217. package/src/shade/util/compute_max_mip_count.js +0 -27
  218. /package/src/engine/asset/{loaders/image/codec → codec}/Codec.d.ts +0 -0
  219. /package/src/engine/asset/{loaders/image/codec → codec}/Codec.js +0 -0
  220. /package/src/engine/asset/{loaders/image/codec → codec}/CodecWithFallback.d.ts +0 -0
@@ -0,0 +1,189 @@
1
+ import { ByteCursor } from "../core/binary/ByteCursor.js";
2
+ import { EndianType } from "../core/binary/EndianType.js";
3
+
4
+ /**
5
+ * Bytes the global data header occupies: two 16-bit counts and four 32-bit lengths.
6
+ *
7
+ * @readonly
8
+ * @type {number}
9
+ */
10
+ const GLOBAL_HEADER_BYTES = 20;
11
+
12
+ /**
13
+ * Bytes each image descriptor occupies: a flags word and two offset/length pairs.
14
+ *
15
+ * @readonly
16
+ * @type {number}
17
+ */
18
+ const IMAGE_DESC_BYTES = 20;
19
+
20
+ /**
21
+ * The image flag marking a frame that refers to the one before it.
22
+ *
23
+ * @readonly
24
+ * @type {number}
25
+ */
26
+ const IMAGE_FLAG_IS_P_FRAME = 0x02;
27
+
28
+ /**
29
+ * Read the BasisLZ supercompression global data.
30
+ *
31
+ * This is the codebook every image in the file shares — endpoints, selectors and Huffman tables —
32
+ * plus one descriptor per image saying where that image's slices sit inside its mip level. The
33
+ * structure is the *container's*, defined by KTX2 rather than by Basis; what is inside the four
34
+ * sections is the codec's, and is decoded by the transcoder.
35
+ *
36
+ * **Slice offsets are relative to their own mip level**, not to the file, which is why the level
37
+ * bytes are passed in already located rather than the file being re-walked here.
38
+ *
39
+ * @param {ArrayBuffer|Uint8Array} bytes the whole file
40
+ * @param {number} byte_offset of the global data section, from `sgdByteOffset`
41
+ * @param {number} byte_length from `sgdByteLength`
42
+ * @param {number} image_count one per level, for the 2D non-array textures this reader accepts
43
+ * @param {Uint8Array[]} level_bytes one per level, base first, as located by the level index
44
+ * @param {boolean} has_alpha whether the file's images carry a second slice, from the descriptor
45
+ * @returns {import("../basis/transcode_basis.js").BasisEtc1sPayload} without its dimensions, which
46
+ * the caller holds
47
+ * @throws {Error} naming the field, for global data that is truncated or disagrees with itself
48
+ *
49
+ * @see the KTX2 specification, Appendix C
50
+ * @author Alex Goldring
51
+ * @copyright Company Named Limited (c) 2026
52
+ */
53
+ export function ktx2_read_basis_lz_global_data(
54
+ bytes, byte_offset, byte_length, image_count, level_bytes, has_alpha
55
+ ) {
56
+ if (byte_offset === 0 || byte_length === 0) {
57
+ throw new Error(
58
+ "KTX2: the file declares BasisLZ supercompression and carries no supercompression global"
59
+ + " data. The endpoint and selector codebooks live there, and without them the levels"
60
+ + " are a stream of indices into nothing."
61
+ );
62
+ }
63
+
64
+ const cursor = new ByteCursor().init(bytes, EndianType.LittleEndian);
65
+
66
+ cursor.seek(byte_offset);
67
+
68
+ const endpoint_count = cursor.u16();
69
+ const selector_count = cursor.u16();
70
+ const endpoints_byte_length = cursor.u32();
71
+ const selectors_byte_length = cursor.u32();
72
+ const tables_byte_length = cursor.u32();
73
+ const extended_byte_length = cursor.u32();
74
+
75
+ /*
76
+ The specification requires this exactly, and checking it is worth the two lines: every section
77
+ below is located by adding lengths, so a header that does not add up produces sections that
78
+ overlap or run past the end, and the failure would surface as a corrupt Huffman table rather
79
+ than as a malformed file.
80
+ */
81
+ const expected_byte_length = GLOBAL_HEADER_BYTES
82
+ + IMAGE_DESC_BYTES * image_count
83
+ + endpoints_byte_length
84
+ + selectors_byte_length
85
+ + tables_byte_length
86
+ + extended_byte_length;
87
+
88
+ if (byte_length !== expected_byte_length) {
89
+ throw new Error(
90
+ `KTX2: sgdByteLength is ${byte_length}, and the header's own section lengths add up to`
91
+ + ` ${expected_byte_length} for ${image_count} image${image_count === 1 ? "" : "s"}`
92
+ );
93
+ }
94
+
95
+ if (extended_byte_length !== 0) {
96
+ throw new Error(
97
+ `KTX2: the BasisLZ global data declares ${extended_byte_length} bytes of extended data,`
98
+ + ` and the specification requires 0 for an ETC1S payload`
99
+ );
100
+ }
101
+
102
+ if (endpoint_count === 0 || selector_count === 0) {
103
+ throw new Error(
104
+ `KTX2: the BasisLZ global data declares ${endpoint_count} endpoints and`
105
+ + ` ${selector_count} selectors, and a slice's indices refer into both`
106
+ );
107
+ }
108
+
109
+ const images = [];
110
+
111
+ for (let image = 0; image < image_count; image++) {
112
+ const flags = cursor.u32();
113
+ const rgb_byte_offset = cursor.u32();
114
+ const rgb_byte_length = cursor.u32();
115
+ const alpha_byte_offset = cursor.u32();
116
+ const alpha_byte_length = cursor.u32();
117
+
118
+ if ((flags & IMAGE_FLAG_IS_P_FRAME) !== 0) {
119
+ /*
120
+ A P-frame's blocks may copy their indices from the previous frame, which needs the
121
+ frames decoded in order and the previous one kept. Nothing here plays a video texture,
122
+ and a still image never sets this — so refusing names the feature rather than decoding
123
+ the frame as though every block stood alone, which would be wrong exactly where the
124
+ encoder saved the most.
125
+ */
126
+ throw new Error(
127
+ `KTX2: image ${image} is a P frame of an animation sequence, which refers to the`
128
+ + ` frame before it. Texture video is not transcoded here.`
129
+ );
130
+ }
131
+
132
+ const level = level_bytes[image];
133
+
134
+ images.push({
135
+ rgb: slice_of(level, rgb_byte_offset, rgb_byte_length, image, "rgb"),
136
+ alpha: has_alpha
137
+ ? slice_of(level, alpha_byte_offset, alpha_byte_length, image, "alpha")
138
+ : undefined,
139
+ });
140
+ }
141
+
142
+ const endpoints = cursor.view_bytes(endpoints_byte_length);
143
+ const selectors = cursor.view_bytes(selectors_byte_length);
144
+ const tables = cursor.view_bytes(tables_byte_length);
145
+
146
+ return {
147
+ has_alpha,
148
+ endpoint_count,
149
+ selector_count,
150
+ endpoints,
151
+ selectors,
152
+ tables,
153
+ images,
154
+ };
155
+ }
156
+
157
+ /**
158
+ * One slice, as a view into its mip level's bytes.
159
+ *
160
+ * @param {Uint8Array} level
161
+ * @param {number} byte_offset within `level`
162
+ * @param {number} byte_length
163
+ * @param {number} image for the error message
164
+ * @param {string} which for the error message
165
+ * @returns {Uint8Array}
166
+ * @throws {Error} for a slice that runs past its level
167
+ */
168
+ function slice_of(level, byte_offset, byte_length, image, which) {
169
+ if (level === undefined) {
170
+ throw new Error(
171
+ `KTX2: the BasisLZ global data describes image ${image}, and the level index has no`
172
+ + ` level for it`
173
+ );
174
+ }
175
+
176
+ if (byte_length === 0) {
177
+ throw new Error(`KTX2: image ${image} declares an empty ${which} slice`);
178
+ }
179
+
180
+ if (byte_offset + byte_length > level.byteLength) {
181
+ throw new Error(
182
+ `KTX2: image ${image}'s ${which} slice claims bytes`
183
+ + ` [${byte_offset}, ${byte_offset + byte_length}) of a ${level.byteLength} byte mip`
184
+ + ` level, which is past its end`
185
+ );
186
+ }
187
+
188
+ return level.subarray(byte_offset, byte_offset + byte_length);
189
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Every `vkFormat` this module maps, for a test that wants to sweep them.
3
+ *
4
+ * @returns {number[]}
5
+ */
6
+ export function vk_formats_mapped(): number[];
7
+ /**
8
+ * Every `vkFormat` this module names but deliberately does not map, for the test that keeps the two
9
+ * tables from overlapping.
10
+ *
11
+ * @returns {number[]}
12
+ */
13
+ export function vk_formats_unmappable(): number[];
14
+ /**
15
+ * The Vulkan name of `vk_format`, where this module knows it.
16
+ *
17
+ * @param {number} vk_format
18
+ * @returns {string} the `VK_FORMAT_…` name, or `vkFormat <n>` for one outside both tables
19
+ */
20
+ export function vk_format_name(vk_format: number): string;
21
+ /**
22
+ * The {@link TextureFormat} holding the same bytes as `vk_format`.
23
+ *
24
+ * Byte for byte, not approximately: every mapping here is a pair of names for one memory layout, so
25
+ * a payload passes through unchanged and the only thing the mapping decides is what the sampler is
26
+ * told about it. The single caveat is BC1, noted beside its rows in the table.
27
+ *
28
+ * @param {number} vk_format as read from a KTX2 header
29
+ * @returns {TextureFormat}
30
+ * @throws {Error} naming the format, for one WebGPU does not expose
31
+ */
32
+ export function vk_format_to_texture_format(vk_format: number): TextureFormat;
33
+ /**
34
+ * `VkFormat` numbers that map onto a {@link TextureFormat}, and the ones that deliberately do not.
35
+ *
36
+ * KTX2 names its payload's encoding with a Vulkan format number, so reading one means owning a
37
+ * corner of Vulkan's enumeration. Only the part WebGPU also exposes can be mapped; everything else
38
+ * is a refusal, and the point of writing the refusals down beside the mappings is that a file the
39
+ * engine cannot use says *which* format it holds instead of failing somewhere downstream with a
40
+ * number nobody recognises.
41
+ *
42
+ * @see https://registry.khronos.org/vulkan/specs/latest/man/html/VkFormat.html
43
+ * @author Alex Goldring
44
+ * @copyright Company Named Limited (c) 2026
45
+ */
46
+ /**
47
+ * `VK_FORMAT_UNDEFINED`. In a KTX2 file this does not mean "no format" — it means the payload is
48
+ * Basis Universal and the Data Format Descriptor, not `vkFormat`, says which of the two it is.
49
+ *
50
+ * @readonly
51
+ * @type {number}
52
+ */
53
+ export const VK_FORMAT_UNDEFINED: number;
54
+ import { TextureFormat } from "../shade/descriptor/texture/format/TextureFormat.js";
55
+ //# sourceMappingURL=vk_format_to_texture_format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vk_format_to_texture_format.d.ts","sourceRoot":"","sources":["../../../src/ktx2/vk_format_to_texture_format.js"],"names":[],"mappings":"AAqOA;;;;GAIG;AACH,qCAFa,MAAM,EAAE,CAIpB;AAED;;;;;GAKG;AACH,yCAFa,MAAM,EAAE,CAIpB;AAED;;;;;GAKG;AACH,0CAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;;;;GAUG;AACH,uDAJW,MAAM,GACJ,aAAa,CAuBzB;AA/RD;;;;;;;;;;;;GAYG;AAEH;;;;;;GAMG;AACH,kCAFU,MAAM,CAEqB;8BAvBP,qDAAqD"}
@@ -0,0 +1,290 @@
1
+ import { TextureFormat } from "../shade/descriptor/texture/format/TextureFormat.js";
2
+
3
+ /**
4
+ * `VkFormat` numbers that map onto a {@link TextureFormat}, and the ones that deliberately do not.
5
+ *
6
+ * KTX2 names its payload's encoding with a Vulkan format number, so reading one means owning a
7
+ * corner of Vulkan's enumeration. Only the part WebGPU also exposes can be mapped; everything else
8
+ * is a refusal, and the point of writing the refusals down beside the mappings is that a file the
9
+ * engine cannot use says *which* format it holds instead of failing somewhere downstream with a
10
+ * number nobody recognises.
11
+ *
12
+ * @see https://registry.khronos.org/vulkan/specs/latest/man/html/VkFormat.html
13
+ * @author Alex Goldring
14
+ * @copyright Company Named Limited (c) 2026
15
+ */
16
+
17
+ /**
18
+ * `VK_FORMAT_UNDEFINED`. In a KTX2 file this does not mean "no format" — it means the payload is
19
+ * Basis Universal and the Data Format Descriptor, not `vkFormat`, says which of the two it is.
20
+ *
21
+ * @readonly
22
+ * @type {number}
23
+ */
24
+ export const VK_FORMAT_UNDEFINED = 0;
25
+
26
+ /**
27
+ * `[vkFormat, Vulkan name, GPUTextureFormat]`.
28
+ *
29
+ * Sorted by `vkFormat`, which is how the Vulkan header reads and how a reviewer checks a row against
30
+ * it. The one entry that is not a straight rename is BC1, which is commented where it sits.
31
+ *
32
+ * @type {[number, string, TextureFormat][]}
33
+ */
34
+ const MAPPED = [
35
+ [9, "VK_FORMAT_R8_UNORM", TextureFormat.R8UNORM],
36
+ [10, "VK_FORMAT_R8_SNORM", TextureFormat.R8SNORM],
37
+ [13, "VK_FORMAT_R8_UINT", TextureFormat.R8UINT],
38
+ [14, "VK_FORMAT_R8_SINT", TextureFormat.R8SINT],
39
+
40
+ [16, "VK_FORMAT_R8G8_UNORM", TextureFormat.RG8UNORM],
41
+ [17, "VK_FORMAT_R8G8_SNORM", TextureFormat.RG8SNORM],
42
+ [20, "VK_FORMAT_R8G8_UINT", TextureFormat.RG8UINT],
43
+ [21, "VK_FORMAT_R8G8_SINT", TextureFormat.RG8SINT],
44
+
45
+ [37, "VK_FORMAT_R8G8B8A8_UNORM", TextureFormat.RGBA8UNORM],
46
+ [38, "VK_FORMAT_R8G8B8A8_SNORM", TextureFormat.RGBA8SNORM],
47
+ [41, "VK_FORMAT_R8G8B8A8_UINT", TextureFormat.RGBA8UINT],
48
+ [42, "VK_FORMAT_R8G8B8A8_SINT", TextureFormat.RGBA8SINT],
49
+ [43, "VK_FORMAT_R8G8B8A8_SRGB", TextureFormat.RGBA8UNORM_SRGB],
50
+
51
+ [44, "VK_FORMAT_B8G8R8A8_UNORM", TextureFormat.BGRA8UNORM],
52
+ [50, "VK_FORMAT_B8G8R8A8_SRGB", TextureFormat.BGRA8UNORM_SRGB],
53
+
54
+ [64, "VK_FORMAT_A2B10G10R10_UNORM_PACK32", TextureFormat.RGB10A2UNORM],
55
+ [68, "VK_FORMAT_A2B10G10R10_UINT_PACK32", TextureFormat.RGB10A2UINT],
56
+
57
+ [70, "VK_FORMAT_R16_UNORM", TextureFormat.R16UNORM],
58
+ [71, "VK_FORMAT_R16_SNORM", TextureFormat.R16SNORM],
59
+ [74, "VK_FORMAT_R16_UINT", TextureFormat.R16UINT],
60
+ [75, "VK_FORMAT_R16_SINT", TextureFormat.R16SINT],
61
+ [76, "VK_FORMAT_R16_SFLOAT", TextureFormat.R16FLOAT],
62
+
63
+ [77, "VK_FORMAT_R16G16_UNORM", TextureFormat.RG16UNORM],
64
+ [78, "VK_FORMAT_R16G16_SNORM", TextureFormat.RG16SNORM],
65
+ [81, "VK_FORMAT_R16G16_UINT", TextureFormat.RG16UINT],
66
+ [82, "VK_FORMAT_R16G16_SINT", TextureFormat.RG16SINT],
67
+ [83, "VK_FORMAT_R16G16_SFLOAT", TextureFormat.RG16FLOAT],
68
+
69
+ [91, "VK_FORMAT_R16G16B16A16_UNORM", TextureFormat.RGBA16UNORM],
70
+ [92, "VK_FORMAT_R16G16B16A16_SNORM", TextureFormat.RGBA16SNORM],
71
+ [95, "VK_FORMAT_R16G16B16A16_UINT", TextureFormat.RGBA16UINT],
72
+ [96, "VK_FORMAT_R16G16B16A16_SINT", TextureFormat.RGBA16SINT],
73
+ [97, "VK_FORMAT_R16G16B16A16_SFLOAT", TextureFormat.RGBA16FLOAT],
74
+
75
+ [98, "VK_FORMAT_R32_UINT", TextureFormat.R32UINT],
76
+ [99, "VK_FORMAT_R32_SINT", TextureFormat.R32SINT],
77
+ [100, "VK_FORMAT_R32_SFLOAT", TextureFormat.R32FLOAT],
78
+
79
+ [101, "VK_FORMAT_R32G32_UINT", TextureFormat.RG32UINT],
80
+ [102, "VK_FORMAT_R32G32_SINT", TextureFormat.RG32SINT],
81
+ [103, "VK_FORMAT_R32G32_SFLOAT", TextureFormat.RG32FLOAT],
82
+
83
+ [107, "VK_FORMAT_R32G32B32A32_UINT", TextureFormat.RGBA32UINT],
84
+ [108, "VK_FORMAT_R32G32B32A32_SINT", TextureFormat.RGBA32SINT],
85
+ [109, "VK_FORMAT_R32G32B32A32_SFLOAT", TextureFormat.RGBA32FLOAT],
86
+
87
+ [122, "VK_FORMAT_B10G11R11_UFLOAT_PACK32", TextureFormat.RG11B10UFLOAT],
88
+ [123, "VK_FORMAT_E5B9G9R9_UFLOAT_PACK32", TextureFormat.RGB9E5UFLOAT],
89
+
90
+ /*
91
+ BC — 131 and 132 are the RGB spelling, and WebGPU has no name for it.
92
+
93
+ `VK_FORMAT_BC1_RGB_*` and `VK_FORMAT_BC1_RGBA_*` are the same sixty-four bits per block; the only
94
+ difference is what a block in three-colour mode does with its fourth index — the RGB spelling
95
+ reads it as opaque black, the RGBA spelling as transparent. So a file naming the RGB spelling is
96
+ decoded here with punch-through alpha honoured.
97
+
98
+ Mapped rather than refused, because refusing would reject a large share of real BC1 content over
99
+ a difference no encoder targeting the RGB spelling exercises: having no alpha to store, it has no
100
+ reason to emit that index at all. A consumer that needs the guarantee ignores alpha at the sample
101
+ site, which is what an opaque texture's material does anyway.
102
+ */
103
+ [131, "VK_FORMAT_BC1_RGB_UNORM_BLOCK", TextureFormat.BC1_RGBA_UNORM],
104
+ [132, "VK_FORMAT_BC1_RGB_SRGB_BLOCK", TextureFormat.BC1_RGBA_UNORM_SRGB],
105
+ [133, "VK_FORMAT_BC1_RGBA_UNORM_BLOCK", TextureFormat.BC1_RGBA_UNORM],
106
+ [134, "VK_FORMAT_BC1_RGBA_SRGB_BLOCK", TextureFormat.BC1_RGBA_UNORM_SRGB],
107
+ [135, "VK_FORMAT_BC2_UNORM_BLOCK", TextureFormat.BC2_RGBA_UNORM],
108
+ [136, "VK_FORMAT_BC2_SRGB_BLOCK", TextureFormat.BC2_RGBA_UNORM_SRGB],
109
+ [137, "VK_FORMAT_BC3_UNORM_BLOCK", TextureFormat.BC3_RGBA_UNORM],
110
+ [138, "VK_FORMAT_BC3_SRGB_BLOCK", TextureFormat.BC3_RGBA_UNORM_SRGB],
111
+ [139, "VK_FORMAT_BC4_UNORM_BLOCK", TextureFormat.BC4_R_UNORM],
112
+ [140, "VK_FORMAT_BC4_SNORM_BLOCK", TextureFormat.BC4_R_SNORM],
113
+ [141, "VK_FORMAT_BC5_UNORM_BLOCK", TextureFormat.BC5_RG_UNORM],
114
+ [142, "VK_FORMAT_BC5_SNORM_BLOCK", TextureFormat.BC5_RG_SNORM],
115
+ [143, "VK_FORMAT_BC6H_UFLOAT_BLOCK", TextureFormat.BC6H_RGB_UFLOAT],
116
+ [144, "VK_FORMAT_BC6H_SFLOAT_BLOCK", TextureFormat.BC6H_RGB_FLOAT],
117
+ [145, "VK_FORMAT_BC7_UNORM_BLOCK", TextureFormat.BC7_RGBA_UNORM],
118
+ [146, "VK_FORMAT_BC7_SRGB_BLOCK", TextureFormat.BC7_RGBA_UNORM_SRGB],
119
+
120
+ // ETC2 and EAC
121
+ [147, "VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK", TextureFormat.ETC2_RGB8UNORM],
122
+ [148, "VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK", TextureFormat.ETC2_RGB8UNORM_SRGB],
123
+ [149, "VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK", TextureFormat.ETC2_RGB8A1UNORM],
124
+ [150, "VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK", TextureFormat.ETC2_RGB8A1UNORM_SRGB],
125
+ [151, "VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK", TextureFormat.ETC2_RGBA8UNORM],
126
+ [152, "VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK", TextureFormat.ETC2_RGBA8UNORM_SRGB],
127
+ [153, "VK_FORMAT_EAC_R11_UNORM_BLOCK", TextureFormat.EAC_R11UNORM],
128
+ [154, "VK_FORMAT_EAC_R11_SNORM_BLOCK", TextureFormat.EAC_R11SNORM],
129
+ [155, "VK_FORMAT_EAC_R11G11_UNORM_BLOCK", TextureFormat.EAC_RG11UNORM],
130
+ [156, "VK_FORMAT_EAC_R11G11_SNORM_BLOCK", TextureFormat.EAC_RG11SNORM],
131
+
132
+ // ASTC LDR — every block size WebGPU exposes, which is every block size Vulkan defines for LDR
133
+ [157, "VK_FORMAT_ASTC_4x4_UNORM_BLOCK", TextureFormat.ASTC_4X4_UNORM],
134
+ [158, "VK_FORMAT_ASTC_4x4_SRGB_BLOCK", TextureFormat.ASTC_4X4_UNORM_SRGB],
135
+ [159, "VK_FORMAT_ASTC_5x4_UNORM_BLOCK", TextureFormat.ASTC_5X4_UNORM],
136
+ [160, "VK_FORMAT_ASTC_5x4_SRGB_BLOCK", TextureFormat.ASTC_5X4_UNORM_SRGB],
137
+ [161, "VK_FORMAT_ASTC_5x5_UNORM_BLOCK", TextureFormat.ASTC_5X5_UNORM],
138
+ [162, "VK_FORMAT_ASTC_5x5_SRGB_BLOCK", TextureFormat.ASTC_5X5_UNORM_SRGB],
139
+ [163, "VK_FORMAT_ASTC_6x5_UNORM_BLOCK", TextureFormat.ASTC_6X5_UNORM],
140
+ [164, "VK_FORMAT_ASTC_6x5_SRGB_BLOCK", TextureFormat.ASTC_6X5_UNORM_SRGB],
141
+ [165, "VK_FORMAT_ASTC_6x6_UNORM_BLOCK", TextureFormat.ASTC_6X6_UNORM],
142
+ [166, "VK_FORMAT_ASTC_6x6_SRGB_BLOCK", TextureFormat.ASTC_6X6_UNORM_SRGB],
143
+ [167, "VK_FORMAT_ASTC_8x5_UNORM_BLOCK", TextureFormat.ASTC_8X5_UNORM],
144
+ [168, "VK_FORMAT_ASTC_8x5_SRGB_BLOCK", TextureFormat.ASTC_8X5_UNORM_SRGB],
145
+ [169, "VK_FORMAT_ASTC_8x6_UNORM_BLOCK", TextureFormat.ASTC_8X6_UNORM],
146
+ [170, "VK_FORMAT_ASTC_8x6_SRGB_BLOCK", TextureFormat.ASTC_8X6_UNORM_SRGB],
147
+ [171, "VK_FORMAT_ASTC_8x8_UNORM_BLOCK", TextureFormat.ASTC_8X8_UNORM],
148
+ [172, "VK_FORMAT_ASTC_8x8_SRGB_BLOCK", TextureFormat.ASTC_8X8_UNORM_SRGB],
149
+ [173, "VK_FORMAT_ASTC_10x5_UNORM_BLOCK", TextureFormat.ASTC_10X5_UNORM],
150
+ [174, "VK_FORMAT_ASTC_10x5_SRGB_BLOCK", TextureFormat.ASTC_10X5_UNORM_SRGB],
151
+ [175, "VK_FORMAT_ASTC_10x6_UNORM_BLOCK", TextureFormat.ASTC_10X6_UNORM],
152
+ [176, "VK_FORMAT_ASTC_10x6_SRGB_BLOCK", TextureFormat.ASTC_10X6_UNORM_SRGB],
153
+ [177, "VK_FORMAT_ASTC_10x8_UNORM_BLOCK", TextureFormat.ASTC_10X8_UNORM],
154
+ [178, "VK_FORMAT_ASTC_10x8_SRGB_BLOCK", TextureFormat.ASTC_10X8_UNORM_SRGB],
155
+ [179, "VK_FORMAT_ASTC_10x10_UNORM_BLOCK", TextureFormat.ASTC_10X10_UNORM],
156
+ [180, "VK_FORMAT_ASTC_10x10_SRGB_BLOCK", TextureFormat.ASTC_10X10_UNORM_SRGB],
157
+ [181, "VK_FORMAT_ASTC_12x10_UNORM_BLOCK", TextureFormat.ASTC_12X10_UNORM],
158
+ [182, "VK_FORMAT_ASTC_12x10_SRGB_BLOCK", TextureFormat.ASTC_12X10_UNORM_SRGB],
159
+ [183, "VK_FORMAT_ASTC_12x12_UNORM_BLOCK", TextureFormat.ASTC_12X12_UNORM],
160
+ [184, "VK_FORMAT_ASTC_12x12_SRGB_BLOCK", TextureFormat.ASTC_12X12_UNORM_SRGB],
161
+ ];
162
+
163
+ /**
164
+ * `[vkFormat, Vulkan name, why it cannot be mapped]`.
165
+ *
166
+ * Not the whole of what is missing — Vulkan defines hundreds of formats and most will never appear
167
+ * in a texture file — but every entry here is one a real encoder emits, so a file that hits one is
168
+ * told what is wrong with it rather than handed a bare number. Anything outside both tables is
169
+ * refused by number, which is the honest answer for a format this reader has never heard of.
170
+ *
171
+ * @type {[number, string, string][]}
172
+ */
173
+ const UNMAPPABLE = [
174
+ [15, "VK_FORMAT_R8_SRGB", "WebGPU has no single-channel sRGB format"],
175
+ [22, "VK_FORMAT_R8G8_SRGB", "WebGPU has no two-channel sRGB format"],
176
+
177
+ [23, "VK_FORMAT_R8G8B8_UNORM", "WebGPU has no three-channel formats; re-encode with an alpha channel"],
178
+ [29, "VK_FORMAT_R8G8B8_SRGB", "WebGPU has no three-channel formats; re-encode with an alpha channel"],
179
+ [30, "VK_FORMAT_B8G8R8_UNORM", "WebGPU has no three-channel formats; re-encode with an alpha channel"],
180
+ [36, "VK_FORMAT_B8G8R8_SRGB", "WebGPU has no three-channel formats; re-encode with an alpha channel"],
181
+ [90, "VK_FORMAT_R16G16B16_SFLOAT", "WebGPU has no three-channel formats; re-encode with an alpha channel"],
182
+ [106, "VK_FORMAT_R32G32B32_SFLOAT", "WebGPU has no three-channel formats; re-encode with an alpha channel"],
183
+
184
+ [45, "VK_FORMAT_B8G8R8A8_SNORM", "WebGPU exposes BGRA as unorm and unorm-srgb only"],
185
+ [48, "VK_FORMAT_B8G8R8A8_UINT", "WebGPU exposes BGRA as unorm and unorm-srgb only"],
186
+ [49, "VK_FORMAT_B8G8R8A8_SINT", "WebGPU exposes BGRA as unorm and unorm-srgb only"],
187
+
188
+ [58, "VK_FORMAT_A2R10G10B10_UNORM_PACK32", "WebGPU packs ten-bit channels as rgb10a2 only, which is Vulkan's A2B10G10R10 order"],
189
+ [62, "VK_FORMAT_A2R10G10B10_UINT_PACK32", "WebGPU packs ten-bit channels as rgb10a2 only, which is Vulkan's A2B10G10R10 order"],
190
+ [65, "VK_FORMAT_A2B10G10R10_SNORM_PACK32", "WebGPU exposes rgb10a2 as unorm and uint only"],
191
+ [69, "VK_FORMAT_A2B10G10R10_SINT_PACK32", "WebGPU exposes rgb10a2 as unorm and uint only"],
192
+
193
+ [124, "VK_FORMAT_D16_UNORM", "depth and stencil are render pass state rather than image content"],
194
+ [126, "VK_FORMAT_D32_SFLOAT", "depth and stencil are render pass state rather than image content"],
195
+ [125, "VK_FORMAT_X8_D24_UNORM_PACK32", "depth and stencil are render pass state rather than image content"],
196
+ [127, "VK_FORMAT_S8_UINT", "depth and stencil are render pass state rather than image content"],
197
+ [129, "VK_FORMAT_D24_UNORM_S8_UINT", "depth and stencil are render pass state rather than image content"],
198
+ [130, "VK_FORMAT_D32_SFLOAT_S8_UINT", "depth and stencil are render pass state rather than image content"],
199
+
200
+ /*
201
+ Named rather than mapped, deliberately. These two are byte-identical to VK_FORMAT_R8G8B8A8_UNORM
202
+ and _SRGB — but only on a little-endian host, because a PACK32 format names its components from
203
+ the most significant bit of a 32-bit word rather than in memory order. Mapping them would bake
204
+ an endianness assumption into the one table whose entire claim is that a mapping is a pair of
205
+ names for one byte layout.
206
+ */
207
+ [51, "VK_FORMAT_A8B8G8R8_UNORM_PACK32", "a packed spelling whose byte order depends on the host; re-declare it as VK_FORMAT_R8G8B8A8_UNORM, which states the layout the payload actually has"],
208
+ [57, "VK_FORMAT_A8B8G8R8_SRGB_PACK32", "a packed spelling whose byte order depends on the host; re-declare it as VK_FORMAT_R8G8B8A8_SRGB, which states the layout the payload actually has"],
209
+ ];
210
+
211
+ /**
212
+ * @type {Map<number, TextureFormat>}
213
+ */
214
+ const FORMAT_BY_VK = new Map(MAPPED.map(([vk, , format]) => [vk, format]));
215
+
216
+ /**
217
+ * @type {Map<number, string>}
218
+ */
219
+ const NAME_BY_VK = new Map([
220
+ [VK_FORMAT_UNDEFINED, "VK_FORMAT_UNDEFINED"],
221
+ ...MAPPED.map(([vk, name]) => [vk, name]),
222
+ ...UNMAPPABLE.map(([vk, name]) => [vk, name]),
223
+ ]);
224
+
225
+ /**
226
+ * @type {Map<number, string>}
227
+ */
228
+ const REASON_BY_VK = new Map(UNMAPPABLE.map(([vk, , reason]) => [vk, reason]));
229
+
230
+ /**
231
+ * Every `vkFormat` this module maps, for a test that wants to sweep them.
232
+ *
233
+ * @returns {number[]}
234
+ */
235
+ export function vk_formats_mapped() {
236
+ return MAPPED.map(([vk]) => vk);
237
+ }
238
+
239
+ /**
240
+ * Every `vkFormat` this module names but deliberately does not map, for the test that keeps the two
241
+ * tables from overlapping.
242
+ *
243
+ * @returns {number[]}
244
+ */
245
+ export function vk_formats_unmappable() {
246
+ return UNMAPPABLE.map(([vk]) => vk);
247
+ }
248
+
249
+ /**
250
+ * The Vulkan name of `vk_format`, where this module knows it.
251
+ *
252
+ * @param {number} vk_format
253
+ * @returns {string} the `VK_FORMAT_…` name, or `vkFormat <n>` for one outside both tables
254
+ */
255
+ export function vk_format_name(vk_format) {
256
+ return NAME_BY_VK.get(vk_format) ?? `vkFormat ${vk_format}`;
257
+ }
258
+
259
+ /**
260
+ * The {@link TextureFormat} holding the same bytes as `vk_format`.
261
+ *
262
+ * Byte for byte, not approximately: every mapping here is a pair of names for one memory layout, so
263
+ * a payload passes through unchanged and the only thing the mapping decides is what the sampler is
264
+ * told about it. The single caveat is BC1, noted beside its rows in the table.
265
+ *
266
+ * @param {number} vk_format as read from a KTX2 header
267
+ * @returns {TextureFormat}
268
+ * @throws {Error} naming the format, for one WebGPU does not expose
269
+ */
270
+ export function vk_format_to_texture_format(vk_format) {
271
+ const format = FORMAT_BY_VK.get(vk_format);
272
+
273
+ if (format !== undefined) {
274
+ return format;
275
+ }
276
+
277
+ const reason = REASON_BY_VK.get(vk_format);
278
+
279
+ if (reason !== undefined) {
280
+ throw new Error(
281
+ `${vk_format_name(vk_format)} (vkFormat ${vk_format}) has no GPUTextureFormat: ${reason}`
282
+ );
283
+ }
284
+
285
+ throw new Error(
286
+ `vkFormat ${vk_format} is not a format this reader maps to a GPUTextureFormat.`
287
+ + ` Only formats WebGPU exposes can be sampled, and this one is either outside that set or`
288
+ + ` outside the set of Vulkan formats a texture file has been seen to carry.`
289
+ );
290
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Useful for when WebGPU constants are not available.
3
+ *
4
+ * Unlike {@link GPUTextureFormat }, which is a WebIDL enum and therefore just a string, `GPUTextureUsage`
5
+ * is a real global namespace object. Reading it where WebGPU is absent throws a `ReferenceError` —
6
+ * and a class field such as {@link TextureDescriptor }'s `usage` reads it at *module load*, so the
7
+ * `import` itself throws before any code runs.
8
+ *
9
+ * Under vitest a stub in `vitest.setup.mjs` covers that. Nothing covers it anywhere else: a CLI, an
10
+ * asset-pipeline script, or an offline texture encoder is not a test, and importing a descriptor
11
+ * from one has to work.
12
+ *
13
+ * Companion to {@link GPUShaderStage }, for the same reason.
14
+ */
15
+ export type GPUTextureUsage = number;
16
+ export namespace GPUTextureUsage {
17
+ let COPY_SRC: number;
18
+ let COPY_DST: number;
19
+ let TEXTURE_BINDING: number;
20
+ let STORAGE_BINDING: number;
21
+ let RENDER_ATTACHMENT: number;
22
+ }
23
+ //# sourceMappingURL=GPUTextureUsage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GPUTextureUsage.d.ts","sourceRoot":"","sources":["../../../../src/shade/descriptor/GPUTextureUsage.js"],"names":[],"mappings":";;;;;;;;;;;;;;8BAeU,MAAM"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Useful for when WebGPU constants are not available.
3
+ *
4
+ * Unlike {@link GPUTextureFormat}, which is a WebIDL enum and therefore just a string, `GPUTextureUsage`
5
+ * is a real global namespace object. Reading it where WebGPU is absent throws a `ReferenceError` —
6
+ * and a class field such as {@link TextureDescriptor}'s `usage` reads it at *module load*, so the
7
+ * `import` itself throws before any code runs.
8
+ *
9
+ * Under vitest a stub in `vitest.setup.mjs` covers that. Nothing covers it anywhere else: a CLI, an
10
+ * asset-pipeline script, or an offline texture encoder is not a test, and importing a descriptor
11
+ * from one has to work.
12
+ *
13
+ * Companion to {@link GPUShaderStage}, for the same reason.
14
+ *
15
+ * @see https://www.w3.org/TR/webgpu/#namespacedef-gputextureusage
16
+ * @enum {number}
17
+ */
18
+ export const GPUTextureUsage = {
19
+ COPY_SRC: 0x01,
20
+ COPY_DST: 0x02,
21
+ TEXTURE_BINDING: 0x04,
22
+ STORAGE_BINDING: 0x08,
23
+ RENDER_ATTACHMENT: 0x10,
24
+ }
@@ -7,5 +7,8 @@ export namespace WebGPUExtensionType {
7
7
  let Float32Filterable: string;
8
8
  let ShaderF16: string;
9
9
  let TextureFormatsTier1: string;
10
+ let TextureCompressionBC: string;
11
+ let TextureCompressionETC2: string;
12
+ let TextureCompressionASTC: string;
10
13
  }
11
14
  //# sourceMappingURL=WebGPUExtensionType.d.ts.map
@@ -59,4 +59,30 @@ export const WebGPUExtensionType = {
59
59
  * @see https://www.w3.org/TR/webgpu/#texture-formats-tier1
60
60
  */
61
61
  TextureFormatsTier1: "texture-formats-tier1",
62
+
63
+ /**
64
+ * Adds the BC (S3TC / DXT / RGTC / BPTC) compressed texture formats — `bc1` through `bc7`.
65
+ *
66
+ * Desktop's compression family. Sampling one costs nothing: the hardware decodes it, which is
67
+ * the whole reason to ship textures this way rather than transcoding on load.
68
+ *
69
+ * @see https://www.w3.org/TR/webgpu/#texture-compression-bc
70
+ */
71
+ TextureCompressionBC: "texture-compression-bc",
72
+
73
+ /**
74
+ * Adds the ETC2 and EAC compressed texture formats.
75
+ *
76
+ * @see https://www.w3.org/TR/webgpu/#texture-compression-etc2
77
+ */
78
+ TextureCompressionETC2: "texture-compression-etc2",
79
+
80
+ /**
81
+ * Adds the ASTC compressed texture formats, every block size.
82
+ *
83
+ * Mobile and Apple's family, and the one with a block-size choice to make.
84
+ *
85
+ * @see https://www.w3.org/TR/webgpu/#texture-compression-astc
86
+ */
87
+ TextureCompressionASTC: "texture-compression-astc",
62
88
  }
@@ -52,15 +52,11 @@ export class TextureDescriptor extends ObjectDescriptorBase implements GPUTextur
52
52
  height: number;
53
53
  depthOrArrayLayers: number;
54
54
  };
55
- /**
56
- *
57
- * @return {number}
58
- */
59
- get bits_per_sample(): number;
60
55
  /**
61
56
  * The number is just an estimate, actual VRAM usage will depend on the GPU.
62
57
  * Usually accurate, but when it's not - it's close.
63
- * @returns {number}
58
+ *
59
+ * @returns {number} bytes
64
60
  */
65
61
  get memory_footprint(): number;
66
62
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"TextureDescriptor.d.ts","sourceRoot":"","sources":["../../../../../src/shade/descriptor/texture/TextureDescriptor.js"],"names":[],"mappings":"AA+BA;;;GAGG;AACH,uEAFe,oBAAoB;IA8K/B;;;;OAIG;IACH,yCAFY,iBAAiB,CAQ5B;IA/KD,sBAAkB;IAClB,oBAAgB;IAEhB;;;OAGG;IACH,WAFU,sBAAoB,MAAM,CAEnB;IAEjB;;OAEG;IACH,yBAAsB;IAEtB;;OAEG;IACH,OAFU,MAAM,uBAAqB,CAEG;IAExC;;;OAGG;IACH,aAFU,kBAAkB,CAEX;IAEjB;;;OAGG;IACH,eAAyB;IAEzB;;;OAGG;IACH;eAU4B,MAAM;gBAAS,MAAM;4BAAqB,MAAM;OAJ3E;IAED;;;OAGG;IACH;eAF4B,MAAM;gBAAS,MAAM;4BAAqB,MAAM;MAI3E;IAGD;;;OAGG;IACH,8BAkBC;IAGD;;;;OAIG;IACH,+BAgBC;IAED;;;;OAIG;IACH,cAHW,iBAAiB,GAChB,OAAO,CAelB;IAED;;;OAGG;IACH,YAFW,iBAAiB,QAa3B;IAcD;;;OAGG;IACH,uCASC;IAeD;;;OAGG;IACH,2CAwCC;IAIL;;;OAGG;IACH,8BAFU,OAAO,CAE8B;;CAP9C;qCAjQoC,4BAA4B"}
1
+ {"version":3,"file":"TextureDescriptor.d.ts","sourceRoot":"","sources":["../../../../../src/shade/descriptor/texture/TextureDescriptor.js"],"names":[],"mappings":"AAgCA;;;GAGG;AACH,uEAFe,oBAAoB;IA6J/B;;;;OAIG;IACH,yCAFY,iBAAiB,CAQ5B;IA9JD,sBAAkB;IAClB,oBAAgB;IAEhB;;;OAGG;IACH,WAFU,sBAAoB,MAAM,CAEnB;IAEjB;;OAEG;IACH,yBAAsB;IAEtB;;OAEG;IACH,OAFU,MAAM,uBAAqB,CAEG;IAExC;;;OAGG;IACH,aAFU,kBAAkB,CAEX;IAEjB;;;OAGG;IACH,eAAyB;IAEzB;;;OAGG;IACH;eAU4B,MAAM;gBAAS,MAAM;4BAAqB,MAAM;OAJ3E;IAED;;;OAGG;IACH;eAF4B,MAAM;gBAAS,MAAM;4BAAqB,MAAM;MAI3E;IAGD;;;;;OAKG;IACH,+BAuBC;IAED;;;;OAIG;IACH,cAHW,iBAAiB,GAChB,OAAO,CAelB;IAED;;;OAGG;IACH,YAFW,iBAAiB,QAa3B;IAcD;;;OAGG;IACH,uCASC;IAeD;;;OAGG;IACH,2CAwCC;IAIL;;;OAGG;IACH,8BAFU,OAAO,CAE8B;;CAP9C;qCAjPoC,4BAA4B"}