@jbrowse/render-core 4.3.0 → 5.0.0-beta.10

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 (352) hide show
  1. package/esm/RenderCanvas.d.ts +2 -2
  2. package/esm/RenderLifecycleMixin.d.ts +52 -20
  3. package/esm/RenderLifecycleMixin.js +89 -23
  4. package/esm/canvas2dUtils.d.ts +90 -23
  5. package/esm/canvas2dUtils.js +119 -36
  6. package/esm/colorRampLut.d.ts +5 -5
  7. package/esm/colorRampLut.js +6 -6
  8. package/esm/computePipeline.d.ts +14 -0
  9. package/esm/computePipeline.js +62 -0
  10. package/esm/contractReports.d.ts +54 -0
  11. package/esm/contractReports.js +112 -0
  12. package/esm/coverageBand.d.ts +13 -8
  13. package/esm/coverageBand.js +15 -5
  14. package/esm/coverageBandBuffers.d.ts +2 -9
  15. package/esm/coverageBandBuffers.js +1 -13
  16. package/esm/createRenderingBackend.d.ts +14 -18
  17. package/esm/createRenderingBackend.js +4 -2
  18. package/esm/displayPhase.d.ts +83 -104
  19. package/esm/displayPhase.js +42 -82
  20. package/esm/encodeMemo.d.ts +14 -0
  21. package/esm/encodeMemo.js +48 -0
  22. package/esm/gpuContextLostError.d.ts +30 -0
  23. package/esm/gpuContextLostError.js +40 -0
  24. package/esm/gpuDevice.d.ts +29 -10
  25. package/esm/gpuDevice.js +35 -16
  26. package/esm/graphicsCapabilities.d.ts +27 -19
  27. package/esm/graphicsCapabilities.js +40 -18
  28. package/esm/hal/createHal.d.ts +4 -5
  29. package/esm/hal/createHal.js +14 -4
  30. package/esm/hal/deviceGpuCache.d.ts +25 -30
  31. package/esm/hal/deviceGpuCache.js +88 -97
  32. package/esm/hal/gpuHalBase.d.ts +5 -4
  33. package/esm/hal/gpuHalBase.js +25 -14
  34. package/esm/hal/index.d.ts +2 -2
  35. package/esm/hal/index.js +1 -1
  36. package/esm/hal/mockHal.d.ts +15 -10
  37. package/esm/hal/mockHal.js +31 -18
  38. package/esm/hal/oomReporter.d.ts +7 -0
  39. package/esm/hal/oomReporter.js +10 -0
  40. package/esm/hal/passIds.d.ts +8 -7
  41. package/esm/hal/passIds.js +11 -10
  42. package/esm/hal/regionRegistry.d.ts +0 -1
  43. package/esm/hal/regionRegistry.js +3 -15
  44. package/esm/hal/types.d.ts +55 -18
  45. package/esm/hal/webgl2Hal.d.ts +23 -6
  46. package/esm/hal/webgl2Hal.js +161 -155
  47. package/esm/hal/webgpuHal.d.ts +29 -13
  48. package/esm/hal/webgpuHal.js +221 -153
  49. package/esm/installUpload.d.ts +16 -3
  50. package/esm/installUpload.js +13 -41
  51. package/esm/instanceCache.d.ts +10 -7
  52. package/esm/instanceCache.js +14 -15
  53. package/esm/instancePass.d.ts +2 -1
  54. package/esm/mapUploadSync.d.ts +2 -10
  55. package/esm/mapUploadSync.js +2 -3
  56. package/esm/marks/barMark.d.ts +30 -0
  57. package/esm/marks/barMark.js +149 -0
  58. package/esm/marks/colorFill.d.ts +17 -0
  59. package/esm/marks/colorFill.js +26 -0
  60. package/esm/marks/drawAgainstHit.d.ts +113 -0
  61. package/esm/marks/drawAgainstHit.js +407 -0
  62. package/esm/marks/ellipseDistance.d.ts +10 -0
  63. package/esm/marks/ellipseDistance.js +136 -0
  64. package/esm/marks/glyphPaint.d.ts +36 -0
  65. package/esm/marks/glyphPaint.js +77 -0
  66. package/esm/marks/index.d.ts +33 -0
  67. package/esm/marks/index.js +20 -0
  68. package/esm/marks/lineMark.d.ts +37 -0
  69. package/esm/marks/lineMark.js +416 -0
  70. package/esm/marks/linkMark.d.ts +76 -0
  71. package/esm/marks/linkMark.js +585 -0
  72. package/esm/marks/markBackend.d.ts +118 -0
  73. package/esm/marks/markBackend.js +196 -0
  74. package/esm/marks/markHit.d.ts +32 -0
  75. package/esm/marks/markHit.js +61 -0
  76. package/esm/marks/markInk.d.ts +18 -0
  77. package/esm/marks/markInk.js +71 -0
  78. package/esm/marks/markPaint.d.ts +14 -0
  79. package/esm/marks/markPaint.js +32 -0
  80. package/esm/marks/markPlan.d.ts +25 -0
  81. package/esm/marks/markPlan.js +20 -0
  82. package/esm/marks/markRamp.d.ts +72 -0
  83. package/esm/marks/markRamp.js +197 -0
  84. package/esm/marks/nearestMarkHit.d.ts +55 -0
  85. package/esm/marks/nearestMarkHit.js +158 -0
  86. package/esm/marks/pathRecorder.d.ts +14 -0
  87. package/esm/marks/pathRecorder.js +80 -0
  88. package/esm/marks/pointMark.d.ts +42 -0
  89. package/esm/marks/pointMark.js +125 -0
  90. package/esm/marks/rowLane.d.ts +39 -0
  91. package/esm/marks/rowLane.js +41 -0
  92. package/esm/marks/rowSpanIndex.d.ts +29 -0
  93. package/esm/marks/rowSpanIndex.js +141 -0
  94. package/esm/marks/rowTable.d.ts +41 -0
  95. package/esm/marks/rowTable.js +75 -0
  96. package/esm/marks/ruleMark.d.ts +21 -0
  97. package/esm/marks/ruleMark.js +91 -0
  98. package/esm/marks/spanMark.d.ts +42 -0
  99. package/esm/marks/spanMark.js +81 -0
  100. package/esm/marks/types.d.ts +261 -0
  101. package/esm/marks/types.js +175 -0
  102. package/esm/marks/valueScale.d.ts +23 -0
  103. package/esm/marks/valueScale.js +11 -0
  104. package/esm/namedReactions.d.ts +3 -4
  105. package/esm/namedReactions.js +3 -4
  106. package/esm/perRegionRenderingBackend.d.ts +21 -3
  107. package/esm/perRegionRenderingBackend.js +37 -3
  108. package/esm/regionDataMap.d.ts +2 -2
  109. package/esm/regionDataMap.js +25 -23
  110. package/esm/renderBlock.d.ts +14 -0
  111. package/esm/renderBlock.js +25 -0
  112. package/esm/renderingBackendBase.d.ts +20 -14
  113. package/esm/renderingBackendBase.js +12 -7
  114. package/esm/scoreScale.d.ts +27 -0
  115. package/esm/scoreScale.js +88 -0
  116. package/esm/shaders/barMark.generated.d.ts +3 -0
  117. package/esm/shaders/barMark.generated.js +7 -0
  118. package/esm/shaders/barMark.glsl.generated.d.ts +2 -0
  119. package/esm/shaders/barMark.glsl.generated.js +4 -0
  120. package/esm/shaders/barMark.iface.generated.d.ts +90 -0
  121. package/esm/shaders/barMark.iface.generated.js +205 -0
  122. package/esm/shaders/barMark.wgsl.generated.d.ts +1 -0
  123. package/esm/shaders/barMark.wgsl.generated.js +3 -0
  124. package/esm/shaders/capsule.js.generated.d.ts +1 -0
  125. package/esm/shaders/capsule.js.generated.js +11 -0
  126. package/esm/shaders/clipStrip.generated.d.ts +2 -0
  127. package/esm/shaders/clipStrip.generated.js +4 -0
  128. package/esm/shaders/clipStrip.js.generated.d.ts +1 -0
  129. package/esm/shaders/clipStrip.js.generated.js +21 -0
  130. package/esm/shaders/colorRampLut.js.generated.d.ts +1 -0
  131. package/esm/shaders/colorRampLut.js.generated.js +17 -0
  132. package/esm/shaders/coverageBar.generated.d.ts +2 -3
  133. package/esm/shaders/coverageBar.generated.js +4 -3
  134. package/esm/shaders/coverageBar.glsl.generated.d.ts +2 -0
  135. package/esm/shaders/coverageBar.glsl.generated.js +4 -0
  136. package/esm/shaders/coverageBar.iface.generated.js +1 -1
  137. package/esm/shaders/coverageBar.wgsl.generated.d.ts +1 -0
  138. package/esm/shaders/coverageBar.wgsl.generated.js +3 -0
  139. package/esm/shaders/coverageClip.generated.d.ts +3 -0
  140. package/esm/shaders/coverageClip.generated.js +7 -0
  141. package/esm/shaders/coverageClip.glsl.generated.d.ts +2 -0
  142. package/esm/shaders/coverageClip.glsl.generated.js +4 -0
  143. package/esm/shaders/coverageClip.iface.generated.d.ts +85 -0
  144. package/esm/shaders/coverageClip.iface.generated.js +114 -0
  145. package/esm/shaders/coverageClip.wgsl.generated.d.ts +1 -0
  146. package/esm/shaders/coverageClip.wgsl.generated.js +3 -0
  147. package/esm/shaders/coverageIndicator.generated.d.ts +2 -3
  148. package/esm/shaders/coverageIndicator.generated.js +4 -3
  149. package/esm/shaders/coverageIndicator.glsl.generated.d.ts +2 -0
  150. package/esm/shaders/coverageIndicator.glsl.generated.js +4 -0
  151. package/esm/shaders/coverageIndicator.iface.generated.js +1 -1
  152. package/esm/shaders/coverageIndicator.wgsl.generated.d.ts +1 -0
  153. package/esm/shaders/coverageIndicator.wgsl.generated.js +3 -0
  154. package/esm/shaders/coverageInterbase.generated.d.ts +2 -3
  155. package/esm/shaders/coverageInterbase.generated.js +4 -3
  156. package/esm/shaders/coverageInterbase.glsl.generated.d.ts +2 -0
  157. package/esm/shaders/coverageInterbase.glsl.generated.js +4 -0
  158. package/esm/shaders/coverageInterbase.iface.generated.js +1 -1
  159. package/esm/shaders/coverageInterbase.wgsl.generated.d.ts +1 -0
  160. package/esm/shaders/coverageInterbase.wgsl.generated.js +3 -0
  161. package/esm/shaders/coverageMod.generated.d.ts +2 -3
  162. package/esm/shaders/coverageMod.generated.js +4 -3
  163. package/esm/shaders/coverageMod.glsl.generated.d.ts +2 -0
  164. package/esm/shaders/coverageMod.glsl.generated.js +4 -0
  165. package/esm/shaders/coverageMod.iface.generated.js +1 -1
  166. package/esm/shaders/coverageMod.wgsl.generated.d.ts +1 -0
  167. package/esm/shaders/coverageMod.wgsl.generated.js +3 -0
  168. package/esm/shaders/coverageSnp.generated.d.ts +2 -3
  169. package/esm/shaders/coverageSnp.generated.js +4 -3
  170. package/esm/shaders/coverageSnp.glsl.generated.d.ts +2 -0
  171. package/esm/shaders/coverageSnp.glsl.generated.js +4 -0
  172. package/esm/shaders/coverageSnp.iface.generated.js +1 -1
  173. package/esm/shaders/coverageSnp.wgsl.generated.d.ts +1 -0
  174. package/esm/shaders/coverageSnp.wgsl.generated.js +3 -0
  175. package/esm/shaders/curveDistance.js.generated.d.ts +5 -0
  176. package/esm/shaders/curveDistance.js.generated.js +87 -0
  177. package/esm/shaders/hpmath.js.generated.d.ts +2 -1
  178. package/esm/shaders/hpmath.js.generated.js +5 -2
  179. package/esm/shaders/lineCenterMark.generated.d.ts +3 -0
  180. package/esm/shaders/lineCenterMark.generated.js +7 -0
  181. package/esm/shaders/lineCenterMark.glsl.generated.d.ts +2 -0
  182. package/esm/shaders/lineCenterMark.glsl.generated.js +4 -0
  183. package/esm/shaders/lineCenterMark.iface.generated.d.ts +104 -0
  184. package/esm/shaders/lineCenterMark.iface.generated.js +237 -0
  185. package/esm/shaders/lineCenterMark.wgsl.generated.d.ts +1 -0
  186. package/esm/shaders/lineCenterMark.wgsl.generated.js +3 -0
  187. package/esm/shaders/lineCommon.generated.d.ts +2 -0
  188. package/esm/shaders/lineCommon.generated.js +4 -0
  189. package/esm/shaders/lineStepMark.generated.d.ts +3 -0
  190. package/esm/shaders/lineStepMark.generated.js +7 -0
  191. package/esm/shaders/lineStepMark.glsl.generated.d.ts +2 -0
  192. package/esm/shaders/lineStepMark.glsl.generated.js +4 -0
  193. package/esm/shaders/lineStepMark.iface.generated.d.ts +98 -0
  194. package/esm/shaders/lineStepMark.iface.generated.js +225 -0
  195. package/esm/shaders/lineStepMark.wgsl.generated.d.ts +1 -0
  196. package/esm/shaders/lineStepMark.wgsl.generated.js +3 -0
  197. package/esm/shaders/linkMark.consts.generated.d.ts +14 -0
  198. package/esm/shaders/linkMark.consts.generated.js +16 -0
  199. package/esm/shaders/linkMark.generated.d.ts +4 -0
  200. package/esm/shaders/linkMark.generated.js +8 -0
  201. package/esm/shaders/linkMark.glsl.generated.d.ts +2 -0
  202. package/esm/shaders/linkMark.glsl.generated.js +4 -0
  203. package/esm/shaders/linkMark.iface.generated.d.ts +142 -0
  204. package/esm/shaders/linkMark.iface.generated.js +1829 -0
  205. package/esm/shaders/linkMark.js.generated.d.ts +7 -0
  206. package/esm/shaders/linkMark.js.generated.js +159 -0
  207. package/esm/shaders/linkMark.wgsl.generated.d.ts +1 -0
  208. package/esm/shaders/linkMark.wgsl.generated.js +3 -0
  209. package/esm/shaders/markColor.generated.d.ts +9 -0
  210. package/esm/shaders/markColor.generated.js +11 -0
  211. package/esm/shaders/pointGlyph.js.generated.d.ts +2 -0
  212. package/esm/shaders/pointGlyph.js.generated.js +15 -0
  213. package/esm/shaders/pointMark.consts.generated.d.ts +7 -0
  214. package/esm/shaders/pointMark.consts.generated.js +9 -0
  215. package/esm/shaders/pointMark.generated.d.ts +4 -0
  216. package/esm/shaders/pointMark.generated.js +8 -0
  217. package/esm/shaders/pointMark.glsl.generated.d.ts +2 -0
  218. package/esm/shaders/pointMark.glsl.generated.js +4 -0
  219. package/esm/shaders/pointMark.iface.generated.d.ts +98 -0
  220. package/esm/shaders/pointMark.iface.generated.js +219 -0
  221. package/esm/shaders/pointMark.js.generated.d.ts +3 -0
  222. package/esm/shaders/pointMark.js.generated.js +93 -0
  223. package/esm/shaders/pointMark.wgsl.generated.d.ts +1 -0
  224. package/esm/shaders/pointMark.wgsl.generated.js +3 -0
  225. package/esm/shaders/rowRect.generated.d.ts +0 -1
  226. package/esm/shaders/rowRect.generated.js +0 -1
  227. package/esm/shaders/rowTable.generated.d.ts +1 -0
  228. package/esm/shaders/rowTable.generated.js +3 -0
  229. package/esm/shaders/rowTable.js.generated.d.ts +5 -0
  230. package/esm/shaders/rowTable.js.generated.js +29 -0
  231. package/esm/shaders/scoreScale.generated.d.ts +2 -0
  232. package/esm/shaders/scoreScale.generated.js +4 -0
  233. package/esm/shaders/scoreScale.js.generated.d.ts +1 -0
  234. package/esm/shaders/scoreScale.js.generated.js +50 -23
  235. package/esm/shaders/spanMark.generated.d.ts +3 -0
  236. package/esm/shaders/spanMark.generated.js +7 -0
  237. package/esm/shaders/spanMark.glsl.generated.d.ts +2 -0
  238. package/esm/shaders/spanMark.glsl.generated.js +4 -0
  239. package/esm/shaders/spanMark.iface.generated.d.ts +81 -0
  240. package/esm/shaders/spanMark.iface.generated.js +215 -0
  241. package/esm/shaders/spanMark.wgsl.generated.d.ts +1 -0
  242. package/esm/shaders/spanMark.wgsl.generated.js +3 -0
  243. package/esm/sharedBackendKey.d.ts +18 -0
  244. package/esm/{keyedRenderingBackend.js → sharedBackendKey.js} +5 -0
  245. package/esm/slangPass.d.ts +18 -11
  246. package/esm/slangPass.js +12 -4
  247. package/esm/useGraphicsCapabilities.d.ts +1 -1
  248. package/esm/useGraphicsCapabilities.js +1 -1
  249. package/esm/useRenderingBackend.d.ts +13 -13
  250. package/esm/useRenderingBackend.js +58 -20
  251. package/esm/webgpuUtils.d.ts +3 -11
  252. package/esm/webgpuUtils.js +12 -33
  253. package/package.json +32 -7
  254. package/src/shaders/antialias.slang +46 -0
  255. package/src/shaders/arcHull.test.ts +267 -0
  256. package/src/shaders/barMark.generated.ts +11 -0
  257. package/src/shaders/barMark.glsl.generated.ts +6 -0
  258. package/src/shaders/barMark.iface.generated.ts +285 -0
  259. package/src/shaders/barMark.slang +167 -0
  260. package/src/shaders/barMark.wgsl.generated.ts +4 -0
  261. package/src/shaders/capsule.js.generated.ts +14 -0
  262. package/src/shaders/capsule.slang +12 -4
  263. package/src/shaders/clipStrip.generated.ts +6 -0
  264. package/src/shaders/clipStrip.js.generated.ts +22 -0
  265. package/src/shaders/clipStrip.slang +34 -0
  266. package/src/shaders/clipStrip.test.ts +39 -0
  267. package/src/shaders/colorPack.slang +5 -1
  268. package/src/shaders/colorRampLut.js.generated.ts +22 -0
  269. package/src/shaders/colorRampLut.slang +15 -1
  270. package/src/shaders/coverageBand.slang +64 -32
  271. package/src/shaders/coverageBar.generated.ts +6 -5
  272. package/src/shaders/coverageBar.glsl.generated.ts +6 -0
  273. package/src/shaders/coverageBar.iface.generated.ts +1 -1
  274. package/src/shaders/coverageBar.slang +10 -10
  275. package/src/shaders/coverageBar.wgsl.generated.ts +4 -0
  276. package/src/shaders/coverageClip.generated.ts +11 -0
  277. package/src/shaders/coverageClip.glsl.generated.ts +6 -0
  278. package/src/shaders/coverageClip.iface.generated.ts +172 -0
  279. package/src/shaders/coverageClip.slang +38 -0
  280. package/src/shaders/coverageClip.wgsl.generated.ts +4 -0
  281. package/src/shaders/coverageIndicator.generated.ts +6 -5
  282. package/src/shaders/coverageIndicator.glsl.generated.ts +6 -0
  283. package/src/shaders/coverageIndicator.iface.generated.ts +1 -1
  284. package/src/shaders/coverageIndicator.wgsl.generated.ts +4 -0
  285. package/src/shaders/coverageInterbase.generated.ts +6 -5
  286. package/src/shaders/coverageInterbase.glsl.generated.ts +6 -0
  287. package/src/shaders/coverageInterbase.iface.generated.ts +1 -1
  288. package/src/shaders/coverageInterbase.wgsl.generated.ts +4 -0
  289. package/src/shaders/coverageMod.generated.ts +6 -5
  290. package/src/shaders/coverageMod.glsl.generated.ts +6 -0
  291. package/src/shaders/coverageMod.iface.generated.ts +1 -1
  292. package/src/shaders/coverageMod.wgsl.generated.ts +4 -0
  293. package/src/shaders/coverageSnp.generated.ts +6 -5
  294. package/src/shaders/coverageSnp.glsl.generated.ts +6 -0
  295. package/src/shaders/coverageSnp.iface.generated.ts +1 -1
  296. package/src/shaders/coverageSnp.wgsl.generated.ts +4 -0
  297. package/src/shaders/curveDistance.js.generated.ts +91 -0
  298. package/src/shaders/curveDistance.slang +265 -0
  299. package/src/shaders/hpClampFloor.test.ts +87 -0
  300. package/src/shaders/hpmath.js.generated.ts +6 -2
  301. package/src/shaders/hpmath.slang +100 -48
  302. package/src/shaders/insetValueScale.test.ts +67 -0
  303. package/src/shaders/lineCenterMark.generated.ts +11 -0
  304. package/src/shaders/lineCenterMark.glsl.generated.ts +6 -0
  305. package/src/shaders/lineCenterMark.iface.generated.ts +328 -0
  306. package/src/shaders/lineCenterMark.slang +127 -0
  307. package/src/shaders/lineCenterMark.wgsl.generated.ts +4 -0
  308. package/src/shaders/lineCommon.generated.ts +6 -0
  309. package/src/shaders/lineCommon.slang +102 -0
  310. package/src/shaders/lineStepMark.generated.ts +11 -0
  311. package/src/shaders/lineStepMark.glsl.generated.ts +6 -0
  312. package/src/shaders/lineStepMark.iface.generated.ts +311 -0
  313. package/src/shaders/lineStepMark.slang +125 -0
  314. package/src/shaders/lineStepMark.wgsl.generated.ts +4 -0
  315. package/src/shaders/linkMark.consts.generated.ts +30 -0
  316. package/src/shaders/linkMark.generated.ts +12 -0
  317. package/src/shaders/linkMark.glsl.generated.ts +6 -0
  318. package/src/shaders/linkMark.iface.generated.ts +1954 -0
  319. package/src/shaders/linkMark.js.generated.ts +167 -0
  320. package/src/shaders/linkMark.slang +439 -0
  321. package/src/shaders/linkMark.wgsl.generated.ts +4 -0
  322. package/src/shaders/markColor.generated.ts +20 -0
  323. package/src/shaders/markColor.slang +128 -0
  324. package/src/shaders/pointGlyph.js.generated.ts +20 -0
  325. package/src/shaders/pointGlyph.slang +23 -7
  326. package/src/shaders/pointGlyphPad.test.ts +242 -0
  327. package/src/shaders/pointMark.consts.generated.ts +16 -0
  328. package/src/shaders/pointMark.generated.ts +12 -0
  329. package/src/shaders/pointMark.glsl.generated.ts +6 -0
  330. package/src/shaders/pointMark.iface.generated.ts +304 -0
  331. package/src/shaders/pointMark.js.generated.ts +99 -0
  332. package/src/shaders/pointMark.slang +227 -0
  333. package/src/shaders/pointMark.wgsl.generated.ts +4 -0
  334. package/src/shaders/rowRect.generated.ts +0 -2
  335. package/src/shaders/rowRect.slang +39 -58
  336. package/src/shaders/rowTable.generated.ts +4 -0
  337. package/src/shaders/rowTable.js.generated.ts +37 -0
  338. package/src/shaders/rowTable.slang +98 -0
  339. package/src/shaders/scoreScale.generated.ts +6 -0
  340. package/src/shaders/scoreScale.js.generated.ts +48 -23
  341. package/src/shaders/scoreScale.slang +49 -55
  342. package/src/shaders/sdEllipse.test.ts +211 -0
  343. package/src/shaders/spanMark.generated.ts +11 -0
  344. package/src/shaders/spanMark.glsl.generated.ts +6 -0
  345. package/src/shaders/spanMark.iface.generated.ts +289 -0
  346. package/src/shaders/spanMark.slang +77 -0
  347. package/src/shaders/spanMark.wgsl.generated.ts +4 -0
  348. package/src/shaders/valueScale.slang +26 -0
  349. package/src/shaders/wideCircleLeg.test.ts +85 -0
  350. package/esm/globalRenderingBackend.d.ts +0 -90
  351. package/esm/globalRenderingBackend.js +0 -53
  352. package/esm/keyedRenderingBackend.d.ts +0 -41
@@ -216,7 +216,7 @@ export function clipBlockForCanvas(block, canvasWidth) {
216
216
  * Clip to one rect, paint, unclip — the `save`/`clip`/`restore` triple with the
217
217
  * `restore` in a `finally`.
218
218
  *
219
- * The `finally` is the whole point, and the cost of missing it is not local: an
219
+ * The `finally` is required, and missing it breaks more than the one frame: an
220
220
  * on-screen ctx outlives the frame and `prepareCanvas`'s setTransform/clearRect
221
221
  * do **not** reset clip state, so one painter throwing once leaves every later
222
222
  * frame drawing through a stale clip. A transient error becomes permanent
@@ -227,10 +227,16 @@ export function clipBlockForCanvas(block, canvasWidth) {
227
227
  * own. Reach for this one for the clips *nested inside* a block — a display
228
228
  * whose bands each own a horizontal strip of the canvas (alignments clips its
229
229
  * coverage, pileup and arc bands separately within one block clip), where the
230
- * nesting is what makes a hand-rolled pairing easy to get wrong: an early
230
+ * nesting makes a hand-rolled pairing easy to get wrong: an early
231
231
  * `return` inside the band body unbalances the block's `save` too.
232
+ *
233
+ * An empty rect paints nothing, as the GPU's empty scissor does; the SVG export
234
+ * would otherwise record every path of a band nothing can show.
232
235
  */
233
236
  export function withClip(ctx, x, y, w, h, paint) {
237
+ if (w <= 0 || h <= 0) {
238
+ return;
239
+ }
234
240
  ctx.save();
235
241
  ctx.beginPath();
236
242
  ctx.rect(x, y, w, h);
@@ -334,6 +340,33 @@ export function strokeRectInside(ctx, x, y, w, h, lineWidth = 1) {
334
340
  export function spanLeft(x1, x2, width) {
335
341
  return x2 < x1 ? x1 - width : x1;
336
342
  }
343
+ /**
344
+ * The `fillRect` x and width a genomic span paints as, given a bare
345
+ * `makeBpMapper`: `spanLeft`'s pivot and the min-width floor that goes with it,
346
+ * as one value a painter and its hit box can both read.
347
+ *
348
+ * `minWidth` defaults to 0, which makes this plain screen ordering — the
349
+ * leftmost projected edge and the unsigned distance. Pass a floor and the span
350
+ * grows away from `startBp`, which is the reversed-block rule `spanLeft` owns:
351
+ * anchoring the leftmost edge instead slides a sub-pixel mark by up to the floor
352
+ * on a flipped region and never on a forward one.
353
+ *
354
+ * Reach for this over `spanLeft` wherever the *numbers* are wanted rather than a
355
+ * fill — a hover box, an SVG rect, a cull test, an overlay div — which is where
356
+ * the pivot and the floor were being restated separately. The multi-row painter
357
+ * and the hover box it has to line up with each spelled out both.
358
+ * `fillBpSpan` is the same span when a `fillRect` is the only consumer.
359
+ *
360
+ * Not for a per-instance paint loop: this allocates a result per call, so the
361
+ * span mark's painter and wiggle's two bar loops take `spanLeft` and the two
362
+ * numbers inline, and stay the last hand-written copies of this arithmetic.
363
+ */
364
+ export function spanRect(toX, startBp, endBp, minWidth = 0) {
365
+ const x1 = toX(startBp);
366
+ const x2 = toX(endBp);
367
+ const width = Math.max(minWidth, Math.abs(x2 - x1));
368
+ return { left: spanLeft(x1, x2, width), width };
369
+ }
337
370
  // Quantize a 0..1 ramp position to a 256-entry index. Shared so the direct
338
371
  // lookup and the fillStyle LUT below can't quantize differently — a half-step
339
372
  // of drift between them shows up as a one-shade mismatch between a cell's fill
@@ -359,26 +392,42 @@ export function makeRampFillStyleLut(ramp) {
359
392
  return s;
360
393
  };
361
394
  }
362
- export function bpToScreenPx(absBp, regionStart, regionEnd, screenStartPx, screenEndPx, reversed) {
363
- const frac = (absBp - regionStart) / (regionEnd - regionStart);
395
+ export function bpProjection(bounds) {
396
+ const { start, end, screenStartPx, screenEndPx, reversed } = bounds;
364
397
  const w = screenEndPx - screenStartPx;
365
- return reversed ? screenEndPx - frac * w : screenStartPx + frac * w;
398
+ return {
399
+ originPx: reversed ? screenEndPx : screenStartPx,
400
+ startBp: start,
401
+ spanBp: end - start,
402
+ signedSpanPx: reversed ? -w : w,
403
+ };
366
404
  }
367
- // Closure-style bp→screen-px mapper bound to one region. Consumers that walk
368
- // many bp positions inside one block (label/peptide overlays, rect/line draws)
369
- // want a 1-arg call instead of repeating 6 args at every site.
405
+ export function projectBp(p, bp) {
406
+ return p.originPx + ((bp - p.startBp) / p.spanBp) * p.signedSpanPx;
407
+ }
408
+ /**
409
+ * One closure literal for both orientations. Split per orientation, a paint
410
+ * loop's mapper call goes megamorphic on a view mixing them, and the loop ran
411
+ * 1.9-2.3x slower (`benches/bpMapper.bench.ts`).
412
+ */
370
413
  export function makeBpMapper(bounds) {
371
- const { start, end, screenStartPx, screenEndPx, reversed } = bounds;
372
- const span = end - start;
373
- const w = screenEndPx - screenStartPx;
374
- return reversed
375
- ? (bp) => screenEndPx - ((bp - start) / span) * w
376
- : (bp) => screenStartPx + ((bp - start) / span) * w;
414
+ const { originPx, startBp, spanBp, signedSpanPx } = bpProjection(bounds);
415
+ return (bp) => originPx + ((bp - startBp) / spanBp) * signedSpanPx;
416
+ }
417
+ /**
418
+ * Screen px one base occupies in this region: the scale factor, unsigned, with
419
+ * the block's direction left to `makeBpMapper` and `spanLeft`. Shared so a mark
420
+ * sized against it in a draw pass and hit-tested against it in a component
421
+ * read one number.
422
+ */
423
+ export function pxPerBpOf(bounds) {
424
+ return ((bounds.screenEndPx - bounds.screenStartPx) / (bounds.end - bounds.start));
377
425
  }
378
426
  /**
379
- * Left edge of the **1bp cell** covering `bp` — for painters that fill a rect
380
- * per base (MAF alignment cells, the alignments pileup's mismatch /
381
- * modification / per-base quality+letter / soft-clip base layers).
427
+ * Left edge of the **1bp cell** covering `bp`, for a painter filling a rect
428
+ * exactly one base wide. A cell floored wider than its base grows from the
429
+ * base's low-coordinate edge instead, leftward on a reversed block, as the
430
+ * alignments pileup's `cellPlacement` does.
382
431
  *
383
432
  * Use this, not `makeBpMapper`, whenever the mark is a cell rather than a point
384
433
  * or a two-edge span. `makeBpMapper(bp)` is the cell's left edge only on a
@@ -395,24 +444,7 @@ export function makeBpMapper(bounds) {
395
444
  * `bpToClipX(pos)`→`bpToClipX(pos+1)` unflipped and mirror via `flipX` — and
396
445
  * gets its own pivot from `writeBpRangeUniforms`.
397
446
  *
398
- * Callers own the cell *width*: it's a per-plugin rule (MAF uses the raw
399
- * bp-scale; the pileup floors at 1px and adds a seam fudge). Only the pivot is
400
- * shared.
401
447
  */
402
- /**
403
- * Screen px one base occupies in this region — the scale factor, unsigned, with
404
- * the block's direction deliberately left out (that lives in `makeBpMapper` and
405
- * `spanLeft`, and folding it in here would make a *scale* carry an orientation).
406
- *
407
- * Shared because it is usually an input to something a second painter has to
408
- * reproduce exactly: a mark sized against it in a draw pass and hit-tested
409
- * against it in a component is two spellings of one number, and the hit target
410
- * silently stops covering the mark if they ever drift. Trivial arithmetic, but
411
- * the drift is not.
412
- */
413
- export function pxPerBpOf(bounds) {
414
- return ((bounds.screenEndPx - bounds.screenStartPx) / (bounds.end - bounds.start));
415
- }
416
448
  export function makeCellLeftMapper(bounds) {
417
449
  const toX = makeBpMapper(bounds);
418
450
  const pxPerBp = pxPerBpOf(bounds);
@@ -429,7 +461,7 @@ export function makeCellLeftMapper(bounds) {
429
461
  *
430
462
  * Prefer this to `makeCellLeftMapper` + a caller-computed width for anything
431
463
  * wider than one base. The pivot in `makeCellLeftMapper` is exactly one base,
432
- * which is right for a 1bp cell and silently wrong for an N-bp span — it
464
+ * which is right for a 1bp cell and wrong for an N-bp span — it
433
465
  * anchors the rect one base from the correct edge and then grows it the wrong
434
466
  * way. `fillBpSpan(bp, bp + 1)` is *identical* to the cell-mapper spelling, so
435
467
  * a per-base painter can use this too and never think about orientation again.
@@ -488,7 +520,7 @@ export function fillBpSpan(ctx, toX, startBp, endBp, top, height, seam = 0) {
488
520
  * `14468.9936` — and rounding the *offset* and then adding such an anchor
489
521
  * returns the anchor's fraction untouched. The result is then not a base at
490
522
  * all, and every caller that indexes one by equality (a mismatch column, a
491
- * coverage bin, the sort-at-this-column anchor) misses silently: the pileup
523
+ * coverage bin, the sort-at-this-column anchor) finds no match: the pileup
492
524
  * offered no SNP submenu over a mismatch it was drawing. Rounding
493
525
  * `whole + fraction + offset` in one step instead fixes that and hands back the
494
526
  * genome-scale addend the paragraph above exists to keep out, so the whole base
@@ -562,3 +594,54 @@ export function bpAtPxExact(px, bounds) {
562
594
  export function regionAtPixel(regions, px) {
563
595
  return regions.find(r => px >= r.screenStartPx && px < r.screenEndPx);
564
596
  }
597
+ /**
598
+ * CSS px a Canvas2D painter adds to the drawn width of a rect whose neighbours
599
+ * abut it. `fillRect` antialiases each edge on its own, so two rects meeting on
600
+ * a fractional column each take partial coverage of it and a hairline of
601
+ * background shows through; abutting GPU quads share an exact clip-space edge
602
+ * and the rasterizer fills it once, so a shader grows no matching pad.
603
+ */
604
+ export const CANVAS_SEAM_PX = 0.8;
605
+ /**
606
+ * Shapes a `CappedPath` holds before it paints and reopens. Chrome's
607
+ * GPU-rasterized canvas, which is desktop Chrome with a GPU and headless Chrome
608
+ * with the GPU blocklist off, silently paints nothing for a path past about
609
+ * 16 MiB: 180,000 discs, 453,000 rects or 931,000 line segments.
610
+ * `pnpm check-canvas-path-limits` drives the painters past it in a real browser.
611
+ */
612
+ const MAX_SHAPES_PER_PATH = 10_000;
613
+ /**
614
+ * One batched Canvas2D path of many shapes, painted in pieces a browser will
615
+ * rasterize. Opens a path on construction; call `add()` before appending each
616
+ * shape and `flush()` to paint what it holds and reopen.
617
+ */
618
+ export class CappedPath {
619
+ shapes = 0;
620
+ ctx;
621
+ paint;
622
+ constructor(ctx, paint) {
623
+ this.ctx = ctx;
624
+ this.paint = paint;
625
+ ctx.beginPath();
626
+ }
627
+ /**
628
+ * True when the path was full and has been painted and reopened, so a
629
+ * polyline must `moveTo` its pen again.
630
+ */
631
+ add() {
632
+ if (this.shapes === MAX_SHAPES_PER_PATH) {
633
+ this.flush();
634
+ this.shapes = 1;
635
+ return true;
636
+ }
637
+ this.shapes++;
638
+ return false;
639
+ }
640
+ flush() {
641
+ if (this.shapes > 0) {
642
+ this.ctx[this.paint]();
643
+ this.ctx.beginPath();
644
+ this.shapes = 0;
645
+ }
646
+ }
647
+ }
@@ -9,9 +9,9 @@ export declare const COLOR_RAMP_LUT_ENTRIES = 256;
9
9
  /**
10
10
  * Upload a 256-entry RGBA colour-ramp LUT as each named pass's 256×1 texture —
11
11
  * the runtime half of the shared ramp mechanism whose shader half is
12
- * `shaders/colorRampLut.slang`. HiC, LD (whose two shader variants are the
13
- * reason this takes a pass list) and wiggle density all put their ramps behind
14
- * their samplers through this one call; each keeps its own scale and its own
15
- * LUT contents.
12
+ * `shaders/colorRampLut.slang`. Called by `createMarkBackend` alone now, for
13
+ * every mark declaring a `texture`: hic, LD's two shader variants and wiggle
14
+ * density all put their ramps behind their samplers through it, each keeping
15
+ * its own scale and its own LUT contents.
16
16
  */
17
- export declare function uploadColorRampLut(hal: GpuHal, ramp: Uint8Array, passIds: readonly string[]): void;
17
+ export declare function uploadColorRampLut(hal: GpuHal, ramp: Uint8Array, passIds: readonly string[], sampler?: string): void;
@@ -9,17 +9,17 @@ export const COLOR_RAMP_LUT_ENTRIES = RAMP_LUT_ENTRIES;
9
9
  /**
10
10
  * Upload a 256-entry RGBA colour-ramp LUT as each named pass's 256×1 texture —
11
11
  * the runtime half of the shared ramp mechanism whose shader half is
12
- * `shaders/colorRampLut.slang`. HiC, LD (whose two shader variants are the
13
- * reason this takes a pass list) and wiggle density all put their ramps behind
14
- * their samplers through this one call; each keeps its own scale and its own
15
- * LUT contents.
12
+ * `shaders/colorRampLut.slang`. Called by `createMarkBackend` alone now, for
13
+ * every mark declaring a `texture`: hic, LD's two shader variants and wiggle
14
+ * density all put their ramps behind their samplers through it, each keeping
15
+ * its own scale and its own LUT contents.
16
16
  */
17
- export function uploadColorRampLut(hal, ramp, passIds) {
17
+ export function uploadColorRampLut(hal, ramp, passIds, sampler) {
18
18
  if (ramp.length !== COLOR_RAMP_LUT_ENTRIES * 4) {
19
19
  throw new Error(`uploadColorRampLut: expected a ${COLOR_RAMP_LUT_ENTRIES}-entry RGBA LUT ` +
20
20
  `(${COLOR_RAMP_LUT_ENTRIES * 4} bytes), got ${ramp.length} bytes`);
21
21
  }
22
22
  for (const passId of passIds) {
23
- hal.uploadTexture(passId, ramp, COLOR_RAMP_LUT_ENTRIES, 1);
23
+ hal.uploadTexture(passId, ramp, COLOR_RAMP_LUT_ENTRIES, 1, sampler);
24
24
  }
25
25
  }
@@ -0,0 +1,14 @@
1
+ import type { ShaderBinding, ShaderSource } from './hal/index.ts';
2
+ export interface ComputePipelineState {
3
+ device: GPUDevice;
4
+ pipeline: GPUComputePipeline;
5
+ bindGroupLayout: GPUBindGroupLayout;
6
+ bindings: readonly ShaderBinding[];
7
+ }
8
+ /**
9
+ * One compute pipeline per kernel, built on first use against the current
10
+ * device and rebuilt after a device loss. Concurrent first callers share the
11
+ * one async build, which is also when the kernel's WGSL is loaded; a failed
12
+ * one is retried by the next caller rather than kept.
13
+ */
14
+ export declare function makeComputePipelineCache(source: Pick<ShaderSource, 'wgsl'>, entryPoint: string, bindings: readonly ShaderBinding[]): (device: GPUDevice) => Promise<ComputePipelineState>;
@@ -0,0 +1,62 @@
1
+ /// <reference types="@webgpu/types" />
2
+ import { onDeviceLost } from './gpuDevice.js';
3
+ import { stageVisibility } from './webgpuUtils.js';
4
+ // Built from the kernel's own reflected binding table rather than restated by
5
+ // the caller, so a mismatch shows up as a validation failure at pipeline
6
+ // creation rather than as a wrong buffer under a right-looking index.
7
+ function makeBindGroupLayout(device, bindings) {
8
+ return device.createBindGroupLayout({
9
+ entries: bindings.map(b => {
10
+ if (b.kind === 'texture' || b.kind === 'sampler') {
11
+ throw new Error(`compute kernel: binding ${b.index} ('${b.name}') is a ${b.kind}, ` +
12
+ `which a buffer-only dispatch does not bind`);
13
+ }
14
+ return {
15
+ binding: b.index,
16
+ visibility: stageVisibility(b.stages),
17
+ buffer: { type: b.kind },
18
+ };
19
+ }),
20
+ });
21
+ }
22
+ /**
23
+ * One compute pipeline per kernel, built on first use against the current
24
+ * device and rebuilt after a device loss. Concurrent first callers share the
25
+ * one async build, which is also when the kernel's WGSL is loaded; a failed
26
+ * one is retried by the next caller rather than kept.
27
+ */
28
+ export function makeComputePipelineCache(source, entryPoint, bindings) {
29
+ let state = null;
30
+ let statePromise = null;
31
+ onDeviceLost(() => {
32
+ state = null;
33
+ statePromise = null;
34
+ });
35
+ return async function ensurePipeline(device) {
36
+ if (state?.device === device) {
37
+ return state;
38
+ }
39
+ if (statePromise) {
40
+ return statePromise;
41
+ }
42
+ statePromise = (async () => {
43
+ try {
44
+ const { WGSL_SOURCE } = await source.wgsl();
45
+ const module = device.createShaderModule({ code: WGSL_SOURCE });
46
+ const bindGroupLayout = makeBindGroupLayout(device, bindings);
47
+ const pipeline = await device.createComputePipelineAsync({
48
+ layout: device.createPipelineLayout({
49
+ bindGroupLayouts: [bindGroupLayout],
50
+ }),
51
+ compute: { module, entryPoint },
52
+ });
53
+ state = { device, pipeline, bindGroupLayout, bindings };
54
+ return state;
55
+ }
56
+ finally {
57
+ statePromise = null;
58
+ }
59
+ })();
60
+ return statePromise;
61
+ };
62
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * A contract family — the `<family>` in the `[jbrowse <family> contract]`
3
+ * prefix every contract check in the tree reports under.
4
+ * `config/jest/console.js` matches `\w+`, so a new one reaches the test gate
5
+ * without touching it.
6
+ */
7
+ export type ContractFamily = 'display' | 'session' | 'figure';
8
+ export interface ContractReport {
9
+ family: ContractFamily;
10
+ message: string;
11
+ /** what armed the channel, so a host can say why it is showing this */
12
+ armedBy: string;
13
+ }
14
+ /**
15
+ * Whether the checks should run at all.
16
+ *
17
+ * Read it where a check costs something to run — the `MutationObserver` a live
18
+ * figure installs, the per-frame payload walk in `installUpload`. A check whose
19
+ * cost is a `WeakSet` lookup should run unconditionally and report through
20
+ * {@link reportContractViolation} instead, so that arming the channel late
21
+ * still surfaces what it found.
22
+ */
23
+ export declare function contractReportsOn(): boolean;
24
+ /**
25
+ * Turn the channel on in a production build, saying what turned it on.
26
+ *
27
+ * The reason is not decoration: a notification that appears in an app the
28
+ * reader did not build has to answer "why am I seeing this" in its own text, or
29
+ * it reads as the app being broken rather than as a plugin being under
30
+ * development. First caller wins, so the earliest evidence is the one quoted.
31
+ */
32
+ export declare function enableContractReports(reason: string): void;
33
+ /**
34
+ * Where a host puts contract violations that reach a user — a session
35
+ * notification in the apps. Installing one drains whatever was found before the
36
+ * host existed, and the disposer only clears the sink it installed, so a
37
+ * session torn down after its replacement was built does not take the live
38
+ * one's sink with it.
39
+ */
40
+ export declare function setContractReportSink(fn: (report: ContractReport) => void): () => void;
41
+ /**
42
+ * Report a violation of an ordering contract no type can state.
43
+ *
44
+ * In tree this is the `console.error` it has always been, and the jest gate is
45
+ * what listens. Out of tree it is the only thing that reaches a plugin author
46
+ * at all: their display runs in a production build of somebody's app, which
47
+ * strips nothing here, and a violation surfaces the moment anything arms the
48
+ * channel — a `localStorage` flag, a plugin loaded from localhost, or a site
49
+ * whose config asks for it.
50
+ *
51
+ * `agent-docs/reference/ARCHITECTURAL_LIMITS.md` §"Ordering is the contract" is
52
+ * the register of what reports here.
53
+ */
54
+ export declare function reportContractViolation(family: ContractFamily, message: string): void;
@@ -0,0 +1,112 @@
1
+ const DEVELOPER_MODE_KEY = 'jbrowseDeveloperMode';
2
+ // The flag a plugin author can set on any deployed JBrowse without owning it or
3
+ // asking anyone, which is the population this whole channel is for.
4
+ function storageFlag() {
5
+ try {
6
+ return typeof localStorage === 'undefined' ||
7
+ localStorage.getItem(DEVELOPER_MODE_KEY) === null
8
+ ? undefined
9
+ : `localStorage.${DEVELOPER_MODE_KEY} is set`;
10
+ }
11
+ catch {
12
+ // storage can be denied outright, and a diagnostic is not the thing to take
13
+ // the app down with
14
+ return undefined;
15
+ }
16
+ }
17
+ // Module scope for the same reason `numberGrouping` is: a check is called from
18
+ // a mixin factory, an MST action and a React effect that cannot share a
19
+ // closure, and each realm resolves this once at startup rather than through an
20
+ // observable a worker could not see.
21
+ let armedBy = process.env.NODE_ENV === 'production'
22
+ ? storageFlag()
23
+ : 'this is a development build';
24
+ let sink;
25
+ const unlogged = [];
26
+ const undelivered = [];
27
+ const PENDING_LIMIT = 20;
28
+ function remember(queue, found) {
29
+ if (queue.length < PENDING_LIMIT) {
30
+ queue.push(found);
31
+ }
32
+ }
33
+ /**
34
+ * Whether the checks should run at all.
35
+ *
36
+ * Read it where a check costs something to run — the `MutationObserver` a live
37
+ * figure installs, the per-frame payload walk in `installUpload`. A check whose
38
+ * cost is a `WeakSet` lookup should run unconditionally and report through
39
+ * {@link reportContractViolation} instead, so that arming the channel late
40
+ * still surfaces what it found.
41
+ */
42
+ export function contractReportsOn() {
43
+ return armedBy !== undefined;
44
+ }
45
+ /**
46
+ * Turn the channel on in a production build, saying what turned it on.
47
+ *
48
+ * The reason is not decoration: a notification that appears in an app the
49
+ * reader did not build has to answer "why am I seeing this" in its own text, or
50
+ * it reads as the app being broken rather than as a plugin being under
51
+ * development. First caller wins, so the earliest evidence is the one quoted.
52
+ */
53
+ export function enableContractReports(reason) {
54
+ armedBy ??= reason;
55
+ for (const found of unlogged.splice(0)) {
56
+ emit(found, armedBy);
57
+ }
58
+ }
59
+ /**
60
+ * Where a host puts contract violations that reach a user — a session
61
+ * notification in the apps. Installing one drains whatever was found before the
62
+ * host existed, and the disposer only clears the sink it installed, so a
63
+ * session torn down after its replacement was built does not take the live
64
+ * one's sink with it.
65
+ */
66
+ export function setContractReportSink(fn) {
67
+ sink = fn;
68
+ if (armedBy !== undefined) {
69
+ for (const found of undelivered.splice(0)) {
70
+ fn({ ...found, armedBy });
71
+ }
72
+ }
73
+ return () => {
74
+ if (sink === fn) {
75
+ sink = undefined;
76
+ }
77
+ };
78
+ }
79
+ function emit(found, armed) {
80
+ // `console.error`, never a throw: an error escaping `afterAttach` is read by
81
+ // the session loader as an invalid track and the display is silently dropped,
82
+ // which would hide the very violation being reported. The prefix is what
83
+ // `config/jest/console.js` buffers and `contractGate.js` fails a test on.
84
+ console.error(`[jbrowse ${found.family} contract] ${found.message}`);
85
+ if (sink === undefined) {
86
+ remember(undelivered, found);
87
+ }
88
+ else {
89
+ sink({ ...found, armedBy: armed });
90
+ }
91
+ }
92
+ /**
93
+ * Report a violation of an ordering contract no type can state.
94
+ *
95
+ * In tree this is the `console.error` it has always been, and the jest gate is
96
+ * what listens. Out of tree it is the only thing that reaches a plugin author
97
+ * at all: their display runs in a production build of somebody's app, which
98
+ * strips nothing here, and a violation surfaces the moment anything arms the
99
+ * channel — a `localStorage` flag, a plugin loaded from localhost, or a site
100
+ * whose config asks for it.
101
+ *
102
+ * `agent-docs/reference/ARCHITECTURAL_LIMITS.md` §"Ordering is the contract" is
103
+ * the register of what reports here.
104
+ */
105
+ export function reportContractViolation(family, message) {
106
+ if (armedBy === undefined) {
107
+ remember(unlogged, { family, message });
108
+ }
109
+ else {
110
+ emit({ family, message }, armedBy);
111
+ }
112
+ }
@@ -1,6 +1,5 @@
1
1
  import type { CoverageBandBuffers } from './coverageBandBuffers.ts';
2
2
  import type { InstancePass } from './instancePass.ts';
3
- export { coverageBandBuffers } from './coverageBandBuffers.ts';
4
3
  export type { CoverageBandBuffers } from './coverageBandBuffers.ts';
5
4
  export declare const COVERAGE_BAND_UNIFORMS_SIZE_BYTES = 112;
6
5
  /**
@@ -15,10 +14,10 @@ export interface CoverageBandModBuffer {
15
14
  /**
16
15
  * One draw layer of the coverage band, and the id of the GPU pass that draws it.
17
16
  *
18
- * The band is the same five marks wherever it appears — a display either has a
17
+ * The band is the same six marks wherever it appears — a display either has a
19
18
  * layer's data or does not, and no display reorders them.
20
19
  */
21
- export type CoverageLayerId = 'coverage' | 'snpCov' | 'modCov' | 'interbase' | 'indicator';
20
+ export type CoverageLayerId = 'coverage' | 'snpCov' | 'modCov' | 'interbase' | 'indicator' | 'clipStrip';
22
21
  /**
23
22
  * The band's z-order, back to front: the depth bars, the SNP slices stacked
24
23
  * inside them, the modification slices stacked on those, the interbase histogram
@@ -47,6 +46,12 @@ export declare const COVERAGE_BAND_LAYER_ORDER: readonly CoverageLayerId[];
47
46
  */
48
47
  export declare function orderCoverageBandLayers<T>(byId: Record<CoverageLayerId, T | undefined>): (T & ({} | null))[];
49
48
  export declare const COVERAGE_BAR_PASS: InstancePass<Pick<CoverageBandBuffers, 'coveragePackedBuffer'>>;
49
+ /**
50
+ * The clip strips over the depth bars the domain cut, off the bar pass's own
51
+ * buffer and last in the order, since every layer between stacks inside the
52
+ * bar and would paint over a strip drawn with it.
53
+ */
54
+ export declare const COVERAGE_CLIP_PASS: InstancePass<Pick<CoverageBandBuffers, 'coveragePackedBuffer'>>;
50
55
  export declare const COVERAGE_SNP_PASS: InstancePass<Pick<CoverageBandBuffers, 'snpPackedBuffer'>>;
51
56
  export declare const COVERAGE_MOD_PASS: InstancePass<CoverageBandModBuffer>;
52
57
  export declare const COVERAGE_INTERBASE_PASS: InstancePass<Pick<CoverageBandBuffers, 'interbasePackedBuffer'>>;
@@ -81,7 +86,7 @@ export interface CoverageBandUniformValues {
81
86
  covHeight: number;
82
87
  covYOffset: number;
83
88
  covTop: number;
84
- /** The region's own peak depth, which is what the buffers' `relDepth` is a fraction of. */
89
+ /** The region's peak depth; the buffers' `relDepth` is a fraction of it. */
85
90
  regionMaxDepth: number;
86
91
  /** The display's autoscaled depth domain. `undefined` max = not resolved yet. */
87
92
  domainMin: number;
@@ -99,9 +104,9 @@ export interface CoverageBandUniformValues {
99
104
  * Fill the coverage band's uniform buffer. Total-write (the generated packer),
100
105
  * so a field left out is a compile error rather than last frame's value.
101
106
  *
102
- * `hpZero` is derived here rather than at each call site because getting it
103
- * wrong is a silently wrong band, not a broken one: it MUST be 0, since the HP
104
- * math materializes +inf as `1/hpZero` to stop the compiler folding the hi/lo
105
- * split it exists to preserve.
107
+ * `hpZero` is derived here rather than at each call site because a wrong value
108
+ * draws a plausible but wrong band and raises no error: it MUST be 0, since the
109
+ * HP math adds it to a clamp floor to keep that floor off the compiler's
110
+ * constant table and so stop it folding the hi/lo split away.
106
111
  */
107
112
  export declare function writeCoverageBandUniforms(buf: ArrayBuffer, v: CoverageBandUniformValues): void;
@@ -1,10 +1,10 @@
1
1
  import * as coverageBarShader from './shaders/coverageBar.generated.js';
2
+ import * as coverageClipShader from './shaders/coverageClip.generated.js';
2
3
  import * as coverageIndicatorShader from './shaders/coverageIndicator.generated.js';
3
4
  import * as coverageInterbaseShader from './shaders/coverageInterbase.generated.js';
4
5
  import * as coverageModShader from './shaders/coverageMod.generated.js';
5
6
  import * as coverageSnpShader from './shaders/coverageSnp.generated.js';
6
7
  import { slangPass } from './slangPass.js';
7
- export { coverageBandBuffers } from './coverageBandBuffers.js';
8
8
  export const COVERAGE_BAND_UNIFORMS_SIZE_BYTES = coverageBarShader.UNIFORMS_SIZE_BYTES;
9
9
  /**
10
10
  * The band's z-order, back to front: the depth bars, the SNP slices stacked
@@ -27,6 +27,7 @@ export const COVERAGE_BAND_LAYER_ORDER = [
27
27
  'modCov',
28
28
  'interbase',
29
29
  'indicator',
30
+ 'clipStrip',
30
31
  ];
31
32
  /**
32
33
  * Whatever a display attaches to each band layer — a GPU pass, a Canvas2D
@@ -50,6 +51,15 @@ export const COVERAGE_BAR_PASS = {
50
51
  ...slangPass({ id: 'coverage', mod: coverageBarShader }),
51
52
  pack: data => data.coveragePackedBuffer,
52
53
  };
54
+ /**
55
+ * The clip strips over the depth bars the domain cut, off the bar pass's own
56
+ * buffer and last in the order, since every layer between stacks inside the
57
+ * bar and would paint over a strip drawn with it.
58
+ */
59
+ export const COVERAGE_CLIP_PASS = {
60
+ ...slangPass({ id: 'clipStrip', mod: coverageClipShader }),
61
+ pack: data => data.coveragePackedBuffer,
62
+ };
53
63
  export const COVERAGE_SNP_PASS = {
54
64
  ...slangPass({ id: 'snpCov', mod: coverageSnpShader }),
55
65
  pack: data => data.snpPackedBuffer,
@@ -70,10 +80,10 @@ export const COVERAGE_INDICATOR_PASS = {
70
80
  * Fill the coverage band's uniform buffer. Total-write (the generated packer),
71
81
  * so a field left out is a compile error rather than last frame's value.
72
82
  *
73
- * `hpZero` is derived here rather than at each call site because getting it
74
- * wrong is a silently wrong band, not a broken one: it MUST be 0, since the HP
75
- * math materializes +inf as `1/hpZero` to stop the compiler folding the hi/lo
76
- * split it exists to preserve.
83
+ * `hpZero` is derived here rather than at each call site because a wrong value
84
+ * draws a plausible but wrong band and raises no error: it MUST be 0, since the
85
+ * HP math adds it to a clamp floor to keep that floor off the compiler's
86
+ * constant table and so stop it folding the hi/lo split away.
77
87
  */
78
88
  export function writeCoverageBandUniforms(buf, v) {
79
89
  const { domainMax, colors } = v;
@@ -7,9 +7,8 @@
7
7
  *
8
8
  * Structural rather than nominal, and named after the layout rather than after
9
9
  * either display: the alignments worker's `CoverageUploadData` and the MAF
10
- * worker's `MafCoverageRegion` both satisfy it, which is what lets the passes
11
- * in `coverageBand.ts` carry their own packers instead of each plugin
12
- * restating four field reads.
10
+ * worker's `MafCoverageRegion` both satisfy it, so the passes in
11
+ * `coverageBand.ts` carry the packers and no plugin restates four field reads.
13
12
  *
14
13
  * Its own module, apart from the GPU passes in `coverageBand.ts`: a state
15
14
  * model reaching for just this shape has no reason to statically pull in
@@ -22,9 +21,3 @@ export interface CoverageBandBuffers {
22
21
  interbasePackedBuffer: ArrayBuffer;
23
22
  indicatorPackedBuffer: ArrayBuffer;
24
23
  }
25
- /**
26
- * Just the band's four buffers out of a wider per-region payload — the field set
27
- * stated once, so a display carrying them into its own upload payload cannot
28
- * spell three of them.
29
- */
30
- export declare function coverageBandBuffers(src: CoverageBandBuffers): CoverageBandBuffers;
@@ -1,13 +1 @@
1
- /**
2
- * Just the band's four buffers out of a wider per-region payload — the field set
3
- * stated once, so a display carrying them into its own upload payload cannot
4
- * spell three of them.
5
- */
6
- export function coverageBandBuffers(src) {
7
- return {
8
- coveragePackedBuffer: src.coveragePackedBuffer,
9
- snpPackedBuffer: src.snpPackedBuffer,
10
- interbasePackedBuffer: src.interbasePackedBuffer,
11
- indicatorPackedBuffer: src.indicatorPackedBuffer,
12
- };
13
- }
1
+ export {};