@flighthq/render-wgpu 0.5.1-next.973.788d3d7 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (407) hide show
  1. package/README.md +2 -2
  2. package/dist/.tsbuildinfo.compressed-texture-decoder-contract +1 -0
  3. package/dist/.tsbuildinfo.contract +1 -0
  4. package/dist/.tsbuildinfo.runtime +1 -0
  5. package/dist/compressed-texture-decoder-contract/WgpuCompressedTextureDecoder.d.ts +3 -0
  6. package/dist/compressed-texture-decoder-contract/WgpuCompressedTextureDecoder.d.ts.map +1 -0
  7. package/dist/compressed-texture-decoder-contract/WgpuCompressedTextureDecoder.js +2 -0
  8. package/dist/compressed-texture-decoder-contract/WgpuCompressedTextureDecoder.js.map +1 -0
  9. package/dist/compressed-texture-decoder-contract/compressedTextureDecoderContract.d.ts +2 -0
  10. package/dist/compressed-texture-decoder-contract/compressedTextureDecoderContract.d.ts.map +1 -0
  11. package/dist/compressed-texture-decoder-contract/compressedTextureDecoderContract.js +2 -0
  12. package/dist/compressed-texture-decoder-contract/compressedTextureDecoderContract.js.map +1 -0
  13. package/dist/contract.d.ts +32 -34
  14. package/dist/contract.d.ts.map +1 -1
  15. package/dist/contract.js +32 -34
  16. package/dist/contract.js.map +1 -1
  17. package/dist/contract.render-wgpu-types.d.ts +55 -0
  18. package/dist/contract.render-wgpu-types.d.ts.map +1 -0
  19. package/dist/contract.render-wgpu-types.js +5 -0
  20. package/dist/contract.render-wgpu-types.js.map +1 -0
  21. package/dist/enableWgpuTextureResolverGuards.d.ts +3 -2
  22. package/dist/enableWgpuTextureResolverGuards.d.ts.map +1 -1
  23. package/dist/enableWgpuTextureResolverGuards.js +12 -9
  24. package/dist/enableWgpuTextureResolverGuards.js.map +1 -1
  25. package/dist/explainWgpuTextureResolution.d.ts +2 -1
  26. package/dist/explainWgpuTextureResolution.d.ts.map +1 -1
  27. package/dist/explainWgpuTextureResolution.js +2 -5
  28. package/dist/explainWgpuTextureResolution.js.map +1 -1
  29. package/dist/explainWgpuUniformEndianness.d.ts +3 -0
  30. package/dist/explainWgpuUniformEndianness.d.ts.map +1 -0
  31. package/dist/explainWgpuUniformEndianness.js +25 -0
  32. package/dist/explainWgpuUniformEndianness.js.map +1 -0
  33. package/dist/index.d.ts +20 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +20 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/types/Host.d.ts +5 -0
  38. package/dist/types/Host.d.ts.map +1 -0
  39. package/dist/types/Host.js +2 -0
  40. package/dist/types/Host.js.map +1 -0
  41. package/dist/types/WgpuAdapter.d.ts +14 -0
  42. package/dist/types/WgpuAdapter.d.ts.map +1 -0
  43. package/dist/types/WgpuAdapter.js +2 -0
  44. package/dist/types/WgpuAdapter.js.map +1 -0
  45. package/dist/types/WgpuAdapterCapabilities.d.ts +7 -0
  46. package/dist/types/WgpuAdapterCapabilities.d.ts.map +1 -0
  47. package/dist/types/WgpuAdapterCapabilities.js +2 -0
  48. package/dist/types/WgpuAdapterCapabilities.js.map +1 -0
  49. package/dist/types/WgpuBindGroup.d.ts +23 -0
  50. package/dist/types/WgpuBindGroup.d.ts.map +1 -0
  51. package/dist/types/WgpuBindGroup.js +2 -0
  52. package/dist/types/WgpuBindGroup.js.map +1 -0
  53. package/dist/types/WgpuBindGroupLayout.d.ts +45 -0
  54. package/dist/types/WgpuBindGroupLayout.d.ts.map +1 -0
  55. package/dist/types/WgpuBindGroupLayout.js +7 -0
  56. package/dist/types/WgpuBindGroupLayout.js.map +1 -0
  57. package/dist/types/WgpuBuffer.d.ts +34 -0
  58. package/dist/types/WgpuBuffer.d.ts.map +1 -0
  59. package/dist/types/WgpuBuffer.js +19 -0
  60. package/dist/types/WgpuBuffer.js.map +1 -0
  61. package/dist/types/WgpuCanvasContext.d.ts +17 -0
  62. package/dist/types/WgpuCanvasContext.d.ts.map +1 -0
  63. package/dist/types/WgpuCanvasContext.js +2 -0
  64. package/dist/types/WgpuCanvasContext.js.map +1 -0
  65. package/dist/types/WgpuColorAdjustmentMaterialFeature.d.ts +14 -0
  66. package/dist/types/WgpuColorAdjustmentMaterialFeature.d.ts.map +1 -0
  67. package/dist/types/WgpuColorAdjustmentMaterialFeature.js +2 -0
  68. package/dist/types/WgpuColorAdjustmentMaterialFeature.js.map +1 -0
  69. package/dist/types/WgpuCommandBuffer.d.ts +5 -0
  70. package/dist/types/WgpuCommandBuffer.d.ts.map +1 -0
  71. package/dist/types/WgpuCommandBuffer.js +2 -0
  72. package/dist/types/WgpuCommandBuffer.js.map +1 -0
  73. package/dist/types/WgpuCommandEncoder.d.ts +12 -0
  74. package/dist/types/WgpuCommandEncoder.d.ts.map +1 -0
  75. package/dist/types/WgpuCommandEncoder.js +2 -0
  76. package/dist/types/WgpuCommandEncoder.js.map +1 -0
  77. package/dist/types/WgpuCompressedTextureSupport.d.ts +6 -0
  78. package/dist/types/WgpuCompressedTextureSupport.d.ts.map +1 -0
  79. package/dist/types/WgpuCompressedTextureSupport.js +2 -0
  80. package/dist/types/WgpuCompressedTextureSupport.js.map +1 -0
  81. package/dist/types/WgpuCompressedTextureUploader.d.ts +6 -0
  82. package/dist/types/WgpuCompressedTextureUploader.d.ts.map +1 -0
  83. package/dist/types/WgpuCompressedTextureUploader.js +2 -0
  84. package/dist/types/WgpuCompressedTextureUploader.js.map +1 -0
  85. package/dist/types/WgpuCustomMaterialShaderSource.d.ts +2 -0
  86. package/dist/types/WgpuCustomMaterialShaderSource.d.ts.map +1 -0
  87. package/dist/types/WgpuCustomMaterialShaderSource.js +2 -0
  88. package/dist/types/WgpuCustomMaterialShaderSource.js.map +1 -0
  89. package/dist/types/WgpuDevice.d.ts +76 -0
  90. package/dist/types/WgpuDevice.d.ts.map +1 -0
  91. package/dist/types/WgpuDevice.js +2 -0
  92. package/dist/types/WgpuDevice.js.map +1 -0
  93. package/dist/types/WgpuDeviceRuntime.d.ts +53 -0
  94. package/dist/types/WgpuDeviceRuntime.d.ts.map +1 -0
  95. package/dist/types/WgpuDeviceRuntime.js +2 -0
  96. package/dist/types/WgpuDeviceRuntime.js.map +1 -0
  97. package/dist/types/WgpuDeviceSignals.d.ts +6 -0
  98. package/dist/types/WgpuDeviceSignals.d.ts.map +1 -0
  99. package/dist/types/WgpuDeviceSignals.js +2 -0
  100. package/dist/types/WgpuDeviceSignals.js.map +1 -0
  101. package/dist/types/WgpuDeviceState.d.ts +7 -0
  102. package/dist/types/WgpuDeviceState.d.ts.map +1 -0
  103. package/dist/types/WgpuDeviceState.js +2 -0
  104. package/dist/types/WgpuDeviceState.js.map +1 -0
  105. package/dist/types/WgpuEffectState.d.ts +19 -0
  106. package/dist/types/WgpuEffectState.d.ts.map +1 -0
  107. package/dist/types/WgpuEffectState.js +2 -0
  108. package/dist/types/WgpuEffectState.js.map +1 -0
  109. package/dist/types/WgpuExternalImageSource.d.ts +18 -0
  110. package/dist/types/WgpuExternalImageSource.d.ts.map +1 -0
  111. package/dist/types/WgpuExternalImageSource.js +2 -0
  112. package/dist/types/WgpuExternalImageSource.js.map +1 -0
  113. package/dist/types/WgpuFullscreenPipeline.d.ts +14 -0
  114. package/dist/types/WgpuFullscreenPipeline.d.ts.map +1 -0
  115. package/dist/types/WgpuFullscreenPipeline.js +2 -0
  116. package/dist/types/WgpuFullscreenPipeline.js.map +1 -0
  117. package/dist/types/WgpuGpu.d.ts +7 -0
  118. package/dist/types/WgpuGpu.d.ts.map +1 -0
  119. package/dist/types/WgpuGpu.js +2 -0
  120. package/dist/types/WgpuGpu.js.map +1 -0
  121. package/dist/types/WgpuHost.d.ts +44 -0
  122. package/dist/types/WgpuHost.d.ts.map +1 -0
  123. package/dist/types/WgpuHost.js +2 -0
  124. package/dist/types/WgpuHost.js.map +1 -0
  125. package/dist/types/WgpuMeshMaterialRenderer.d.ts +11 -0
  126. package/dist/types/WgpuMeshMaterialRenderer.d.ts.map +1 -0
  127. package/dist/types/WgpuMeshMaterialRenderer.js +2 -0
  128. package/dist/types/WgpuMeshMaterialRenderer.js.map +1 -0
  129. package/dist/types/WgpuModifierSnippet.d.ts +16 -0
  130. package/dist/types/WgpuModifierSnippet.d.ts.map +1 -0
  131. package/dist/types/WgpuModifierSnippet.js +2 -0
  132. package/dist/types/WgpuModifierSnippet.js.map +1 -0
  133. package/dist/types/WgpuParticleResources.d.ts +12 -0
  134. package/dist/types/WgpuParticleResources.d.ts.map +1 -0
  135. package/dist/types/WgpuParticleResources.js +2 -0
  136. package/dist/types/WgpuParticleResources.js.map +1 -0
  137. package/dist/types/WgpuPipelineLayout.d.ts +8 -0
  138. package/dist/types/WgpuPipelineLayout.d.ts.map +1 -0
  139. package/dist/types/WgpuPipelineLayout.js +2 -0
  140. package/dist/types/WgpuPipelineLayout.js.map +1 -0
  141. package/dist/types/WgpuQuadBatchResources.d.ts +12 -0
  142. package/dist/types/WgpuQuadBatchResources.d.ts.map +1 -0
  143. package/dist/types/WgpuQuadBatchResources.js +2 -0
  144. package/dist/types/WgpuQuadBatchResources.js.map +1 -0
  145. package/dist/types/WgpuQuadMaterialRenderer.d.ts +9 -0
  146. package/dist/types/WgpuQuadMaterialRenderer.d.ts.map +1 -0
  147. package/dist/types/WgpuQuadMaterialRenderer.js +2 -0
  148. package/dist/types/WgpuQuadMaterialRenderer.js.map +1 -0
  149. package/dist/types/WgpuQueue.d.ts +12 -0
  150. package/dist/types/WgpuQueue.d.ts.map +1 -0
  151. package/dist/types/WgpuQueue.js +2 -0
  152. package/dist/types/WgpuQueue.js.map +1 -0
  153. package/dist/types/WgpuRenderOptions.d.ts +14 -0
  154. package/dist/types/WgpuRenderOptions.d.ts.map +1 -0
  155. package/dist/types/WgpuRenderOptions.js +2 -0
  156. package/dist/types/WgpuRenderOptions.js.map +1 -0
  157. package/dist/types/WgpuRenderPass.d.ts +31 -0
  158. package/dist/types/WgpuRenderPass.d.ts.map +1 -0
  159. package/dist/types/WgpuRenderPass.js +2 -0
  160. package/dist/types/WgpuRenderPass.js.map +1 -0
  161. package/dist/types/WgpuRenderPassEncoder.d.ts +52 -0
  162. package/dist/types/WgpuRenderPassEncoder.d.ts.map +1 -0
  163. package/dist/types/WgpuRenderPassEncoder.js +2 -0
  164. package/dist/types/WgpuRenderPassEncoder.js.map +1 -0
  165. package/dist/types/WgpuRenderPipeline.d.ts +96 -0
  166. package/dist/types/WgpuRenderPipeline.d.ts.map +1 -0
  167. package/dist/types/WgpuRenderPipeline.js +9 -0
  168. package/dist/types/WgpuRenderPipeline.js.map +1 -0
  169. package/dist/types/WgpuRenderState.d.ts +249 -0
  170. package/dist/types/WgpuRenderState.d.ts.map +1 -0
  171. package/dist/types/WgpuRenderState.js +2 -0
  172. package/dist/types/WgpuRenderState.js.map +1 -0
  173. package/dist/types/WgpuRenderStateOptions.d.ts +31 -0
  174. package/dist/types/WgpuRenderStateOptions.d.ts.map +1 -0
  175. package/dist/types/WgpuRenderStateOptions.js +2 -0
  176. package/dist/types/WgpuRenderStateOptions.js.map +1 -0
  177. package/dist/types/WgpuRenderTarget.d.ts +62 -0
  178. package/dist/types/WgpuRenderTarget.d.ts.map +1 -0
  179. package/dist/types/WgpuRenderTarget.js +2 -0
  180. package/dist/types/WgpuRenderTarget.js.map +1 -0
  181. package/dist/types/WgpuRenderTexture.d.ts +25 -0
  182. package/dist/types/WgpuRenderTexture.d.ts.map +1 -0
  183. package/dist/types/WgpuRenderTexture.js +2 -0
  184. package/dist/types/WgpuRenderTexture.js.map +1 -0
  185. package/dist/types/WgpuSampler.d.ts +19 -0
  186. package/dist/types/WgpuSampler.d.ts.map +1 -0
  187. package/dist/types/WgpuSampler.js +2 -0
  188. package/dist/types/WgpuSampler.js.map +1 -0
  189. package/dist/types/WgpuScene3DRuntime.d.ts +6 -0
  190. package/dist/types/WgpuScene3DRuntime.d.ts.map +1 -0
  191. package/dist/types/WgpuScene3DRuntime.js +2 -0
  192. package/dist/types/WgpuScene3DRuntime.js.map +1 -0
  193. package/dist/types/WgpuShaderModule.d.ts +6 -0
  194. package/dist/types/WgpuShaderModule.d.ts.map +1 -0
  195. package/dist/types/WgpuShaderModule.js +2 -0
  196. package/dist/types/WgpuShaderModule.js.map +1 -0
  197. package/dist/types/WgpuShapeMesh.d.ts +7 -0
  198. package/dist/types/WgpuShapeMesh.d.ts.map +1 -0
  199. package/dist/types/WgpuShapeMesh.js +2 -0
  200. package/dist/types/WgpuShapeMesh.js.map +1 -0
  201. package/dist/types/WgpuSkinningAdapter.d.ts +18 -0
  202. package/dist/types/WgpuSkinningAdapter.d.ts.map +1 -0
  203. package/dist/types/WgpuSkinningAdapter.js +2 -0
  204. package/dist/types/WgpuSkinningAdapter.js.map +1 -0
  205. package/dist/types/WgpuSurface.d.ts +5 -0
  206. package/dist/types/WgpuSurface.d.ts.map +1 -0
  207. package/dist/types/WgpuSurface.js +2 -0
  208. package/dist/types/WgpuSurface.js.map +1 -0
  209. package/dist/types/WgpuTexture.d.ts +58 -0
  210. package/dist/types/WgpuTexture.d.ts.map +1 -0
  211. package/dist/types/WgpuTexture.js +9 -0
  212. package/dist/types/WgpuTexture.js.map +1 -0
  213. package/dist/types/WgpuTextureFormat.d.ts +2 -0
  214. package/dist/types/WgpuTextureFormat.d.ts.map +1 -0
  215. package/dist/types/WgpuTextureFormat.js +2 -0
  216. package/dist/types/WgpuTextureFormat.js.map +1 -0
  217. package/dist/types/WgpuTextureResolver.d.ts +4 -0
  218. package/dist/types/WgpuTextureResolver.d.ts.map +1 -0
  219. package/dist/types/WgpuTextureResolver.js +2 -0
  220. package/dist/types/WgpuTextureResolver.js.map +1 -0
  221. package/dist/types/WgpuTextureView.d.ts +16 -0
  222. package/dist/types/WgpuTextureView.d.ts.map +1 -0
  223. package/dist/types/WgpuTextureView.js +2 -0
  224. package/dist/types/WgpuTextureView.js.map +1 -0
  225. package/dist/types/WgpuUniformEndianness.d.ts +7 -0
  226. package/dist/types/WgpuUniformEndianness.d.ts.map +1 -0
  227. package/dist/types/WgpuUniformEndianness.js +2 -0
  228. package/dist/types/WgpuUniformEndianness.js.map +1 -0
  229. package/dist/types/WgpuVelocityWriter.d.ts +11 -0
  230. package/dist/types/WgpuVelocityWriter.d.ts.map +1 -0
  231. package/dist/types/WgpuVelocityWriter.js +2 -0
  232. package/dist/types/WgpuVelocityWriter.js.map +1 -0
  233. package/dist/wgpuAdapterCapabilities.d.ts +2 -2
  234. package/dist/wgpuAdapterCapabilities.d.ts.map +1 -1
  235. package/dist/wgpuAdapterCapabilities.js.map +1 -1
  236. package/dist/wgpuCompressedTexture.d.ts +7 -5
  237. package/dist/wgpuCompressedTexture.d.ts.map +1 -1
  238. package/dist/wgpuCompressedTexture.js +10 -18
  239. package/dist/wgpuCompressedTexture.js.map +1 -1
  240. package/dist/wgpuDeviceLoss.d.ts +2 -2
  241. package/dist/wgpuDeviceLoss.d.ts.map +1 -1
  242. package/dist/wgpuDeviceLoss.js +1 -1
  243. package/dist/wgpuDeviceLoss.js.map +1 -1
  244. package/dist/wgpuDraw.d.ts +11 -5
  245. package/dist/wgpuDraw.d.ts.map +1 -1
  246. package/dist/wgpuDraw.js +21 -20
  247. package/dist/wgpuDraw.js.map +1 -1
  248. package/dist/wgpuExternalImageSource.d.ts +3 -2
  249. package/dist/wgpuExternalImageSource.d.ts.map +1 -1
  250. package/dist/wgpuExternalImageSource.js.map +1 -1
  251. package/dist/wgpuExternalTexture.d.ts +7 -3
  252. package/dist/wgpuExternalTexture.d.ts.map +1 -1
  253. package/dist/wgpuExternalTexture.js +5 -5
  254. package/dist/wgpuExternalTexture.js.map +1 -1
  255. package/dist/wgpuFrame.d.ts +23 -0
  256. package/dist/wgpuFrame.d.ts.map +1 -0
  257. package/dist/{wgpuBackground.js → wgpuFrame.js} +67 -122
  258. package/dist/wgpuFrame.js.map +1 -0
  259. package/dist/wgpuFullscreenPass.d.ts +5 -4
  260. package/dist/wgpuFullscreenPass.d.ts.map +1 -1
  261. package/dist/wgpuFullscreenPass.js +22 -8
  262. package/dist/wgpuFullscreenPass.js.map +1 -1
  263. package/dist/wgpuHost.d.ts +4 -7
  264. package/dist/wgpuHost.d.ts.map +1 -1
  265. package/dist/wgpuHost.js +81 -70
  266. package/dist/wgpuHost.js.map +1 -1
  267. package/dist/wgpuMipmap.d.ts +2 -2
  268. package/dist/wgpuMipmap.d.ts.map +1 -1
  269. package/dist/wgpuMipmap.js +4 -3
  270. package/dist/wgpuMipmap.js.map +1 -1
  271. package/dist/wgpuQuadMaterialRegistry.d.ts +7 -0
  272. package/dist/wgpuQuadMaterialRegistry.d.ts.map +1 -0
  273. package/dist/wgpuQuadMaterialRegistry.js +33 -0
  274. package/dist/wgpuQuadMaterialRegistry.js.map +1 -0
  275. package/dist/wgpuRenderPass.d.ts +9 -0
  276. package/dist/wgpuRenderPass.d.ts.map +1 -0
  277. package/dist/wgpuRenderPass.js +210 -0
  278. package/dist/wgpuRenderPass.js.map +1 -0
  279. package/dist/wgpuRenderState.d.ts +16 -12
  280. package/dist/wgpuRenderState.d.ts.map +1 -1
  281. package/dist/wgpuRenderState.js +104 -149
  282. package/dist/wgpuRenderState.js.map +1 -1
  283. package/dist/wgpuRenderTarget.d.ts +13 -29
  284. package/dist/wgpuRenderTarget.d.ts.map +1 -1
  285. package/dist/wgpuRenderTarget.js +20 -253
  286. package/dist/wgpuRenderTarget.js.map +1 -1
  287. package/dist/wgpuRenderTargetPool.d.ts +8 -6
  288. package/dist/wgpuRenderTargetPool.d.ts.map +1 -1
  289. package/dist/wgpuRenderTargetPool.js +9 -9
  290. package/dist/wgpuRenderTargetPool.js.map +1 -1
  291. package/dist/wgpuRenderTexture.d.ts +7 -4
  292. package/dist/wgpuRenderTexture.d.ts.map +1 -1
  293. package/dist/wgpuRenderTexture.js +15 -17
  294. package/dist/wgpuRenderTexture.js.map +1 -1
  295. package/dist/wgpuRenderTexturePool.d.ts +3 -1
  296. package/dist/wgpuRenderTexturePool.d.ts.map +1 -1
  297. package/dist/wgpuRenderTexturePool.js +5 -7
  298. package/dist/wgpuRenderTexturePool.js.map +1 -1
  299. package/dist/wgpuScissor.d.ts +3 -3
  300. package/dist/wgpuScissor.d.ts.map +1 -1
  301. package/dist/wgpuScissor.js +8 -5
  302. package/dist/wgpuScissor.js.map +1 -1
  303. package/dist/wgpuScreenAntialias.d.ts +3 -0
  304. package/dist/wgpuScreenAntialias.d.ts.map +1 -0
  305. package/dist/wgpuScreenAntialias.js +120 -0
  306. package/dist/wgpuScreenAntialias.js.map +1 -0
  307. package/dist/wgpuScreenCapture.d.ts +6 -0
  308. package/dist/wgpuScreenCapture.d.ts.map +1 -0
  309. package/dist/wgpuScreenCapture.js +138 -0
  310. package/dist/wgpuScreenCapture.js.map +1 -0
  311. package/dist/wgpuScreenRenderTarget.d.ts +11 -0
  312. package/dist/wgpuScreenRenderTarget.d.ts.map +1 -0
  313. package/dist/wgpuScreenRenderTarget.js +121 -0
  314. package/dist/wgpuScreenRenderTarget.js.map +1 -0
  315. package/dist/wgpuShader.d.ts +11 -8
  316. package/dist/wgpuShader.d.ts.map +1 -1
  317. package/dist/wgpuShader.js +11 -10
  318. package/dist/wgpuShader.js.map +1 -1
  319. package/dist/wgpuShaderBinding.d.ts +3 -1
  320. package/dist/wgpuShaderBinding.d.ts.map +1 -1
  321. package/dist/wgpuShaderBinding.js +1 -1
  322. package/dist/wgpuShaderBinding.js.map +1 -1
  323. package/dist/wgpuShaderRegistry.d.ts +1 -1
  324. package/dist/wgpuShaderRegistry.d.ts.map +1 -1
  325. package/dist/wgpuShaderRegistry.js +1 -1
  326. package/dist/wgpuShaderRegistry.js.map +1 -1
  327. package/dist/wgpuTestHelper.d.ts +11 -2
  328. package/dist/wgpuTestHelper.d.ts.map +1 -1
  329. package/dist/wgpuTestHelper.js +50 -38
  330. package/dist/wgpuTestHelper.js.map +1 -1
  331. package/dist/wgpuTextureRenderTarget.d.ts +22 -0
  332. package/dist/wgpuTextureRenderTarget.d.ts.map +1 -0
  333. package/dist/wgpuTextureRenderTarget.js +123 -0
  334. package/dist/wgpuTextureRenderTarget.js.map +1 -0
  335. package/dist/wgpuTextureResolver.d.ts +5 -1
  336. package/dist/wgpuTextureResolver.d.ts.map +1 -1
  337. package/dist/wgpuTextureResolver.js +13 -12
  338. package/dist/wgpuTextureResolver.js.map +1 -1
  339. package/dist/wgpuTextureUpload.d.ts +5 -4
  340. package/dist/wgpuTextureUpload.d.ts.map +1 -1
  341. package/dist/wgpuTextureUpload.js +1 -1
  342. package/dist/wgpuTextureUpload.js.map +1 -1
  343. package/package.json +33 -13
  344. package/src/enableWgpuTextureResolverGuards.test.ts +40 -19
  345. package/src/explainWgpuTextureResolution.test.ts +6 -6
  346. package/src/explainWgpuUniformEndianness.test.ts +11 -0
  347. package/src/types/WgpuBindGroupLayout.test.ts +9 -0
  348. package/src/types/WgpuBuffer.test.ts +26 -0
  349. package/src/types/WgpuGpu.test.ts +56 -0
  350. package/src/types/WgpuRenderPipeline.test.ts +12 -0
  351. package/src/types/WgpuTexture.test.ts +15 -0
  352. package/src/wgpuAdapterCapabilities.test.ts +5 -4
  353. package/src/wgpuCompressedTexture.test.ts +31 -37
  354. package/src/wgpuDeviceLoss.test.ts +31 -24
  355. package/src/wgpuDraw.test.ts +21 -24
  356. package/src/wgpuExternalImageSource.test.ts +12 -11
  357. package/src/wgpuExternalTexture.test.ts +7 -6
  358. package/src/{wgpuBackground.test.ts → wgpuFrame.test.ts} +47 -29
  359. package/src/wgpuFullscreenPass.test.ts +8 -8
  360. package/src/wgpuHost.test.ts +57 -186
  361. package/src/wgpuMipmap.test.ts +15 -9
  362. package/src/wgpuQuadMaterialRegistry.test.ts +132 -0
  363. package/src/wgpuRenderPass.test.ts +239 -0
  364. package/src/wgpuRenderState.test.ts +215 -550
  365. package/src/wgpuRenderTarget.test.ts +44 -220
  366. package/src/wgpuRenderTargetPool.test.ts +23 -23
  367. package/src/wgpuRenderTexture.test.ts +21 -18
  368. package/src/wgpuRenderTexturePool.test.ts +3 -3
  369. package/src/wgpuScissor.test.ts +50 -19
  370. package/src/wgpuScreenAntialias.test.ts +65 -0
  371. package/src/wgpuScreenCapture.test.ts +165 -0
  372. package/src/wgpuScreenRenderTarget.test.ts +172 -0
  373. package/src/wgpuShader.test.ts +12 -11
  374. package/src/wgpuShaderBinding.test.ts +4 -4
  375. package/src/wgpuShaderRegistry.test.ts +4 -5
  376. package/src/wgpuTestHelper.test.ts +8 -7
  377. package/src/wgpuTextureRenderTarget.test.ts +129 -0
  378. package/src/wgpuTextureResolver.test.ts +25 -14
  379. package/src/wgpuTextureUpload.test.ts +15 -10
  380. package/dist/wgpuAntialias.d.ts +0 -14
  381. package/dist/wgpuAntialias.d.ts.map +0 -1
  382. package/dist/wgpuAntialias.js +0 -155
  383. package/dist/wgpuAntialias.js.map +0 -1
  384. package/dist/wgpuBackground.d.ts +0 -20
  385. package/dist/wgpuBackground.d.ts.map +0 -1
  386. package/dist/wgpuBackground.js.map +0 -1
  387. package/dist/wgpuElement.d.ts +0 -7
  388. package/dist/wgpuElement.d.ts.map +0 -1
  389. package/dist/wgpuElement.js +0 -20
  390. package/dist/wgpuElement.js.map +0 -1
  391. package/dist/wgpuMaterialRegistry.d.ts +0 -5
  392. package/dist/wgpuMaterialRegistry.d.ts.map +0 -1
  393. package/dist/wgpuMaterialRegistry.js +0 -32
  394. package/dist/wgpuMaterialRegistry.js.map +0 -1
  395. package/dist/wgpuPipeline.d.ts +0 -6
  396. package/dist/wgpuPipeline.d.ts.map +0 -1
  397. package/dist/wgpuPipeline.js +0 -33
  398. package/dist/wgpuPipeline.js.map +0 -1
  399. package/dist/wgpuSurface.d.ts +0 -6
  400. package/dist/wgpuSurface.d.ts.map +0 -1
  401. package/dist/wgpuSurface.js +0 -155
  402. package/dist/wgpuSurface.js.map +0 -1
  403. package/src/wgpuAntialias.test.ts +0 -239
  404. package/src/wgpuElement.test.ts +0 -145
  405. package/src/wgpuMaterialRegistry.test.ts +0 -100
  406. package/src/wgpuPipeline.test.ts +0 -62
  407. package/src/wgpuSurface.test.ts +0 -141
@@ -1,48 +1,42 @@
1
- import { allocateEntity, finishEntity } from '@flighthq/entity/contract';
2
- import {
3
- createKeyedTable,
4
- getRegistryTableEntry,
5
- hasRegistryTableEntry,
6
- withRegistryTableEntry,
7
- } from '@flighthq/registry/contract';
1
+ import { allocateEntity } from '@flighthq/entity/contract';
2
+ import type { Entity } from '@flighthq/entity/contract';
3
+ import { EntityRuntimeKey } from '@flighthq/entity/contract';
4
+ import { withKindMapEntry } from '@flighthq/registry/contract';
8
5
  import {
9
6
  enableColorAdjustmentGuards,
10
7
  enableColorAdjustments,
11
8
  getColorAdjustmentUnsupportedGuard,
12
9
  getRenderStateRuntime,
13
10
  prepareScene2DRender,
14
- registerRenderer,
11
+ registerNodeRenderer,
15
12
  } from '@flighthq/render/contract';
13
+ import type { EffectPaddingResolver, RenderRootGuard, RenderState } from '@flighthq/render/contract';
16
14
  import { createDisplayObject } from '@flighthq/scene2d/contract';
15
+
17
16
  import type {
18
- Entity,
19
- RenderEffectPaddingResolver,
20
- RenderRootGuard,
21
- RenderState,
17
+ WgpuBindGroupLayout,
22
18
  WgpuColorAdjustmentMaterialFeature,
23
19
  WgpuColorAdjustmentMaterialFeatureGuard,
20
+ WgpuDevice,
21
+ WgpuSampler,
22
+ WgpuShaderModule,
23
+ } from './contract.render-wgpu-types.ts';
24
+ import type {
24
25
  WgpuHostAcquisition,
25
- WgpuHostBackend,
26
- WgpuPipeline,
27
- WgpuPresentationRenderState,
28
- WgpuPresentationSurface,
26
+ HostWgpuCapability,
29
27
  WgpuRenderOptions,
30
28
  WgpuRenderState,
31
- } from '@flighthq/types/contract';
32
- import { EntityRuntimeKey, RegistryEntryState } from '@flighthq/types/contract';
33
-
34
- import { getWgpuSurfaceRenderExtent } from './wgpuAntialias';
35
- import { beginWgpuFrame, withWgpuFrameBorrow } from './wgpuBackground';
36
- import { registerWgpuCompressedTextureDecoder, registerWgpuCompressedTextureUpload } from './wgpuCompressedTexture';
37
- import { setWgpuHostBackend } from './wgpuHost';
38
- import { registerWgpuMaterialRenderer } from './wgpuMaterialRegistry';
39
- import { createEmptyWgpuRegistries, createWgpuPipeline } from './wgpuPipeline';
29
+ } from './contract.render-wgpu-types.ts';
30
+ import { registerWgpuCompressedTextureDecoder, registerWgpuCompressedTextureUpload } from './wgpuCompressedTexture.ts';
31
+ import { beginWgpuFrame, withWgpuFrameBorrow } from './wgpuFrame.ts';
32
+ import { createTestWgpuSurface, testWgpuHost } from './wgpuHost.ts';
33
+ import { registerWgpuQuadMaterialRenderer } from './wgpuQuadMaterialRegistry.ts';
40
34
  import {
41
- createWgpuAcquisitionFromCanvasElement,
35
+ buildWgpuRenderRegistries,
36
+ createWgpuAcquisition,
42
37
  createWgpuDeviceState,
43
38
  createWgpuOffscreenRenderState as createDeviceOnlyWgpuRenderState,
44
39
  createWgpuRenderState as createWgpuRenderStateWithPipeline,
45
- createWgpuRenderStateFromCanvasElement as createWgpuRenderStateFromCanvasElementWithPipeline,
46
40
  createWgpuRenderStateRuntime as createWgpuRenderStateRuntimeWithPipeline,
47
41
  destroyWgpuRenderState,
48
42
  getWgpuColorAdjustmentMaterialFeature,
@@ -60,9 +54,9 @@ import {
60
54
  registerWgpuRenderStateTeardown,
61
55
  releaseWgpuAcquisition,
62
56
  resolveWgpuApplyBlendMode,
63
- } from './wgpuRenderState';
64
- import { createWgpuRenderStateForTest, installWgpuMock } from './wgpuTestHelper';
65
- import { registerWgpuTextureResolver } from './wgpuTextureResolver';
57
+ } from './wgpuRenderState.ts';
58
+ import { createWgpuRenderStateForTest, installWgpuMock } from './wgpuTestHelper.ts';
59
+ import { registerWgpuTextureResolver } from './wgpuTextureResolver.ts';
66
60
 
67
61
  function expectEntitySlot(slot: object & { readonly [EntityRuntimeKey]?: unknown }, fields: object): void {
68
62
  const { [EntityRuntimeKey]: entityRuntime, ...slotFields } = slot;
@@ -75,35 +69,28 @@ beforeAll(() => {
75
69
  installWgpuMock();
76
70
  });
77
71
 
78
- const _testPipeline = createWgpuPipeline(createEmptyWgpuRegistries());
79
-
80
- function createWgpuRenderState(acquisition: Readonly<WgpuHostAcquisition>, options: Readonly<WgpuRenderOptions> = {}) {
81
- return createWgpuRenderStateWithPipeline(acquisition, _testPipeline, options);
82
- }
72
+ const _testPipeline = {};
73
+ const _webBackend = testWgpuHost;
83
74
 
84
- function createWgpuRenderStateFromCanvasElement(
85
- canvas: HTMLCanvasElement,
86
- options: Readonly<WgpuRenderOptions & { powerPreference?: GPUPowerPreference }> = {},
87
- ) {
88
- return createWgpuRenderStateFromCanvasElementWithPipeline(canvas, _testPipeline, options);
75
+ function createWgpuRenderState(device: WgpuDevice, options: Readonly<WgpuRenderOptions> = {}) {
76
+ return createWgpuRenderStateWithPipeline(device, { ..._testPipeline, ...options });
89
77
  }
90
78
 
91
79
  function createWgpuRenderStateRuntime(deviceState: ReturnType<typeof createWgpuDeviceState>) {
92
- return createWgpuRenderStateRuntimeWithPipeline(deviceState, _testPipeline);
80
+ return createWgpuRenderStateRuntimeWithPipeline(deviceState, { ..._testPipeline });
93
81
  }
94
82
 
95
- function entityHostBackend(fields: Omit<WgpuHostBackend, keyof Entity>): WgpuHostBackend {
83
+ function entityHostBackend(fields: Omit<HostWgpuCapability, keyof Entity>): HostWgpuCapability {
96
84
  return (() => {
97
- const out = allocateEntity<any>();
85
+ const out = allocateEntity<any>() as any;
98
86
  Object.assign(out, fields);
99
- return finishEntity(out);
87
+ return out;
100
88
  })();
101
89
  }
102
90
 
103
91
  function createWgpuOffscreenRenderState(source: WgpuRenderState): WgpuRenderState {
104
- const pipeline: WgpuPipeline = createWgpuPipeline(getWgpuRenderStateRuntime(source).registries);
105
- const state = createDeviceOnlyWgpuRenderState(source.deviceState, pipeline, {
106
- backgroundColor: source.backgroundColor,
92
+ const state = createDeviceOnlyWgpuRenderState(source.deviceState, {
93
+ ...getWgpuRenderStateRuntime(source).registries,
107
94
  format: source.format,
108
95
  imageSmoothingEnabled: source.allowSmoothing,
109
96
  pixelRatio: source.pixelRatio,
@@ -121,57 +108,84 @@ function createWgpuOffscreenRenderState(source: WgpuRenderState): WgpuRenderStat
121
108
  return state;
122
109
  }
123
110
 
124
- function getPaddingResolver(state: RenderState, kind: string): RenderEffectPaddingResolver | null {
111
+ function getPaddingResolver(state: RenderState, kind: string): EffectPaddingResolver | null {
125
112
  const table = getRenderStateRuntime(state).registries.effectPaddingResolvers;
126
- return table === undefined ? null : getRegistryTableEntry(table, kind);
113
+ return table === undefined ? null : (table.get(kind) ?? null);
127
114
  }
128
115
 
129
- function registerPaddingResolver(state: RenderState, kind: string, resolver: RenderEffectPaddingResolver): void {
116
+ function registerPaddingResolver(state: RenderState, kind: string, resolver: EffectPaddingResolver): void {
130
117
  const runtime = getRenderStateRuntime(state);
131
- runtime.registries.effectPaddingResolvers = withRegistryTableEntry(
132
- runtime.registries.effectPaddingResolvers ??
133
- createKeyedTable<RenderEffectPaddingResolver>('RenderEffectPaddingResolver', 'Zero'),
118
+ runtime.registries.effectPaddingResolvers = withKindMapEntry(
119
+ runtime.registries.effectPaddingResolvers ?? new Map(),
134
120
  kind,
135
121
  resolver,
136
122
  );
137
123
  }
138
124
 
139
- describe('createWgpuAcquisitionFromCanvasElement', () => {
125
+ describe('buildWgpuRenderRegistries', () => {
126
+ it('returns all required fields with default values', () => {
127
+ const registries = buildWgpuRenderRegistries({});
128
+ expect(registries.nodeRenderers).toBeInstanceOf(Map);
129
+ expect(registries.nodeRenderers.size).toBe(0);
130
+ expect(registries.materialRenderers).toBeInstanceOf(Map);
131
+ expect(registries.modifierSnippets).toBeInstanceOf(Map);
132
+ expect(registries.textureResolvers).toBeInstanceOf(Map);
133
+ expect(registries.strokeTessellator).toBeNull();
134
+ expect(registries.gpuSkinning).toBeNull();
135
+ });
136
+
137
+ it('clones provided registry maps and pass arrays into an isolated live aggregate', () => {
138
+ const nodeRenderers = new Map();
139
+ const passes: never[] = [];
140
+ const registries = buildWgpuRenderRegistries({ nodeRenderers, passes });
141
+ expect(registries.nodeRenderers).not.toBe(nodeRenderers);
142
+ expect(registries.passes).not.toBe(passes);
143
+
144
+ nodeRenderers.set('acme.Late', {});
145
+ expect(registries.nodeRenderers.has('acme.Late')).toBe(false);
146
+ });
147
+ });
148
+
149
+ describe('createWgpuAcquisition', () => {
140
150
  it('hands back handles the CALLER owns, so no state teardown can release them', async () => {
141
- const acquisition = await createWgpuAcquisitionFromCanvasElement(document.createElement('canvas'));
151
+ const acquisition = await createWgpuAcquisition(
152
+ _webBackend,
153
+ createTestWgpuSurface(document.createElement('canvas')),
154
+ );
142
155
 
143
156
  expect(acquisition).not.toBeNull();
144
157
  expect(acquisition!.ownership).toBe('caller');
145
158
  expect(acquisition!.surface).toBeDefined();
146
- releaseWgpuAcquisition(acquisition!);
159
+ releaseWgpuAcquisition(_webBackend, acquisition!);
147
160
  });
148
161
 
149
162
  // ★ NULL, NOT THROW. "This environment cannot give me WebGPU" is an expected outcome, not API misuse, so
150
163
  // it reports through the return value like every other expected failure in this SDK.
151
164
  it('returns null when the host cannot acquire, rather than rejecting', async () => {
152
- setWgpuHostBackend(
153
- entityHostBackend({
154
- acquire: vi.fn(async () => {
155
- throw new Error('no adapter');
156
- }),
157
- isSupported: vi.fn(() => false),
158
- release: vi.fn(),
165
+ const failingBackend = entityHostBackend({
166
+ acquire: vi.fn(async () => {
167
+ throw new Error('no adapter');
159
168
  }),
160
- );
169
+ attachSurface: vi.fn(() => null),
170
+ create: vi.fn(() => null),
171
+ isSupported: vi.fn(() => false),
172
+ release: vi.fn(),
173
+ });
161
174
 
162
- await expect(createWgpuAcquisitionFromCanvasElement(document.createElement('canvas'))).resolves.toBeNull();
163
- setWgpuHostBackend(null);
175
+ await expect(
176
+ createWgpuAcquisition(failingBackend, createTestWgpuSurface(document.createElement('canvas'))),
177
+ ).resolves.toBeNull();
164
178
  });
165
179
  });
166
180
 
167
181
  describe('createWgpuDeviceState', () => {
168
182
  it('allocates distinct owners for repeated calls with the same raw device', () => {
169
- const device = {} as GPUDevice;
183
+ const device = {} as WgpuDevice;
170
184
  expect(createWgpuDeviceState(device)).not.toBe(createWgpuDeviceState(device));
171
185
  });
172
186
 
173
187
  it('rejects a plain literal at the Entity boundary: EntityRuntimeKey is absent without allocateEntity', () => {
174
- const device = {} as GPUDevice;
188
+ const device = {} as WgpuDevice;
175
189
  const literal = { device };
176
190
  expect(EntityRuntimeKey in literal).toBe(false);
177
191
 
@@ -180,29 +194,21 @@ describe('createWgpuDeviceState', () => {
180
194
  });
181
195
 
182
196
  it('returns a state that shares the device tier across derived runtimes', () => {
183
- const device = {} as GPUDevice;
197
+ const device = {} as WgpuDevice;
184
198
  const deviceState = createWgpuDeviceState(device);
185
199
  const runtimeA = createWgpuRenderStateRuntime(deviceState);
186
200
  const runtimeB = createWgpuRenderStateRuntime(deviceState);
187
- runtimeA.context.standardMaterialModule = {} as GPUShaderModule;
201
+ runtimeA.context.standardMaterialModule = {} as WgpuShaderModule;
188
202
  expect(runtimeB.context.standardMaterialModule).toBe(runtimeA.context.standardMaterialModule);
189
203
  });
190
204
 
191
205
  it('represents device-native resources as absent before the first render state initializes them', () => {
192
- const runtime = getWgpuDeviceRuntime(createWgpuDeviceState({} as GPUDevice));
206
+ const runtime = getWgpuDeviceRuntime(createWgpuDeviceState({} as WgpuDevice));
193
207
  expect(runtime.resources).toBeNull();
194
208
  });
195
209
  });
196
210
 
197
211
  describe('createWgpuOffscreenRenderState', () => {
198
- it('rejects a device-only state at presentation boundaries', () => {
199
- const deviceOnlyState = null as WgpuRenderState | null;
200
- if (deviceOnlyState === null) return;
201
-
202
- // @ts-expect-error — a device-only state has no presentation surface or canvas context.
203
- beginWgpuFrame(deviceOnlyState);
204
- });
205
-
206
212
  it('resolves late screen blend-mode wiring explicitly until locally overridden', async () => {
207
213
  const screen = await createWgpuRenderStateForTest();
208
214
  const offscreen = createWgpuOffscreenRenderState(screen);
@@ -245,32 +251,17 @@ describe('createWgpuOffscreenRenderState', () => {
245
251
  };
246
252
  const colorAdjustmentFeatureGuard: WgpuColorAdjustmentMaterialFeatureGuard = vi.fn();
247
253
  const renderRootGuard: RenderRootGuard = vi.fn();
248
- registerRenderer(screen, 'acme.Node', renderer);
249
- registerWgpuMaterialRenderer(screen, 'acme.Material', materialRenderer);
254
+ registerNodeRenderer(screen, 'acme.Node', renderer);
255
+ registerWgpuQuadMaterialRenderer(screen, 'acme.Material', materialRenderer);
250
256
  registerWgpuTextureResolver(screen, 'acme.Texture', textureResolver);
251
257
  enableColorAdjustments(screen);
252
- enableColorAdjustmentGuards(screen);
258
+ enableColorAdjustmentGuards(screen, null);
253
259
  registerPaddingResolver(screen, 'acme.Effect', paddingResolver);
254
- getWgpuRenderStateRuntime(screen).registries.colorAdjustmentFeature = {
255
- entry: { state: RegistryEntryState.Bound, value: colorAdjustmentFeature },
256
- onMiss: 'Disabled',
257
- registry: 'WgpuColorAdjustmentFeature',
258
- shape: 'slot',
259
- };
260
- getWgpuRenderStateRuntime(screen).registries.colorAdjustmentFeatureGuard = {
261
- entry: { state: RegistryEntryState.Bound, value: colorAdjustmentFeatureGuard },
262
- onMiss: 'Disabled',
263
- registry: 'WgpuColorAdjustmentFeatureGuard',
264
- shape: 'slot',
265
- };
266
- getWgpuRenderStateRuntime(screen).registries.renderRootGuard = {
267
- entry: { state: RegistryEntryState.Bound, value: renderRootGuard },
268
- onMiss: 'Disabled',
269
- registry: 'RenderRootGuard',
270
- shape: 'slot',
271
- };
272
- getWgpuRenderStateRuntime(screen).registries.renderEffects = withRegistryTableEntry(
273
- getWgpuRenderStateRuntime(screen).registries.renderEffects,
260
+ getWgpuRenderStateRuntime(screen).registries.colorAdjustmentFeature = colorAdjustmentFeature;
261
+ getWgpuRenderStateRuntime(screen).registries.colorAdjustmentFeatureGuard = colorAdjustmentFeatureGuard;
262
+ getWgpuRenderStateRuntime(screen).registries.renderRootGuard = renderRootGuard;
263
+ getWgpuRenderStateRuntime(screen).registries.effects = withKindMapEntry(
264
+ getWgpuRenderStateRuntime(screen).registries.effects,
274
265
  'acme.Effect',
275
266
  { runner: effectRunner },
276
267
  );
@@ -284,7 +275,7 @@ describe('createWgpuOffscreenRenderState', () => {
284
275
  expect('surface' in offscreen).toBe(false);
285
276
  expect(offscreenRuntime.context).toBe(screenRuntime.context);
286
277
  expect(offscreenRuntime.uniformBuffer).not.toBe(screenRuntime.uniformBuffer);
287
- expect(offscreenRuntime.registries.renderers).toBe(screenRuntime.registries.renderers);
278
+ expect(offscreenRuntime.registries.nodeRenderers).not.toBe(screenRuntime.registries.nodeRenderers);
288
279
  expect(offscreenRuntime.registries).not.toBe(screenRuntime.registries);
289
280
  expect(offscreenRuntime.registries.colorAdjustmentFeature).toBe(screenRuntime.registries.colorAdjustmentFeature);
290
281
  expect(getWgpuColorAdjustmentMaterialFeature(offscreen)).toBe(colorAdjustmentFeature);
@@ -313,41 +304,32 @@ describe('createWgpuOffscreenRenderState', () => {
313
304
  expect(offscreenRuntime.registries.colorAdjustmentUnsupportedGuard).toBe(sharedUnsupportedGuard);
314
305
  expect(getColorAdjustmentUnsupportedGuard(offscreen)).not.toBeNull();
315
306
  expect(offscreenRuntime.registries.renderRootGuard).toBe(screenRuntime.registries.renderRootGuard);
316
- expect(offscreenRuntime.registries.renderRootGuard?.entry).toEqual({
317
- state: RegistryEntryState.Bound,
318
- value: renderRootGuard,
319
- });
307
+ expect(offscreenRuntime.registries.renderRootGuard).toEqual(renderRootGuard);
320
308
  const sharedRenderRootGuard = offscreenRuntime.registries.renderRootGuard;
321
309
  screenRuntime.registries.renderRootGuard = undefined;
322
310
  expect(screenRuntime.registries.renderRootGuard).toBeUndefined();
323
311
  expect(offscreenRuntime.registries.renderRootGuard).toBe(sharedRenderRootGuard);
324
- expect(
325
- getRegistryTableEntry(
326
- offscreenRuntime.registries.renderRootGuard!,
327
- offscreenRuntime.registries.renderRootGuard!.registry,
328
- ),
329
- ).toBe(renderRootGuard);
312
+ expect(offscreenRuntime.registries.renderRootGuard).toBe(renderRootGuard);
330
313
  expect(offscreenRuntime.registries.compressedTextureDecoder).toBe(
331
314
  screenRuntime.registries.compressedTextureDecoder,
332
315
  );
333
316
  expect(offscreenRuntime.registries.compressedTextureUpload).toBe(screenRuntime.registries.compressedTextureUpload);
334
- expect(offscreenRuntime.registries.customMaterialShaders).toBe(screenRuntime.registries.customMaterialShaders);
335
- expect(offscreenRuntime.registries.materialRenderers).toBe(screenRuntime.registries.materialRenderers);
336
- expect(offscreenRuntime.registries.meshMaterialRenderers).toBe(screenRuntime.registries.meshMaterialRenderers);
337
- expect(offscreenRuntime.registries.modifierSnippets).toBe(screenRuntime.registries.modifierSnippets);
338
- expect(offscreenRuntime.registries.modifierSnippetRevision).toBe(screenRuntime.registries.modifierSnippetRevision);
339
- expect(offscreenRuntime.registries.renderEffects).toBe(screenRuntime.registries.renderEffects);
317
+ expect(offscreenRuntime.registries.customMaterialShaders).not.toBe(screenRuntime.registries.customMaterialShaders);
318
+ expect(offscreenRuntime.registries.materialRenderers).not.toBe(screenRuntime.registries.materialRenderers);
319
+ expect(offscreenRuntime.registries.modifierSnippets).not.toBe(screenRuntime.registries.modifierSnippets);
320
+ expect(offscreenRuntime.modifierSnippetRevision).toBe(screenRuntime.modifierSnippetRevision);
321
+ expect(offscreenRuntime.registries.effects).not.toBe(screenRuntime.registries.effects);
340
322
  expect(offscreenRuntime.registries.shapeRasterizer).toBe(screenRuntime.registries.shapeRasterizer);
341
323
  expect(offscreenRuntime.registries.strokeTessellator).toBe(screenRuntime.registries.strokeTessellator);
342
- expect(offscreenRuntime.registries.textureResolvers).toBe(screenRuntime.registries.textureResolvers);
343
- expect(offscreenRuntime.registries.velocityWriters).toBe(screenRuntime.registries.velocityWriters);
344
- expect(offscreenRuntime.registries.effectPaddingResolvers).toBe(screenRuntime.registries.effectPaddingResolvers);
345
- expect(getRegistryTableEntry(offscreenRuntime.registries.renderers, 'acme.Node')).toBe(renderer);
346
- expect(getRegistryTableEntry(offscreenRuntime.registries.materialRenderers, 'acme.Material')).toBe(
347
- materialRenderer,
324
+ expect(offscreenRuntime.registries.textureResolvers).not.toBe(screenRuntime.registries.textureResolvers);
325
+ expect(offscreenRuntime.registries.velocityWriters).not.toBe(screenRuntime.registries.velocityWriters);
326
+ expect(offscreenRuntime.registries.effectPaddingResolvers).not.toBe(
327
+ screenRuntime.registries.effectPaddingResolvers,
348
328
  );
349
- expect(getRegistryTableEntry(offscreenRuntime.registries.textureResolvers, 'acme.Texture')).toBe(textureResolver);
350
- expect(getRegistryTableEntry(offscreenRuntime.registries.renderEffects, 'acme.Effect')).toEqual({
329
+ expect(offscreenRuntime.registries.nodeRenderers.get('acme.Node') ?? null).toBe(renderer);
330
+ expect(offscreenRuntime.registries.materialRenderers.get('acme.Material') ?? null).toBe(materialRenderer);
331
+ expect(offscreenRuntime.registries.textureResolvers.get('acme.Texture') ?? null).toBe(textureResolver);
332
+ expect(offscreenRuntime.registries.effects.get('acme.Effect') ?? null).toEqual({
351
333
  runner: effectRunner,
352
334
  });
353
335
  expect(getPaddingResolver(offscreen, 'acme.Effect')).toBe(paddingResolver);
@@ -357,7 +339,7 @@ describe('createWgpuOffscreenRenderState', () => {
357
339
  const screen = await createWgpuRenderStateForTest();
358
340
  const offscreen = createWgpuOffscreenRenderState(screen);
359
341
  const root = createDisplayObject();
360
- registerRenderer(offscreen, root.kind, { createData: () => finishEntity(allocateEntity()), submit: vi.fn() });
342
+ registerNodeRenderer(offscreen, root.kind, { createData: () => allocateEntity(), submit: vi.fn() });
361
343
  prepareScene2DRender(offscreen, root);
362
344
  beginWgpuFrame(screen);
363
345
 
@@ -382,7 +364,6 @@ describe('createWgpuOffscreenRenderState', () => {
382
364
 
383
365
  withWgpuFrameBorrow(screen, offscreen, () => {
384
366
  expect(offscreenRuntime.commandEncoder).toBe(encoder);
385
- expect(getWgpuSurfaceRenderExtent(offscreen)).toEqual({ height: 600, width: 800 });
386
367
  offscreenRuntime.uniformOffset = offscreenRuntime.uniformStride;
387
368
  });
388
369
 
@@ -403,7 +384,6 @@ describe('createWgpuOffscreenRenderState', () => {
403
384
  expect.anything(),
404
385
  );
405
386
  expect(submit).not.toHaveBeenCalled();
406
- expect(() => getWgpuSurfaceRenderExtent(offscreen)).toThrow(/outside an explicit frame borrow/);
407
387
  });
408
388
 
409
389
  it('submits a standalone borrow and restores both states when the callback throws', async () => {
@@ -421,7 +401,6 @@ describe('createWgpuOffscreenRenderState', () => {
421
401
  expect(submit).toHaveBeenCalledOnce();
422
402
  expect(getWgpuRenderStateRuntime(screen).commandEncoder).toBeNull();
423
403
  expect(getWgpuRenderStateRuntime(offscreen).commandEncoder).toBeNull();
424
- expect(() => getWgpuSurfaceRenderExtent(offscreen)).toThrow(/outside an explicit frame borrow/);
425
404
  });
426
405
 
427
406
  it('rejects nested borrowing by the same offscreen state', async () => {
@@ -437,8 +416,8 @@ describe('createWgpuOffscreenRenderState', () => {
437
416
  const screen = await createWgpuRenderStateForTest();
438
417
  const root = createDisplayObject();
439
418
  const destroyData = vi.fn();
440
- registerRenderer(screen, root.kind, {
441
- createData: () => finishEntity(allocateEntity()),
419
+ registerNodeRenderer(screen, root.kind, {
420
+ createData: () => allocateEntity(),
442
421
  destroyData,
443
422
  submit: vi.fn(),
444
423
  });
@@ -459,88 +438,36 @@ describe('createWgpuOffscreenRenderState', () => {
459
438
  const offscreen = createWgpuOffscreenRenderState(screen);
460
439
  const renderer = { createData: () => null, submit: vi.fn() };
461
440
  const paddingResolver = vi.fn(() => ({ bottom: 2, left: 2, right: 2, top: 2 }));
462
- registerRenderer(screen, 'acme.LateNode', renderer);
441
+ registerNodeRenderer(screen, 'acme.LateNode', renderer);
463
442
  registerPaddingResolver(screen, 'acme.LateEffect', paddingResolver);
464
443
 
465
- expect(hasRegistryTableEntry(getRenderStateRuntime(offscreen).registries.renderers, 'acme.LateNode')).toBe(false);
444
+ expect(getRenderStateRuntime(offscreen).registries.nodeRenderers.has('acme.LateNode')).toBe(false);
466
445
  expect(getPaddingResolver(offscreen, 'acme.LateEffect')).toBeNull();
467
446
 
468
447
  const refreshed = createWgpuOffscreenRenderState(screen);
469
- expect(getRegistryTableEntry(getRenderStateRuntime(refreshed).registries.renderers, 'acme.LateNode')).toBe(
470
- renderer,
471
- );
448
+ expect(getRenderStateRuntime(refreshed).registries.nodeRenderers.get('acme.LateNode') ?? null).toBe(renderer);
472
449
  expect(getPaddingResolver(refreshed, 'acme.LateEffect')).toBe(paddingResolver);
473
450
  });
474
451
  });
475
452
 
476
453
  describe('createWgpuRenderState', () => {
477
- it('keeps exact caller-owned handles usable through every shared-state teardown', async () => {
478
- const owner = await createWgpuRenderStateForTest();
479
- const canvas = document.createElement('canvas');
480
- const _acqOut = allocateEntity<WgpuHostAcquisition>();
481
- _acqOut.context = owner.context;
482
- _acqOut.device = owner.device;
483
- _acqOut.format = owner.format;
484
- _acqOut.ownership = 'caller' as const;
485
- _acqOut.surface = owner.surface;
486
- const acquisition = finishEntity(_acqOut);
487
- let contextUsable = true;
488
- let deviceUsable = true;
489
- const originalCreateBuffer = acquisition.device.createBuffer.bind(acquisition.device);
490
- const originalGetCurrentTexture = acquisition.context.getCurrentTexture.bind(acquisition.context);
491
- const createBuffer = vi.spyOn(acquisition.device, 'createBuffer').mockImplementation((descriptor) => {
492
- if (!deviceUsable) throw new Error('caller device was destroyed');
493
- return originalCreateBuffer(descriptor);
494
- });
495
- const getCurrentTexture = vi.spyOn(acquisition.context, 'getCurrentTexture').mockImplementation(() => {
496
- if (!contextUsable) throw new Error('caller context was unconfigured');
497
- return originalGetCurrentTexture();
498
- });
499
- const unconfigure = vi.spyOn(acquisition.context, 'unconfigure').mockImplementation(() => {
500
- contextUsable = false;
501
- });
502
- const destroy = vi.spyOn(acquisition.device, 'destroy').mockImplementation(() => {
503
- deviceUsable = false;
504
- });
505
- Object.defineProperty(globalThis.navigator, 'gpu', {
506
- configurable: true,
507
- get(): never {
508
- throw new Error('host getter failed');
509
- },
510
- });
454
+ it('takes the device alone: no surface, no context, nothing that belongs to a screen', async () => {
455
+ // The state is "how to talk to the GPU" and the screen target is "which surface a frame lands on".
456
+ // Keeping them apart is what lets one state render to several windows, and lets an offscreen state
457
+ // exist without inventing a canvas for it.
458
+ const acquisition = await createWgpuAcquisition(
459
+ _webBackend,
460
+ createTestWgpuSurface(document.createElement('canvas')),
461
+ );
462
+ const state = createWgpuRenderState(acquisition!.device, { format: acquisition!.format });
511
463
 
512
- try {
513
- const state = createWgpuRenderState(acquisition);
514
- const offscreen = createWgpuOffscreenRenderState(state);
515
- expect(state.context).toBe(acquisition.context);
516
- expect(state.device).toBe(acquisition.device);
517
- expect(state.format).toBe(acquisition.format);
518
- expect('context' in offscreen).toBe(false);
519
- expect(offscreen.device).toBe(acquisition.device);
520
- expect(offscreen.format).toBe(acquisition.format);
521
- const createBufferCallsBeforeTeardown = createBuffer.mock.calls.length;
522
- const getCurrentTextureCallsBeforeTeardown = getCurrentTexture.mock.calls.length;
523
- destroyWgpuRenderState(state);
524
- destroyWgpuRenderState(offscreen);
525
- expect(unconfigure).not.toHaveBeenCalled();
526
- expect(destroy).not.toHaveBeenCalled();
527
-
528
- const buffer = acquisition.device.createBuffer({ size: 4, usage: GPUBufferUsage.COPY_DST });
529
- expect(buffer.size).toBe(4);
530
- expect(acquisition.context.getCurrentTexture().createView()).toBeDefined();
531
- expect(createBuffer).toHaveBeenCalledTimes(createBufferCallsBeforeTeardown + 1);
532
- expect(getCurrentTexture).toHaveBeenCalledTimes(getCurrentTextureCallsBeforeTeardown + 1);
533
- buffer.destroy();
534
- } finally {
535
- installWgpuMock();
536
- destroyWgpuRenderState(owner);
537
- }
538
- });
464
+ expect(state.device).toBe(acquisition!.device);
465
+ expect(state.format).toBe(acquisition!.format);
466
+ expect('context' in state).toBe(false);
467
+ expect('surface' in state).toBe(false);
539
468
 
540
- it('returns a render state with device and context', async () => {
541
- const state = await createWgpuRenderStateForTest();
542
- expect(state.device).toBeDefined();
543
- expect(state.context).toBeDefined();
469
+ destroyWgpuRenderState(state);
470
+ releaseWgpuAcquisition(_webBackend, acquisition!);
544
471
  });
545
472
 
546
473
  it('sets allowSmoothing to true by default', async () => {
@@ -556,169 +483,87 @@ describe('createWgpuRenderState', () => {
556
483
  expect(runtime.uniformOffset).toBe(0);
557
484
  });
558
485
 
559
- // C5: the state exposes the surface as SIZE ONLY. Asserting `instanceof HTMLCanvasElement` here would
560
- // re-impose the DOM dependency the surface type exists to remove — that the web backend's surface happens
561
- // to be a canvas is a property of that backend, pinned in wgpuHost.test.ts, not of the state contract.
562
- it('exposes the presentation surface as live size, carrying no DOM member', async () => {
486
+ it('does not mutate a frozen preset when used as options input', async () => {
487
+ const preset = Object.freeze({
488
+ ...buildWgpuRenderRegistries({}),
489
+ nodeRenderers: new Map(),
490
+ });
491
+ const state = await createWgpuRenderStateForTest({ ...preset });
492
+ registerNodeRenderer(state, 'acme.Test', { createData: () => null, submit: () => {} });
493
+ expect(preset.nodeRenderers.size).toBe(0);
494
+ expect(getWgpuRenderStateRuntime(state).registries.nodeRenderers.size).toBe(1);
495
+ });
496
+
497
+ it('keeps revision counters on the runtime, not in registries', async () => {
563
498
  const state = await createWgpuRenderStateForTest();
564
- expect(typeof state.surface.width).toBe('number');
565
- expect(typeof state.surface.height).toBe('number');
566
- expect(Object.keys(state.surface as object).filter((key) => key !== 'width' && key !== 'height')).toEqual([]);
499
+ const runtime = getWgpuRenderStateRuntime(state);
500
+ expect(runtime.modifierSnippetRevision).toBe(0);
501
+ expect('modifierSnippetRevision' in runtime.registries).toBe(false);
567
502
  });
568
503
 
569
- it('starts with null renderPass and commandEncoder', async () => {
504
+ it('starts with no open frame, pass, or target', async () => {
570
505
  const state = await createWgpuRenderStateForTest();
571
506
  const runtime = getWgpuRenderStateRuntime(state);
572
507
  expect(runtime.renderPass).toBeNull();
573
508
  expect(runtime.commandEncoder).toBeNull();
574
- });
575
- });
576
-
577
- describe('createWgpuRenderStateFromCanvasElement', () => {
578
- it('acquires flight-owned handles and releases them when the state is destroyed', async () => {
579
- const owner = await createWgpuRenderStateForTest();
580
- const acquisition = { ...ownerAcquisition(owner), ownership: 'flight' } as const;
581
- const released: Readonly<WgpuHostAcquisition>[] = [];
582
- setWgpuHostBackend(
583
- entityHostBackend({
584
- acquire: vi.fn(async () => acquisition),
585
- isSupported: vi.fn(() => true),
586
- release: vi.fn((held: Readonly<WgpuHostAcquisition>) => released.push(held)),
587
- }),
588
- );
589
-
590
- const state = await createWgpuRenderStateFromCanvasElement(document.createElement('canvas'));
591
- destroyWgpuRenderState(state);
592
-
593
- expect(released).toEqual([acquisition]);
594
- setWgpuHostBackend(null);
595
- destroyWgpuRenderState(owner);
596
- });
597
-
598
- it('forwards the acquisition options, which the render options no longer carry', async () => {
599
- const owner = await createWgpuRenderStateForTest();
600
- const acquire = vi.fn(async () => ({ ...ownerAcquisition(owner), ownership: 'flight' }) as const);
601
- setWgpuHostBackend(entityHostBackend({ acquire, isSupported: vi.fn(() => true), release: vi.fn() }));
602
- const canvas = document.createElement('canvas');
603
-
604
- const state = await createWgpuRenderStateFromCanvasElement(canvas, {
605
- format: 'rgba8unorm',
606
- powerPreference: 'low-power',
607
- });
608
-
609
- expect(acquire).toHaveBeenCalledWith(canvas, { format: 'rgba8unorm', powerPreference: 'low-power' });
610
- destroyWgpuRenderState(state);
611
- setWgpuHostBackend(null);
612
- destroyWgpuRenderState(owner);
509
+ expect(runtime.passStack).toEqual([]);
510
+ expect(runtime.currentRenderTarget).toBeNull();
613
511
  });
614
512
  });
615
513
 
616
514
  describe('createWgpuRenderStateRuntime', () => {
617
515
  it('returns a runtime with the base binding slot and empty named registration tables', () => {
618
- const runtime = createWgpuRenderStateRuntime(createWgpuDeviceState({} as GPUDevice));
516
+ const runtime = createWgpuRenderStateRuntime(createWgpuDeviceState({} as WgpuDevice));
619
517
  expect(runtime.binding).toBeNull();
620
- expect(runtime.registries.customMaterialShaders).toMatchObject({
621
- onMiss: 'Unregistered',
622
- registry: 'WgpuCustomMaterialShader',
623
- shape: 'keyed',
624
- });
625
- expect(runtime.registries.customMaterialShaders.entries.size).toBe(0);
626
- expect(runtime.registries.materialRenderers).toMatchObject({
627
- onMiss: 'StandardMaterial',
628
- registry: 'WgpuMaterialRenderer',
629
- shape: 'keyed',
630
- });
631
- expect(runtime.registries.materialRenderers.entries.size).toBe(0);
632
- expect(runtime.registries.meshMaterialRenderers).toMatchObject({
633
- onMiss: 'StandardMaterial',
634
- registry: 'WgpuMeshMaterialRenderer',
635
- shape: 'keyed',
636
- });
637
- expect(runtime.registries.meshMaterialRenderers.entries.size).toBe(0);
638
- expect(runtime.registries.modifierSnippets).toMatchObject({
639
- onMiss: 'Unregistered',
640
- registry: 'WgpuModifierSnippet',
641
- shape: 'keyed',
642
- });
643
- expect(runtime.registries.modifierSnippets.entries.size).toBe(0);
644
- expect(runtime.registries.modifierSnippetRevision).toBe(0);
645
- expect(runtime.registries.renderEffects).toMatchObject({
646
- onMiss: 'Unregistered',
647
- registry: 'WgpuRenderEffect',
648
- shape: 'keyed',
649
- });
650
- expectEntitySlot(runtime.registries.compressedTextureDecoder, {
651
- entry: null,
652
- onMiss: 'Unregistered',
653
- registry: 'WgpuCompressedTextureDecoder',
654
- shape: 'slot',
655
- });
518
+ expect(runtime.registries.customMaterialShaders.size).toBe(0);
519
+ expect(runtime.registries.materialRenderers.size).toBe(0);
520
+ expect(runtime.registries.modifierSnippets.size).toBe(0);
521
+ expect(runtime.modifierSnippetRevision).toBe(0);
522
+ expect(runtime.registries.effects.size).toBe(0);
523
+ expect(runtime.registries.compressedTextureDecoder).toBeNull();
656
524
  expect(runtime.registries.colorAdjustments).toBeUndefined();
657
- expectEntitySlot(runtime.registries.compressedTextureUpload, {
658
- entry: null,
659
- onMiss: 'Unregistered',
660
- registry: 'WgpuCompressedTextureUpload',
661
- shape: 'slot',
662
- });
663
- expectEntitySlot(runtime.registries.shapeRasterizer, {
664
- entry: null,
665
- onMiss: 'Unregistered',
666
- registry: 'WgpuShapeRasterizer',
667
- shape: 'slot',
668
- });
669
- expectEntitySlot(runtime.registries.strokeTessellator, {
670
- entry: null,
671
- onMiss: 'Rasterize',
672
- registry: 'StrokeTessellator',
673
- shape: 'slot',
674
- });
675
- expect(runtime.registries.velocityWriters).toMatchObject({
676
- onMiss: 'Unregistered',
677
- registry: 'WgpuVelocityWriter',
678
- shape: 'keyed',
679
- });
680
- expect(runtime.registries.velocityWriters.entries.size).toBe(0);
525
+ expect(runtime.registries.compressedTextureUpload).toBeNull();
526
+ expect(runtime.registries.shapeRasterizer).toBeNull();
527
+ expect(runtime.registries.strokeTessellator).toBeNull();
528
+ expect(runtime.registries.velocityWriters.size).toBe(0);
681
529
  });
682
530
 
683
531
  it('shares the device tier when two runtimes are built from the same WgpuDeviceState', () => {
684
- const deviceState = createWgpuDeviceState({} as GPUDevice);
532
+ const deviceState = createWgpuDeviceState({} as WgpuDevice);
685
533
  const runtimeA = createWgpuRenderStateRuntime(deviceState);
686
534
  const runtimeB = createWgpuRenderStateRuntime(deviceState);
687
535
 
688
536
  const resources = {
689
- linearSampler: {} as GPUSampler,
690
- nearestSampler: {} as GPUSampler,
691
- textureBindGroupLayout: {} as GPUBindGroupLayout,
692
- uniformBindGroupLayout: {} as GPUBindGroupLayout,
537
+ linearSampler: {} as WgpuSampler,
538
+ nearestSampler: {} as WgpuSampler,
539
+ textureBindGroupLayout: {} as WgpuBindGroupLayout,
540
+ uniformBindGroupLayout: {} as WgpuBindGroupLayout,
693
541
  };
694
542
  runtimeA.context.resources = resources;
695
543
  expect(runtimeB.context.resources).toBe(resources);
696
544
  });
697
545
 
698
546
  it('keeps separate device tiers when two runtimes are built from different WgpuDeviceStates', () => {
699
- const runtimeA = createWgpuRenderStateRuntime(createWgpuDeviceState({} as GPUDevice));
700
- const runtimeB = createWgpuRenderStateRuntime(createWgpuDeviceState({} as GPUDevice));
547
+ const runtimeA = createWgpuRenderStateRuntime(createWgpuDeviceState({} as WgpuDevice));
548
+ const runtimeB = createWgpuRenderStateRuntime(createWgpuDeviceState({} as WgpuDevice));
701
549
 
702
550
  expect(runtimeA.context).not.toBe(runtimeB.context);
703
551
  });
704
552
  });
705
553
 
706
554
  describe('destroyWgpuRenderState', () => {
707
- it('releases a Flight-owned acquisition once after its last derived state', async () => {
555
+ it('never destroys the device, however many of its states are torn down', async () => {
556
+ // The device came from the caller and outlives every state built on it — including the last one.
708
557
  const state = await createWgpuRenderStateForTest();
709
558
  const offscreen = createWgpuOffscreenRenderState(state);
710
- const unconfigure = vi.spyOn(state.context, 'unconfigure');
711
559
  const destroy = vi.spyOn(state.device, 'destroy');
712
560
 
713
561
  destroyWgpuRenderState(state);
714
562
  destroyWgpuRenderState(state);
715
- expect(unconfigure).not.toHaveBeenCalled();
716
- expect(destroy).not.toHaveBeenCalled();
717
-
718
563
  destroyWgpuRenderState(offscreen);
719
564
  destroyWgpuRenderState(offscreen);
720
- expect(unconfigure).toHaveBeenCalledOnce();
721
- expect(destroy).toHaveBeenCalledOnce();
565
+
566
+ expect(destroy).not.toHaveBeenCalled();
722
567
  });
723
568
 
724
569
  it('destroys the state-owned uniform buffer', async () => {
@@ -798,17 +643,9 @@ describe('getWgpuColorAdjustmentMaterialFeature', () => {
798
643
  const runtime = getWgpuRenderStateRuntime(state);
799
644
 
800
645
  expect(getWgpuColorAdjustmentMaterialFeature(state)).toBeNull();
801
- runtime.registries.colorAdjustmentFeature = {
802
- entry: { state: RegistryEntryState.Bound, value: feature },
803
- onMiss: 'Disabled',
804
- registry: 'WgpuColorAdjustmentFeature',
805
- shape: 'slot',
806
- };
646
+ runtime.registries.colorAdjustmentFeature = feature;
807
647
  expect(getWgpuColorAdjustmentMaterialFeature(state)).toBe(feature);
808
- runtime.registries.colorAdjustmentFeature = {
809
- ...runtime.registries.colorAdjustmentFeature,
810
- entry: { state: RegistryEntryState.Tombstoned },
811
- };
648
+ runtime.registries.colorAdjustmentFeature = null;
812
649
  expect(getWgpuColorAdjustmentMaterialFeature(state)).toBeNull();
813
650
  });
814
651
  });
@@ -820,24 +657,16 @@ describe('getWgpuColorAdjustmentMaterialFeatureGuard', () => {
820
657
  const runtime = getWgpuRenderStateRuntime(state);
821
658
 
822
659
  expect(getWgpuColorAdjustmentMaterialFeatureGuard(state)).toBeNull();
823
- runtime.registries.colorAdjustmentFeatureGuard = {
824
- entry: { state: RegistryEntryState.Bound, value: guard },
825
- onMiss: 'Disabled',
826
- registry: 'WgpuColorAdjustmentFeatureGuard',
827
- shape: 'slot',
828
- };
660
+ runtime.registries.colorAdjustmentFeatureGuard = guard;
829
661
  expect(getWgpuColorAdjustmentMaterialFeatureGuard(state)).toBe(guard);
830
- runtime.registries.colorAdjustmentFeatureGuard = {
831
- ...runtime.registries.colorAdjustmentFeatureGuard,
832
- entry: { state: RegistryEntryState.Tombstoned },
833
- };
662
+ runtime.registries.colorAdjustmentFeatureGuard = null;
834
663
  expect(getWgpuColorAdjustmentMaterialFeatureGuard(state)).toBeNull();
835
664
  });
836
665
  });
837
666
 
838
667
  describe('getWgpuDeviceRuntime', () => {
839
668
  it('returns the device runtime attached by createWgpuDeviceState', () => {
840
- const device = {} as GPUDevice;
669
+ const device = {} as WgpuDevice;
841
670
  const deviceState = createWgpuDeviceState(device);
842
671
  const runtime = getWgpuDeviceRuntime(deviceState);
843
672
  expect(runtime).toBeDefined();
@@ -846,7 +675,7 @@ describe('getWgpuDeviceRuntime', () => {
846
675
  });
847
676
 
848
677
  it('resolves the same runtime object on repeated calls', () => {
849
- const deviceState = createWgpuDeviceState({} as GPUDevice);
678
+ const deviceState = createWgpuDeviceState({} as WgpuDevice);
850
679
  expect(getWgpuDeviceRuntime(deviceState)).toBe(getWgpuDeviceRuntime(deviceState));
851
680
  });
852
681
  });
@@ -963,7 +792,7 @@ describe('initializeWgpuOffscreenRenderStateOkResult', () => {
963
792
 
964
793
  describe('isWgpuSupported', () => {
965
794
  it('returns true when navigator.gpu is present', () => {
966
- expect(isWgpuSupported()).toBe(true);
795
+ expect(isWgpuSupported(_webBackend)).toBe(true);
967
796
  });
968
797
 
969
798
  it('returns false when navigator.gpu throws', () => {
@@ -974,7 +803,8 @@ describe('isWgpuSupported', () => {
974
803
  },
975
804
  });
976
805
  try {
977
- expect(isWgpuSupported()).toBe(false);
806
+ const unsupportedBackend = testWgpuHost;
807
+ expect(isWgpuSupported(unsupportedBackend)).toBe(false);
978
808
  } finally {
979
809
  installWgpuMock();
980
810
  }
@@ -992,15 +822,6 @@ describe('registerWgpuDeviceTeardown', () => {
992
822
  });
993
823
  });
994
824
 
995
- function ownerAcquisition(owner: WgpuPresentationRenderState): Omit<WgpuHostAcquisition, 'ownership'> {
996
- const out = allocateEntity<any>();
997
- out.context = owner.context;
998
- out.device = owner.device;
999
- out.format = owner.format;
1000
- out.surface = owner.surface;
1001
- return finishEntity(out);
1002
- }
1003
-
1004
825
  describe('registerWgpuRenderStateTeardown', () => {
1005
826
  it('runs a state-owned callback exactly once on teardown', async () => {
1006
827
  const state = await createWgpuRenderStateForTest();
@@ -1019,24 +840,23 @@ describe('releaseWgpuAcquisition', () => {
1019
840
  // Unconditional on purpose: this is the CALLER asking. Flight's own paths refuse to release caller-owned
1020
841
  // handles, so if this verb deferred to the same policy the caller would have no way to end their life.
1021
842
  it('releases caller-owned handles, which Flight itself never does', async () => {
1022
- const owner = await createWgpuRenderStateForTest();
1023
- const acquisition = { ...ownerAcquisition(owner), ownership: 'caller' } as const;
843
+ const acquired = await createWgpuAcquisition(_webBackend, createTestWgpuSurface(document.createElement('canvas')));
844
+ const acquisition = acquired!;
1024
845
  const released: Readonly<WgpuHostAcquisition>[] = [];
1025
- setWgpuHostBackend(
1026
- entityHostBackend({
1027
- acquire: vi.fn(async () => acquisition),
1028
- isSupported: vi.fn(() => true),
1029
- release: vi.fn((held: Readonly<WgpuHostAcquisition>) => released.push(held)),
1030
- }),
1031
- );
846
+ const recordingBackend = entityHostBackend({
847
+ acquire: vi.fn(async () => acquisition),
848
+ attachSurface: vi.fn(() => null),
849
+ create: vi.fn(() => null),
850
+ isSupported: vi.fn(() => true),
851
+ release: vi.fn((held: Readonly<WgpuHostAcquisition>) => released.push(held)),
852
+ });
1032
853
 
1033
- releaseWgpuAcquisition(acquisition);
854
+ releaseWgpuAcquisition(recordingBackend, acquisition);
1034
855
 
1035
856
  expect(released).toEqual([acquisition]);
1036
- setWgpuHostBackend(null);
1037
- destroyWgpuRenderState(owner);
1038
857
  });
1039
858
  });
859
+
1040
860
  describe('resolveWgpuApplyBlendMode', () => {
1041
861
  it('returns a hook installed directly on the state', async () => {
1042
862
  const state = await createWgpuRenderStateForTest();
@@ -1046,157 +866,50 @@ describe('resolveWgpuApplyBlendMode', () => {
1046
866
  });
1047
867
  });
1048
868
 
1049
- // ★ OWNERSHIP LIFECYCLE. Flight decides whether an acquisition is released; the backend only carries out
1050
- // the teardown. Each backend here would really destroy the handles if asked, so "not released" is a fact
1051
- // about Flight's decision rather than about a spy that could not have destroyed anything.
1052
- describe('wgpu acquisition lifecycle', () => {
1053
- const destroyingBackend = (
1054
- acquisition: Readonly<WgpuHostAcquisition>,
1055
- ): { backend: WgpuHostBackend; released: Readonly<WgpuHostAcquisition>[] } => {
1056
- const released: Readonly<WgpuHostAcquisition>[] = [];
1057
- return {
1058
- backend: entityHostBackend({
1059
- acquire: vi.fn(async () => acquisition),
1060
- isSupported: vi.fn(() => true),
1061
- release: vi.fn((held: Readonly<WgpuHostAcquisition>) => {
1062
- released.push(held);
1063
- held.device.destroy();
1064
- }),
1065
- }),
1066
- released,
1067
- };
1068
- };
1069
-
1070
- it('L1: releases a flight-owned acquisition exactly once, after the last sharer, in either order', async () => {
1071
- for (const destroyOffscreenFirst of [false, true]) {
1072
- const owner = await createWgpuRenderStateForTest();
1073
- const acquisition = { ...ownerAcquisition(owner), ownership: 'flight' } as const;
1074
- const { backend, released } = destroyingBackend(acquisition);
1075
- setWgpuHostBackend(backend);
1076
-
1077
- const state = createWgpuRenderState(acquisition);
1078
- const offscreen = createWgpuOffscreenRenderState(state);
1079
- const first = destroyOffscreenFirst ? offscreen : state;
1080
- const second = destroyOffscreenFirst ? state : offscreen;
1081
-
1082
- destroyWgpuRenderState(first);
1083
- expect(released, 'released before the last sharer was destroyed').toEqual([]);
1084
- destroyWgpuRenderState(second);
1085
- expect(released).toEqual([acquisition]);
1086
-
1087
- setWgpuHostBackend(null);
1088
- destroyWgpuRenderState(owner);
1089
- }
1090
- });
1091
-
1092
- it('L2: never releases a caller-owned acquisition, in either destroy order', async () => {
1093
- for (const destroyOffscreenFirst of [false, true]) {
1094
- const owner = await createWgpuRenderStateForTest();
1095
- const acquisition = { ...ownerAcquisition(owner), ownership: 'caller' } as const;
1096
- const { backend, released } = destroyingBackend(acquisition);
1097
- setWgpuHostBackend(backend);
1098
-
1099
- const state = createWgpuRenderState(acquisition);
1100
- const offscreen = createWgpuOffscreenRenderState(state);
1101
- destroyWgpuRenderState(destroyOffscreenFirst ? offscreen : state);
1102
- destroyWgpuRenderState(destroyOffscreenFirst ? state : offscreen);
1103
-
1104
- expect(released).toEqual([]);
1105
- // L5: the handles still work, which is what the caller actually depends on.
1106
- expect(acquisition.device.createBuffer({ size: 4, usage: GPUBufferUsage.COPY_DST }).size).toBe(4);
1107
-
1108
- setWgpuHostBackend(null);
1109
- destroyWgpuRenderState(owner);
1110
- }
1111
- });
1112
-
1113
- it('L3: destroying the same state twice releases once', async () => {
1114
- const owner = await createWgpuRenderStateForTest();
1115
- const acquisition = { ...ownerAcquisition(owner), ownership: 'flight' } as const;
1116
- const { backend, released } = destroyingBackend(acquisition);
1117
- setWgpuHostBackend(backend);
1118
-
1119
- const state = createWgpuRenderState(acquisition);
1120
- destroyWgpuRenderState(state);
1121
- destroyWgpuRenderState(state);
1122
-
1123
- expect(released).toEqual([acquisition]);
1124
- setWgpuHostBackend(null);
1125
- destroyWgpuRenderState(owner);
1126
- });
1127
-
1128
- it('L4: routes release to the backend that acquired, not whichever is installed at destroy time', async () => {
1129
- const owner = await createWgpuRenderStateForTest();
1130
- const acquisition = { ...ownerAcquisition(owner), ownership: 'flight' } as const;
1131
- const acquiring = destroyingBackend(acquisition);
1132
- const replacement = destroyingBackend(acquisition);
1133
- setWgpuHostBackend(acquiring.backend);
1134
-
1135
- const state = createWgpuRenderState(acquisition);
1136
- setWgpuHostBackend(replacement.backend);
1137
- destroyWgpuRenderState(state);
1138
-
1139
- expect(acquiring.released).toEqual([acquisition]);
1140
- expect(replacement.released, 'released through the backend installed later').toEqual([]);
1141
-
1142
- setWgpuHostBackend(null);
1143
- destroyWgpuRenderState(owner);
1144
- });
1145
- });
1146
-
1147
- describe('WgpuPipeline snapshots', () => {
869
+ describe('WgpuRenderRegistries snapshots', () => {
1148
870
  it('captures late Wgpu registrations only when an explicit pipeline is created', async () => {
1149
871
  const screen = await createWgpuRenderStateForTest();
1150
872
  const materialRenderer = { instanceFloatCount: 0, getShaderModule: vi.fn() } as never;
1151
873
  const offscreenMaterialRenderer = { instanceFloatCount: 0, getShaderModule: vi.fn() } as never;
1152
- const decoder = vi.fn(() => new Uint8ClampedArray(4));
874
+ const decoder = vi.fn(() => new Uint8Array(4));
1153
875
  const resolver = vi.fn(() => null);
1154
876
  registerWgpuCompressedTextureDecoder(screen, decoder);
1155
- registerWgpuCompressedTextureUpload(screen);
1156
- registerWgpuMaterialRenderer(screen, 'acme.LateMaterial', materialRenderer);
877
+ registerWgpuCompressedTextureUpload(screen, true);
878
+ registerWgpuQuadMaterialRenderer(screen, 'acme.LateMaterial', materialRenderer);
1157
879
  registerWgpuTextureResolver(screen, 'acme.LateTexture', resolver);
1158
880
  const offscreen = createWgpuOffscreenRenderState(screen);
1159
881
 
1160
- expect(
1161
- getRegistryTableEntry(getWgpuRenderStateRuntime(offscreen).registries.materialRenderers, 'acme.LateMaterial'),
1162
- ).toBe(materialRenderer);
1163
- expect(
1164
- getRegistryTableEntry(getWgpuRenderStateRuntime(offscreen).registries.textureResolvers, 'acme.LateTexture'),
1165
- ).toBe(resolver);
882
+ expect(getWgpuRenderStateRuntime(offscreen).registries.materialRenderers.get('acme.LateMaterial') ?? null).toBe(
883
+ materialRenderer,
884
+ );
885
+ expect(getWgpuRenderStateRuntime(offscreen).registries.textureResolvers.get('acme.LateTexture') ?? null).toBe(
886
+ resolver,
887
+ );
1166
888
  expect(getWgpuRenderStateRuntime(offscreen).registries.compressedTextureDecoder).toBe(
1167
889
  getWgpuRenderStateRuntime(screen).registries.compressedTextureDecoder,
1168
890
  );
1169
- expect(getWgpuRenderStateRuntime(offscreen).registries.compressedTextureDecoder.entry).toEqual({
1170
- state: RegistryEntryState.Bound,
1171
- value: decoder,
1172
- });
891
+ expect(getWgpuRenderStateRuntime(offscreen).registries.compressedTextureDecoder).toEqual(decoder);
1173
892
  expect(getWgpuRenderStateRuntime(offscreen).registries.compressedTextureUpload).toBe(
1174
893
  getWgpuRenderStateRuntime(screen).registries.compressedTextureUpload,
1175
894
  );
1176
- registerWgpuMaterialRenderer(offscreen, 'acme.LateMaterial', offscreenMaterialRenderer);
895
+ registerWgpuQuadMaterialRenderer(offscreen, 'acme.LateMaterial', offscreenMaterialRenderer);
1177
896
  registerWgpuCompressedTextureDecoder(offscreen, null);
1178
- registerWgpuCompressedTextureUpload(offscreen, null);
897
+ registerWgpuCompressedTextureUpload(offscreen, false);
1179
898
  registerWgpuTextureResolver(offscreen, 'acme.LateTexture', null);
1180
- expect(
1181
- getRegistryTableEntry(getWgpuRenderStateRuntime(offscreen).registries.materialRenderers, 'acme.LateMaterial'),
1182
- ).toBe(offscreenMaterialRenderer);
1183
- expect(
1184
- getRegistryTableEntry(getWgpuRenderStateRuntime(screen).registries.materialRenderers, 'acme.LateMaterial'),
1185
- ).toBe(materialRenderer);
1186
- expect(
1187
- hasRegistryTableEntry(getWgpuRenderStateRuntime(offscreen).registries.textureResolvers, 'acme.LateTexture'),
1188
- ).toBe(false);
1189
- expect(
1190
- getRegistryTableEntry(getWgpuRenderStateRuntime(screen).registries.textureResolvers, 'acme.LateTexture'),
1191
- ).toBe(resolver);
1192
- expect(getWgpuRenderStateRuntime(offscreen).registries.compressedTextureDecoder.entry).toBeNull();
1193
- expect(getWgpuRenderStateRuntime(screen).registries.compressedTextureDecoder.entry?.state).toBe(
1194
- RegistryEntryState.Bound,
899
+ expect(getWgpuRenderStateRuntime(offscreen).registries.materialRenderers.get('acme.LateMaterial') ?? null).toBe(
900
+ offscreenMaterialRenderer,
1195
901
  );
1196
- expect(getWgpuRenderStateRuntime(offscreen).registries.compressedTextureUpload.entry).toBeNull();
1197
- expect(getWgpuRenderStateRuntime(screen).registries.compressedTextureUpload.entry?.state).toBe(
1198
- RegistryEntryState.Bound,
902
+ expect(getWgpuRenderStateRuntime(screen).registries.materialRenderers.get('acme.LateMaterial') ?? null).toBe(
903
+ materialRenderer,
904
+ );
905
+ expect(getWgpuRenderStateRuntime(offscreen).registries.textureResolvers.has('acme.LateTexture')).toBe(false);
906
+ expect(getWgpuRenderStateRuntime(screen).registries.textureResolvers.get('acme.LateTexture') ?? null).toBe(
907
+ resolver,
1199
908
  );
909
+ expect(getWgpuRenderStateRuntime(offscreen).registries.compressedTextureDecoder).toBeNull();
910
+ expect(getWgpuRenderStateRuntime(screen).registries.compressedTextureDecoder).not.toBeNull();
911
+ expect(getWgpuRenderStateRuntime(offscreen).registries.compressedTextureUpload).toBeNull();
912
+ expect(getWgpuRenderStateRuntime(screen).registries.compressedTextureUpload).not.toBeNull();
1200
913
  });
1201
914
  });
1202
915
 
@@ -1205,51 +918,3 @@ describe('WgpuPipeline snapshots', () => {
1205
918
  // would satisfy every construction-time assertion in this repo and fail only on a resize, so liveness is
1206
919
  // tested here through a NON-DOM provider whose values change behind getters — which also proves the second
1207
920
  // half of the contract, that nothing on the path reads a DOM member.
1208
- describe('WgpuPresentationSurface', () => {
1209
- it('C1/C2: drives every size consumer from a live, non-DOM, size-only provider', async () => {
1210
- const owner = await createWgpuRenderStateForTest();
1211
- let width = 800;
1212
- let height = 600;
1213
- const surface: WgpuPresentationSurface = {
1214
- get height() {
1215
- return height;
1216
- },
1217
- get width() {
1218
- return width;
1219
- },
1220
- };
1221
- const acquisition = (() => {
1222
- const out = allocateEntity<any>();
1223
- out.context = owner.context;
1224
- out.device = owner.device;
1225
- out.format = owner.format;
1226
- out.ownership = 'caller' as const;
1227
- out.surface = surface;
1228
- return finishEntity(out);
1229
- })();
1230
- const canvas = document.createElement('canvas');
1231
-
1232
- const state = createWgpuRenderState(acquisition);
1233
- expect(getWgpuSurfaceRenderExtent(state)).toEqual({ width: 800, height: 600 });
1234
-
1235
- width = 320;
1236
- height = 240;
1237
-
1238
- // Every consumer re-reads: a captured `{ width, height }` would still answer 800x600 here.
1239
- expect(state.surface.width).toBe(320);
1240
- expect(state.surface.height).toBe(240);
1241
- expect(getWgpuSurfaceRenderExtent(state)).toEqual({ width: 320, height: 240 });
1242
-
1243
- destroyWgpuRenderState(state);
1244
- destroyWgpuRenderState(owner);
1245
- });
1246
-
1247
- it('C4: accepts an HTMLCanvasElement structurally, so the web path needs no wrapper', () => {
1248
- const canvas = document.createElement('canvas');
1249
- canvas.width = 128;
1250
- canvas.height = 64;
1251
- const surface: WgpuPresentationSurface = canvas;
1252
- expect(surface.width).toBe(128);
1253
- expect(surface.height).toBe(64);
1254
- });
1255
- });