@woosh/meep-engine 3.14.0 → 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 +33 -64
  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
@@ -1 +1 @@
1
- {"version":3,"file":"TextureManager.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/texture/TextureManager.js"],"names":[],"mappings":"AA2CA;IAiCI;;;OAGG;IACH,+BAIC;IAtBD;;;OAGG;IACH,qCAEC;IAkBD;;;;OAIG;IACH,6BAFa,iBAAiB,CAY7B;IAED;;;;OAIG;IACH,8CAFa,iBAAiB,CA4B7B;IAeD;;;;OAIG;IACH,kCAHW,iBAAiB,GACf,iBAAiB,CAa7B;IAED,eAEC;IAED,+BAQC;;CACJ;sCAhLqC,oCAAoC;kCADxC,wBAAwB;kCADxB,+CAA+C"}
1
+ {"version":3,"file":"TextureManager.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/texture/TextureManager.js"],"names":[],"mappings":"AA2CA;IAiCI;;;OAGG;IACH,+BAIC;IAtBD;;;OAGG;IACH,qCAEC;IAkBD;;;;OAIG;IACH,6BAFa,iBAAiB,CAY7B;IAED;;;;OAIG;IACH,8CAFa,iBAAiB,CAwC7B;IAeD;;;;OAIG;IACH,kCAHW,iBAAiB,GACf,iBAAiB,CAa7B;IAED,eAEC;IAED,+BAQC;;CACJ;sCA5LqC,oCAAoC;kCADxC,wBAAwB;kCADxB,+CAA+C"}
@@ -121,10 +121,22 @@ export class TextureManager {
121
121
 
122
122
  const ctx = this.contextFromDescriptor(descriptor);
123
123
 
124
- // copy data into texture
125
- this.#image_to_texture(shade.image, ctx.gpu_texture);
126
-
127
- if ((shade.flags & ShadeTextureFlags.GenerateMipMaps) !== 0) {
124
+ /*
125
+ The flag is an instruction, and the descriptor builder has already refused it for any
126
+ format the generator cannot render into — so reaching here with it set means it is
127
+ going to happen. Only the base level is uploaded in that case: the generator produces
128
+ every level above it, and sending levels it is about to overwrite is bytes across the
129
+ bus for nothing.
130
+ */
131
+ const generate = (shade.flags & ShadeTextureFlags.GenerateMipMaps) !== 0;
132
+
133
+ this.#image_to_texture(
134
+ shade.image,
135
+ ctx.gpu_texture,
136
+ generate ? 1 : shade.image.level_count
137
+ );
138
+
139
+ if (generate) {
128
140
  this.#mipmaps.schedule(ctx.gpu_texture, descriptor, shade.mipmapGenerationFilter);
129
141
  }
130
142
 
@@ -138,13 +150,13 @@ export class TextureManager {
138
150
  *
139
151
  * @param {ShadeImage} image
140
152
  * @param {GPUTexture} texture
153
+ * @param {number} level_count how many of the image's levels to upload
141
154
  */
142
- #image_to_texture(image, texture) {
143
-
144
-
155
+ #image_to_texture(image, texture, level_count) {
145
156
  const device = this.#device;
146
157
  const queue = device.queue;
147
- texture_write_to_gpu(image, texture, queue);
158
+
159
+ texture_write_to_gpu(image, texture, queue, level_count);
148
160
  }
149
161
 
150
162
  /**
@@ -0,0 +1,19 @@
1
+ /**
2
+ * What a texture is *for*, as far as choosing an encoding for it goes.
3
+ *
4
+ * The renderer knows things about its material slots that no general image pipeline does: that a
5
+ * normal map's channels are a direction and band visibly under a codec tuned for colour, that an ORM
6
+ * map is linear data whose channels are independent, that albedo is the one people look at. Those
7
+ * facts pick a format, so they have to be sayable.
8
+ *
9
+ * The same distinction {@link image_compression_quality_from_usage } already draws for the AVIF
10
+ * encoder, named once instead of twice.
11
+ */
12
+ export type TextureRole = number;
13
+ export namespace TextureRole {
14
+ let Albedo: number;
15
+ let Normal: number;
16
+ let Orm: number;
17
+ let Emissive: number;
18
+ }
19
+ //# sourceMappingURL=TextureRole.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextureRole.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/texture/TextureRole.js"],"names":[],"mappings":";;;;;;;;;;;0BAWU,MAAM"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * What a texture is *for*, as far as choosing an encoding for it goes.
3
+ *
4
+ * The renderer knows things about its material slots that no general image pipeline does: that a
5
+ * normal map's channels are a direction and band visibly under a codec tuned for colour, that an ORM
6
+ * map is linear data whose channels are independent, that albedo is the one people look at. Those
7
+ * facts pick a format, so they have to be sayable.
8
+ *
9
+ * The same distinction {@link image_compression_quality_from_usage} already draws for the AVIF
10
+ * encoder, named once instead of twice.
11
+ *
12
+ * @enum {number}
13
+ */
14
+ export const TextureRole = {
15
+ /** Base colour. sRGB, alpha may carry cutout or transparency. */
16
+ Albedo: 0,
17
+
18
+ /** Tangent-space normals. Linear, and the channels are a direction rather than a colour. */
19
+ Normal: 1,
20
+
21
+ /** Occlusion / roughness / metalness, packed per channel. Linear, channels independent. */
22
+ Orm: 2,
23
+
24
+ /** Emitted colour. sRGB, like albedo. */
25
+ Emissive: 3,
26
+ };
@@ -0,0 +1,71 @@
1
+ /**
2
+ * What was built for one texture, and where each encoding lives.
3
+ *
4
+ * A texture is not one resource with variants inside it — it is several resources, one per format,
5
+ * and a client fetches the one it wants. This is the manifest that makes that possible: **which
6
+ * encodings exist, known before the first request.** Discovering them by requesting would cost a 404
7
+ * round trip per format a device prefers and nobody built, walking down the preference list, which on
8
+ * a streaming engine is the worst place to put a stall.
9
+ *
10
+ * The {@link fallback} is not a contingency bolted on; it is the entry with no format constraint, and
11
+ * it is what a device with no compression support, a tool, or a test asks for. Every set has one, so
12
+ * selection always has an answer.
13
+ *
14
+ * Deliberately dumb about *content*: it says a format was built and where the bytes are, and nothing
15
+ * about what they decode to. The reader determines that from the payload's own header, which is why
16
+ * a manifest that lies produces a failed read rather than a texture full of garbage.
17
+ */
18
+ export class TextureVariantSet {
19
+ /**
20
+ * Read one entry of a manifest.
21
+ *
22
+ * ```json
23
+ * {
24
+ * "fallback": "textures/wall_albedo.avif",
25
+ * "formats": {
26
+ * "bc7-rgba-unorm": "textures/wall_albedo.bc7.ktx2",
27
+ * "astc-4x4-unorm": "textures/wall_albedo.astc.ktx2"
28
+ * }
29
+ * }
30
+ * ```
31
+ *
32
+ * Format names are the WebGPU strings, and the non-srgb ones: `bc7-rgba-unorm` and
33
+ * `bc7-rgba-unorm-srgb` are the same bytes, so srgb-ness is not a property of the encoding to be
34
+ * listed here — it is chosen when the texture is created, from the image's colour space.
35
+ *
36
+ * @param {{fallback: string, formats?: Object<GPUTextureFormat, string>}} json
37
+ * @returns {TextureVariantSet}
38
+ */
39
+ static fromJSON(json: {
40
+ fallback: string;
41
+ formats?: any;
42
+ }): TextureVariantSet;
43
+ /**
44
+ * @param {string} fallback path of the universally readable encoding
45
+ * @param {Iterable<[GPUTextureFormat, string]>} by_format one entry per format that was built
46
+ */
47
+ constructor(fallback: string, by_format: Iterable<[GPUTextureFormat, string]>);
48
+ /**
49
+ * Path of the encoding every device can read — AVIF, PNG, whatever ships.
50
+ *
51
+ * @type {string}
52
+ * @readonly
53
+ */
54
+ readonly fallback: string;
55
+ /**
56
+ * @param {GPUTextureFormat} format
57
+ * @returns {boolean} whether this encoding was built
58
+ */
59
+ has(format: GPUTextureFormat): boolean;
60
+ /**
61
+ * @param {GPUTextureFormat} format
62
+ * @returns {string|undefined} where it lives, or nothing when it was not built
63
+ */
64
+ path(format: GPUTextureFormat): string | undefined;
65
+ /**
66
+ * @returns {GPUTextureFormat[]} every format built for this texture, fallback excluded
67
+ */
68
+ get formats(): GPUTextureFormat[];
69
+ #private;
70
+ }
71
+ //# sourceMappingURL=TextureVariantSet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextureVariantSet.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/texture/TextureVariantSet.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AACH;IA0DI;;;;;;;;;;;;;;;;;;;OAmBG;IACH,sBAHW;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,MAAkC;KAAC,GAC5D,iBAAiB,CAO7B;IArED;;;OAGG;IACH,sBAHW,MAAM,aACN,SAAS,mBAAmB,MAAM,CAAC,CAAC,EAiB9C;IAhCD;;;;;OAKG;IACH,mBAHU,MAAM,CAGP;IA4BT;;;OAGG;IACH,+BAFa,OAAO,CAInB;IAED;;;OAGG;IACH,gCAFa,MAAM,GAAC,SAAS,CAI5B;IAED;;OAEG;IACH,kCAEC;;CA4BJ"}
@@ -0,0 +1,105 @@
1
+ import { assert } from "../../../core/assert.js";
2
+ import { gpu_texture_format_info } from "../../descriptor/texture/format/gpu_texture_format_info.js";
3
+
4
+ /**
5
+ * What was built for one texture, and where each encoding lives.
6
+ *
7
+ * A texture is not one resource with variants inside it — it is several resources, one per format,
8
+ * and a client fetches the one it wants. This is the manifest that makes that possible: **which
9
+ * encodings exist, known before the first request.** Discovering them by requesting would cost a 404
10
+ * round trip per format a device prefers and nobody built, walking down the preference list, which on
11
+ * a streaming engine is the worst place to put a stall.
12
+ *
13
+ * The {@link fallback} is not a contingency bolted on; it is the entry with no format constraint, and
14
+ * it is what a device with no compression support, a tool, or a test asks for. Every set has one, so
15
+ * selection always has an answer.
16
+ *
17
+ * Deliberately dumb about *content*: it says a format was built and where the bytes are, and nothing
18
+ * about what they decode to. The reader determines that from the payload's own header, which is why
19
+ * a manifest that lies produces a failed read rather than a texture full of garbage.
20
+ */
21
+ export class TextureVariantSet {
22
+ /**
23
+ * Path of the encoding every device can read — AVIF, PNG, whatever ships.
24
+ *
25
+ * @type {string}
26
+ * @readonly
27
+ */
28
+ fallback;
29
+
30
+ /**
31
+ * @type {Map<GPUTextureFormat, string>}
32
+ */
33
+ #by_format = new Map();
34
+
35
+ /**
36
+ * @param {string} fallback path of the universally readable encoding
37
+ * @param {Iterable<[GPUTextureFormat, string]>} by_format one entry per format that was built
38
+ */
39
+ constructor(fallback, by_format) {
40
+ assert.isString(fallback, 'fallback');
41
+ assert.defined(by_format, 'by_format');
42
+
43
+ for (const [format, path] of by_format) {
44
+ // throws for a name that is not a GPUTextureFormat — a manifest naming one is a build
45
+ // artefact nobody can ask for, and finding that out here beats finding it out at a fetch
46
+ gpu_texture_format_info(format);
47
+
48
+ assert.isString(path, `path for '${format}'`);
49
+
50
+ this.#by_format.set(format, path);
51
+ }
52
+
53
+ this.fallback = fallback;
54
+ }
55
+
56
+ /**
57
+ * @param {GPUTextureFormat} format
58
+ * @returns {boolean} whether this encoding was built
59
+ */
60
+ has(format) {
61
+ return this.#by_format.has(format);
62
+ }
63
+
64
+ /**
65
+ * @param {GPUTextureFormat} format
66
+ * @returns {string|undefined} where it lives, or nothing when it was not built
67
+ */
68
+ path(format) {
69
+ return this.#by_format.get(format);
70
+ }
71
+
72
+ /**
73
+ * @returns {GPUTextureFormat[]} every format built for this texture, fallback excluded
74
+ */
75
+ get formats() {
76
+ return Array.from(this.#by_format.keys());
77
+ }
78
+
79
+ /**
80
+ * Read one entry of a manifest.
81
+ *
82
+ * ```json
83
+ * {
84
+ * "fallback": "textures/wall_albedo.avif",
85
+ * "formats": {
86
+ * "bc7-rgba-unorm": "textures/wall_albedo.bc7.ktx2",
87
+ * "astc-4x4-unorm": "textures/wall_albedo.astc.ktx2"
88
+ * }
89
+ * }
90
+ * ```
91
+ *
92
+ * Format names are the WebGPU strings, and the non-srgb ones: `bc7-rgba-unorm` and
93
+ * `bc7-rgba-unorm-srgb` are the same bytes, so srgb-ness is not a property of the encoding to be
94
+ * listed here — it is chosen when the texture is created, from the image's colour space.
95
+ *
96
+ * @param {{fallback: string, formats?: Object<GPUTextureFormat, string>}} json
97
+ * @returns {TextureVariantSet}
98
+ */
99
+ static fromJSON(json) {
100
+ assert.defined(json, 'json');
101
+ assert.isString(json.fallback, 'json.fallback');
102
+
103
+ return new TextureVariantSet(json.fallback, Object.entries(json.formats ?? {}));
104
+ }
105
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"download_texture_data.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/texture/download_texture_data.js"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH,kGAFa,mBAAmB,CAsH/B"}
1
+ {"version":3,"file":"download_texture_data.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/texture/download_texture_data.js"],"names":[],"mappings":"AASA;;;;;;;;;GASG;AACH,kGAFa,mBAAmB,CAwI/B"}
@@ -1,6 +1,10 @@
1
1
  import { assert } from "../../../core/assert.js";
2
2
  import { round_up } from "../../../core/math/round_up.js";
3
3
  import { decode_typed_gpu_data } from "./format/decode_typed_gpu_data.js";
4
+ import {
5
+ gpu_texture_format_info,
6
+ gpu_texture_format_is_block_compressed
7
+ } from "../../descriptor/texture/format/gpu_texture_format_info.js";
4
8
  import { parse_gpu_texture_format } from "../../descriptor/texture/format/parse_gpu_texture_format.js";
5
9
 
6
10
  /**
@@ -61,6 +65,24 @@ export async function download_texture_data({
61
65
  label: "Download Texture Data"
62
66
  });
63
67
 
68
+ /*
69
+ Readback decodes texels into typed array elements, which a block-compressed format has none of —
70
+ `parse_gpu_texture_format`'s expression cannot parse one of their names and would fail with a
71
+ regex error naming nothing. Say what is actually wrong instead.
72
+
73
+ Not an oversight to fix later: there is no useful decoded form of a BC7 block on the CPU short of
74
+ a decoder, and a caller that wants the bytes wants `copyTextureToBuffer` rather than this.
75
+ */
76
+ const format_info = gpu_texture_format_info(source.format);
77
+
78
+ if (gpu_texture_format_is_block_compressed(source.format)) {
79
+ throw new Error(
80
+ `download_texture_data: '${source.format}' is block-compressed`
81
+ + ` (${format_info.block_width}x${format_info.block_height}), which has no per-texel`
82
+ + ` value to read back. Copy the raw blocks with copyTextureToBuffer instead.`
83
+ );
84
+ }
85
+
64
86
  // figure out data type
65
87
  const spec = parse_gpu_texture_format(source.format);
66
88
 
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Every compressed {@link GPUTextureFormat} this device can sample.
3
+ *
4
+ * WebGPU gates compression behind three optional features, all of them all-or-nothing within their
5
+ * family. This turns "which features did we get" into "which formats may we ask the network for",
6
+ * which is the question the asset layer actually has (§5).
7
+ *
8
+ * Empty is an ordinary answer, not a failure: a device with no compression support loads every scene
9
+ * through the uncompressed encoding, exactly as one did before any of this existed.
10
+ *
11
+ * @param {GPUDevice} device
12
+ * @returns {Set<GPUTextureFormat>}
13
+ */
14
+ export function gpu_texture_compression_support(device: GPUDevice): Set<GPUTextureFormat>;
15
+ //# sourceMappingURL=gpu_texture_compression_support.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpu_texture_compression_support.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/texture/format/gpu_texture_compression_support.js"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;GAYG;AACH,oEAFa,qBAAqB,CAoBjC"}
@@ -0,0 +1,50 @@
1
+ import { WebGPUExtensionType } from "../../../descriptor/WebGPUExtensionType.js";
2
+ import { gpu_texture_format_names } from "../../../descriptor/texture/format/gpu_texture_format_info.js";
3
+
4
+ /**
5
+ * Which compressed formats a feature name brings with it.
6
+ *
7
+ * Derived from the format table's own names rather than listed, because the three families partition
8
+ * it cleanly by prefix and a hand-written list is one more thing to forget a format from.
9
+ *
10
+ * @type {[GPUFeatureName, RegExp][]}
11
+ */
12
+ const FAMILIES = [
13
+ [WebGPUExtensionType.TextureCompressionBC, /^bc[0-9]/],
14
+ // ETC2 and EAC arrive together, under one feature
15
+ [WebGPUExtensionType.TextureCompressionETC2, /^(etc2|eac)-/],
16
+ [WebGPUExtensionType.TextureCompressionASTC, /^astc-/],
17
+ ];
18
+
19
+ /**
20
+ * Every compressed {@link GPUTextureFormat} this device can sample.
21
+ *
22
+ * WebGPU gates compression behind three optional features, all of them all-or-nothing within their
23
+ * family. This turns "which features did we get" into "which formats may we ask the network for",
24
+ * which is the question the asset layer actually has (§5).
25
+ *
26
+ * Empty is an ordinary answer, not a failure: a device with no compression support loads every scene
27
+ * through the uncompressed encoding, exactly as one did before any of this existed.
28
+ *
29
+ * @param {GPUDevice} device
30
+ * @returns {Set<GPUTextureFormat>}
31
+ */
32
+ export function gpu_texture_compression_support(device) {
33
+ const features = device.features;
34
+
35
+ const supported = new Set();
36
+
37
+ for (const [feature, pattern] of FAMILIES) {
38
+ if (!features.has(feature)) {
39
+ continue;
40
+ }
41
+
42
+ for (const format of gpu_texture_format_names()) {
43
+ if (pattern.test(format)) {
44
+ supported.add(format);
45
+ }
46
+ }
47
+ }
48
+
49
+ return supported;
50
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Whether {@link WebGPUMipmapGenerator} can produce this format's mip levels.
3
+ *
4
+ * It generates by *rendering* between mip levels, so the question is whether the format can be a
5
+ * colour attachment. Three classes cannot:
6
+ *
7
+ * 1. **Block-compressed.** BC, ETC2 and ASTC are neither render attachments nor storage bindings,
8
+ * and nothing on the device turns a BC7 base level into BC7 mips. Their mips come from whatever
9
+ * encoded them, and that is the case this predicate exists for.
10
+ * 2. **Depth and stencil.** Renderable, but not as *colour*, which is what the generator's pipeline
11
+ * writes.
12
+ * 3. **`snorm`, and `rgb9e5ufloat`.** Sampleable colour formats that WebGPU does not allow as
13
+ * attachments — a gap that predates compressed textures and would otherwise surface as a
14
+ * pipeline-creation failure deep inside the generator.
15
+ *
16
+ * **Not a general renderability table.** Anything outside those three classes answers `true`, which
17
+ * is right for every format the engine currently produces and is not a promise about exotic ones —
18
+ * `rg11b10ufloat` is renderable only with a feature enabled, and this does not check for it. The
19
+ * value of answering here rather than in `createRenderPipeline` is a message that names the texture
20
+ * and says what to do instead.
21
+ *
22
+ * @param {GPUTextureFormat} format
23
+ * @returns {boolean}
24
+ * @throws {Error} for a name that is not a GPUTextureFormat
25
+ */
26
+ export function gpu_texture_format_can_generate_mipmaps(format: GPUTextureFormat): boolean;
27
+ //# sourceMappingURL=gpu_texture_format_can_generate_mipmaps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpu_texture_format_can_generate_mipmaps.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.js"],"names":[],"mappings":"AAyBA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,mFAHa,OAAO,CAiBnB"}
@@ -0,0 +1,65 @@
1
+ import {
2
+ gpu_texture_format_info,
3
+ gpu_texture_format_is_block_compressed
4
+ } from "../../../descriptor/texture/format/gpu_texture_format_info.js";
5
+
6
+ /**
7
+ * Formats that are colour formats and still cannot be a render attachment.
8
+ *
9
+ * Every `snorm` format, plus the shared-exponent packed one. Listed rather than matched on the name
10
+ * for the reason {@link gpu_texture_format_info} gives about its own table — though here the name
11
+ * would in fact carry it, a name-shaped rule invites the next entry to be added by pattern instead of
12
+ * by specification.
13
+ *
14
+ * @type {Set<GPUTextureFormat>}
15
+ */
16
+ const NOT_RENDERABLE = new Set([
17
+ "r8snorm",
18
+ "rg8snorm",
19
+ "rgba8snorm",
20
+ "r16snorm",
21
+ "rg16snorm",
22
+ "rgba16snorm",
23
+ "rgb9e5ufloat",
24
+ ]);
25
+
26
+ /**
27
+ * Whether {@link WebGPUMipmapGenerator} can produce this format's mip levels.
28
+ *
29
+ * It generates by *rendering* between mip levels, so the question is whether the format can be a
30
+ * colour attachment. Three classes cannot:
31
+ *
32
+ * 1. **Block-compressed.** BC, ETC2 and ASTC are neither render attachments nor storage bindings,
33
+ * and nothing on the device turns a BC7 base level into BC7 mips. Their mips come from whatever
34
+ * encoded them, and that is the case this predicate exists for.
35
+ * 2. **Depth and stencil.** Renderable, but not as *colour*, which is what the generator's pipeline
36
+ * writes.
37
+ * 3. **`snorm`, and `rgb9e5ufloat`.** Sampleable colour formats that WebGPU does not allow as
38
+ * attachments — a gap that predates compressed textures and would otherwise surface as a
39
+ * pipeline-creation failure deep inside the generator.
40
+ *
41
+ * **Not a general renderability table.** Anything outside those three classes answers `true`, which
42
+ * is right for every format the engine currently produces and is not a promise about exotic ones —
43
+ * `rg11b10ufloat` is renderable only with a feature enabled, and this does not check for it. The
44
+ * value of answering here rather than in `createRenderPipeline` is a message that names the texture
45
+ * and says what to do instead.
46
+ *
47
+ * @param {GPUTextureFormat} format
48
+ * @returns {boolean}
49
+ * @throws {Error} for a name that is not a GPUTextureFormat
50
+ */
51
+ export function gpu_texture_format_can_generate_mipmaps(format) {
52
+ const info = gpu_texture_format_info(format);
53
+
54
+ if (gpu_texture_format_is_block_compressed(format)) {
55
+ // block-compressed: no attachment, no storage, no way to write a mip on the device
56
+ return false;
57
+ }
58
+
59
+ if (info.aspects.length !== 1 || info.aspects[0] !== "all") {
60
+ // depth and/or stencil — not a colour attachment
61
+ return false;
62
+ }
63
+
64
+ return !NOT_RENDERABLE.has(format);
65
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @param {number} channel_count
3
+ * @param {BinaryDataType} data_type
4
+ * @param {boolean} normalized
5
+ * @param {ColorSpace} color_space
6
+ * @returns {GPUTextureFormat}
7
+ */
8
+ export function infer_format_from_parameters(channel_count: number, data_type: BinaryDataType, normalized: boolean, color_space: ColorSpace): GPUTextureFormat;
9
+ import { BinaryDataType } from "../../../../core/binary/type/BinaryDataType.js";
10
+ import { ColorSpace } from "../ColorSpace.js";
11
+ //# sourceMappingURL=infer_format_from_parameters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer_format_from_parameters.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/texture/format/infer_format_from_parameters.js"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,4DANW,MAAM,aACN,cAAc,cACd,OAAO,eACP,UAAU,oBA6EpB;+BArF8B,gDAAgD;2BAEpD,kBAAkB"}
@@ -0,0 +1,88 @@
1
+ import { BinaryDataType } from "../../../../core/binary/type/BinaryDataType.js";
2
+ import { dataTypeByteSize } from "../../../../core/binary/type/DataTypeByteSizes.js";
3
+ import { ColorSpace } from "../ColorSpace.js";
4
+
5
+ /**
6
+ * @param {number} channel_count
7
+ * @param {BinaryDataType} data_type
8
+ * @param {boolean} normalized
9
+ * @param {ColorSpace} color_space
10
+ * @returns {GPUTextureFormat}
11
+ */
12
+ export function infer_format_from_parameters(
13
+ channel_count,
14
+ data_type,
15
+ normalized,
16
+ color_space
17
+ ) {
18
+
19
+ // Some channel counts are unsupported, specifically RGB, so we have to go up 1 to RGBA
20
+ const valid_channel_counts = [1, 2, 4];
21
+
22
+ let valid_channel_count = channel_count;
23
+
24
+ if (valid_channel_counts.includes(channel_count) === false) {
25
+ for (let i = 0; i < valid_channel_counts.length; i++) {
26
+ let vs = valid_channel_counts[i];
27
+
28
+ if (channel_count < vs) {
29
+ valid_channel_count = vs;
30
+ break;
31
+ }
32
+ }
33
+ }
34
+
35
+ const prefix = 'rgba'.slice(0, valid_channel_count);
36
+
37
+ const byte_size = dataTypeByteSize(data_type);
38
+
39
+ const bit_size = byte_size * 8;
40
+
41
+ let ending;
42
+ if (color_space === ColorSpace.LinearSRGB) {
43
+ if (data_type === BinaryDataType.Uint8) {
44
+ ending = "unorm";
45
+ } else if (data_type === BinaryDataType.Float32) {
46
+ ending = "float";
47
+ } else if (data_type === BinaryDataType.Float16 || data_type === BinaryDataType.Uint16) {
48
+ // Half-float HDR data (e.g. octahedral environment maps). parse_rgbe stores f16 bit
49
+ // patterns in a Uint16Array, so the same half-float payload can be classified as either
50
+ // Float16 or Uint16 depending on the runtime — both map to the 16-bit float format.
51
+ ending = "float";
52
+ } else {
53
+ throw new Error(`Unsupported data type '${data_type}'`);
54
+ }
55
+ } else if (color_space === ColorSpace.None) {
56
+ if (
57
+ data_type === BinaryDataType.Uint8
58
+ || data_type === BinaryDataType.Uint16
59
+ || data_type === BinaryDataType.Uint32
60
+ ) {
61
+ if (normalized) {
62
+ ending = "unorm";
63
+ } else {
64
+ ending = "uint";
65
+ }
66
+
67
+ } else if (
68
+ data_type === BinaryDataType.Float32
69
+ || data_type === BinaryDataType.Float16
70
+ ) {
71
+ ending = "float";
72
+ } else {
73
+ throw new Error(`Unsupported data type '${data_type}'`);
74
+ }
75
+ } else if (color_space === ColorSpace.SRGB) {
76
+ if (data_type === BinaryDataType.Uint8) {
77
+ ending = "unorm-srgb";
78
+ } else {
79
+ throw new Error(`Unsupported data type '${data_type}'`);
80
+ }
81
+ } else {
82
+ throw new Error(`Unsupported color space '${color_space}'`);
83
+ }
84
+
85
+ return `${prefix}${bit_size}${ending}`;
86
+ }
87
+
88
+
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The {@link GPUTextureFormat} a {@link ShadeImage}'s texels are in.
3
+ *
4
+ * A free function rather than a getter on the image, because {@link ShadeImage} describes *data* —
5
+ * a channel count, a data type, a colour space, some bytes — and what WebGPU calls that arrangement
6
+ * is not the data's business. The image stays a model the encoder, the container readers and the
7
+ * asset pipeline can hold without any of them importing a graphics API.
8
+ *
9
+ * What this replaces is the same inference run at *upload* time, inside the descriptor builder. The
10
+ * move matters more than the mechanism: a format worked out by inspecting pixels is a question
11
+ * block-compressed texels cannot answer, so a {@link ShadeTexelData} states its format instead and
12
+ * this function simply reports it. That is what lets both kinds share one path.
13
+ *
14
+ * **Not cached anywhere.** `color_space` is assigned *after* construction in nine places
15
+ * (`gltf_create_material` among them), so a format captured once would leave every glTF albedo map
16
+ * on `rgba8unorm` and silently drop its sRGB decode.
17
+ *
18
+ * @param {ShadeImage} image
19
+ * @returns {GPUTextureFormat}
20
+ * @throws {Error} if the image has no source, or one this does not recognise — a format guessed for
21
+ * texels nobody can describe would put the wrong number of bytes on both sides of the upload
22
+ */
23
+ export function texture_format_from_shade_image(image: ShadeImage): GPUTextureFormat;
24
+ //# sourceMappingURL=texture_format_from_shade_image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"texture_format_from_shade_image.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/texture/format/texture_format_from_shade_image.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qFA2CC"}