@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.
- package/esm/RenderCanvas.d.ts +2 -2
- package/esm/RenderLifecycleMixin.d.ts +52 -20
- package/esm/RenderLifecycleMixin.js +89 -23
- package/esm/canvas2dUtils.d.ts +90 -23
- package/esm/canvas2dUtils.js +119 -36
- package/esm/colorRampLut.d.ts +5 -5
- package/esm/colorRampLut.js +6 -6
- package/esm/computePipeline.d.ts +14 -0
- package/esm/computePipeline.js +62 -0
- package/esm/contractReports.d.ts +54 -0
- package/esm/contractReports.js +112 -0
- package/esm/coverageBand.d.ts +13 -8
- package/esm/coverageBand.js +15 -5
- package/esm/coverageBandBuffers.d.ts +2 -9
- package/esm/coverageBandBuffers.js +1 -13
- package/esm/createRenderingBackend.d.ts +14 -18
- package/esm/createRenderingBackend.js +4 -2
- package/esm/displayPhase.d.ts +83 -104
- package/esm/displayPhase.js +42 -82
- package/esm/encodeMemo.d.ts +14 -0
- package/esm/encodeMemo.js +48 -0
- package/esm/gpuContextLostError.d.ts +30 -0
- package/esm/gpuContextLostError.js +40 -0
- package/esm/gpuDevice.d.ts +29 -10
- package/esm/gpuDevice.js +35 -16
- package/esm/graphicsCapabilities.d.ts +27 -19
- package/esm/graphicsCapabilities.js +40 -18
- package/esm/hal/createHal.d.ts +4 -5
- package/esm/hal/createHal.js +14 -4
- package/esm/hal/deviceGpuCache.d.ts +25 -30
- package/esm/hal/deviceGpuCache.js +88 -97
- package/esm/hal/gpuHalBase.d.ts +5 -4
- package/esm/hal/gpuHalBase.js +25 -14
- package/esm/hal/index.d.ts +2 -2
- package/esm/hal/index.js +1 -1
- package/esm/hal/mockHal.d.ts +15 -10
- package/esm/hal/mockHal.js +31 -18
- package/esm/hal/oomReporter.d.ts +7 -0
- package/esm/hal/oomReporter.js +10 -0
- package/esm/hal/passIds.d.ts +8 -7
- package/esm/hal/passIds.js +11 -10
- package/esm/hal/regionRegistry.d.ts +0 -1
- package/esm/hal/regionRegistry.js +3 -15
- package/esm/hal/types.d.ts +55 -18
- package/esm/hal/webgl2Hal.d.ts +23 -6
- package/esm/hal/webgl2Hal.js +161 -155
- package/esm/hal/webgpuHal.d.ts +29 -13
- package/esm/hal/webgpuHal.js +221 -153
- package/esm/installUpload.d.ts +16 -3
- package/esm/installUpload.js +13 -41
- package/esm/instanceCache.d.ts +10 -7
- package/esm/instanceCache.js +14 -15
- package/esm/instancePass.d.ts +2 -1
- package/esm/mapUploadSync.d.ts +2 -10
- package/esm/mapUploadSync.js +2 -3
- package/esm/marks/barMark.d.ts +30 -0
- package/esm/marks/barMark.js +149 -0
- package/esm/marks/colorFill.d.ts +17 -0
- package/esm/marks/colorFill.js +26 -0
- package/esm/marks/drawAgainstHit.d.ts +113 -0
- package/esm/marks/drawAgainstHit.js +407 -0
- package/esm/marks/ellipseDistance.d.ts +10 -0
- package/esm/marks/ellipseDistance.js +136 -0
- package/esm/marks/glyphPaint.d.ts +36 -0
- package/esm/marks/glyphPaint.js +77 -0
- package/esm/marks/index.d.ts +33 -0
- package/esm/marks/index.js +20 -0
- package/esm/marks/lineMark.d.ts +37 -0
- package/esm/marks/lineMark.js +416 -0
- package/esm/marks/linkMark.d.ts +76 -0
- package/esm/marks/linkMark.js +585 -0
- package/esm/marks/markBackend.d.ts +118 -0
- package/esm/marks/markBackend.js +196 -0
- package/esm/marks/markHit.d.ts +32 -0
- package/esm/marks/markHit.js +61 -0
- package/esm/marks/markInk.d.ts +18 -0
- package/esm/marks/markInk.js +71 -0
- package/esm/marks/markPaint.d.ts +14 -0
- package/esm/marks/markPaint.js +32 -0
- package/esm/marks/markPlan.d.ts +25 -0
- package/esm/marks/markPlan.js +20 -0
- package/esm/marks/markRamp.d.ts +72 -0
- package/esm/marks/markRamp.js +197 -0
- package/esm/marks/nearestMarkHit.d.ts +55 -0
- package/esm/marks/nearestMarkHit.js +158 -0
- package/esm/marks/pathRecorder.d.ts +14 -0
- package/esm/marks/pathRecorder.js +80 -0
- package/esm/marks/pointMark.d.ts +42 -0
- package/esm/marks/pointMark.js +125 -0
- package/esm/marks/rowLane.d.ts +39 -0
- package/esm/marks/rowLane.js +41 -0
- package/esm/marks/rowSpanIndex.d.ts +29 -0
- package/esm/marks/rowSpanIndex.js +141 -0
- package/esm/marks/rowTable.d.ts +41 -0
- package/esm/marks/rowTable.js +75 -0
- package/esm/marks/ruleMark.d.ts +21 -0
- package/esm/marks/ruleMark.js +91 -0
- package/esm/marks/spanMark.d.ts +42 -0
- package/esm/marks/spanMark.js +81 -0
- package/esm/marks/types.d.ts +261 -0
- package/esm/marks/types.js +175 -0
- package/esm/marks/valueScale.d.ts +23 -0
- package/esm/marks/valueScale.js +11 -0
- package/esm/namedReactions.d.ts +3 -4
- package/esm/namedReactions.js +3 -4
- package/esm/perRegionRenderingBackend.d.ts +21 -3
- package/esm/perRegionRenderingBackend.js +37 -3
- package/esm/regionDataMap.d.ts +2 -2
- package/esm/regionDataMap.js +25 -23
- package/esm/renderBlock.d.ts +14 -0
- package/esm/renderBlock.js +25 -0
- package/esm/renderingBackendBase.d.ts +20 -14
- package/esm/renderingBackendBase.js +12 -7
- package/esm/scoreScale.d.ts +27 -0
- package/esm/scoreScale.js +88 -0
- package/esm/shaders/barMark.generated.d.ts +3 -0
- package/esm/shaders/barMark.generated.js +7 -0
- package/esm/shaders/barMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/barMark.glsl.generated.js +4 -0
- package/esm/shaders/barMark.iface.generated.d.ts +90 -0
- package/esm/shaders/barMark.iface.generated.js +205 -0
- package/esm/shaders/barMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/barMark.wgsl.generated.js +3 -0
- package/esm/shaders/capsule.js.generated.d.ts +1 -0
- package/esm/shaders/capsule.js.generated.js +11 -0
- package/esm/shaders/clipStrip.generated.d.ts +2 -0
- package/esm/shaders/clipStrip.generated.js +4 -0
- package/esm/shaders/clipStrip.js.generated.d.ts +1 -0
- package/esm/shaders/clipStrip.js.generated.js +21 -0
- package/esm/shaders/colorRampLut.js.generated.d.ts +1 -0
- package/esm/shaders/colorRampLut.js.generated.js +17 -0
- package/esm/shaders/coverageBar.generated.d.ts +2 -3
- package/esm/shaders/coverageBar.generated.js +4 -3
- package/esm/shaders/coverageBar.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageBar.glsl.generated.js +4 -0
- package/esm/shaders/coverageBar.iface.generated.js +1 -1
- package/esm/shaders/coverageBar.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageBar.wgsl.generated.js +3 -0
- package/esm/shaders/coverageClip.generated.d.ts +3 -0
- package/esm/shaders/coverageClip.generated.js +7 -0
- package/esm/shaders/coverageClip.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageClip.glsl.generated.js +4 -0
- package/esm/shaders/coverageClip.iface.generated.d.ts +85 -0
- package/esm/shaders/coverageClip.iface.generated.js +114 -0
- package/esm/shaders/coverageClip.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageClip.wgsl.generated.js +3 -0
- package/esm/shaders/coverageIndicator.generated.d.ts +2 -3
- package/esm/shaders/coverageIndicator.generated.js +4 -3
- package/esm/shaders/coverageIndicator.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageIndicator.glsl.generated.js +4 -0
- package/esm/shaders/coverageIndicator.iface.generated.js +1 -1
- package/esm/shaders/coverageIndicator.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageIndicator.wgsl.generated.js +3 -0
- package/esm/shaders/coverageInterbase.generated.d.ts +2 -3
- package/esm/shaders/coverageInterbase.generated.js +4 -3
- package/esm/shaders/coverageInterbase.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageInterbase.glsl.generated.js +4 -0
- package/esm/shaders/coverageInterbase.iface.generated.js +1 -1
- package/esm/shaders/coverageInterbase.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageInterbase.wgsl.generated.js +3 -0
- package/esm/shaders/coverageMod.generated.d.ts +2 -3
- package/esm/shaders/coverageMod.generated.js +4 -3
- package/esm/shaders/coverageMod.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageMod.glsl.generated.js +4 -0
- package/esm/shaders/coverageMod.iface.generated.js +1 -1
- package/esm/shaders/coverageMod.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageMod.wgsl.generated.js +3 -0
- package/esm/shaders/coverageSnp.generated.d.ts +2 -3
- package/esm/shaders/coverageSnp.generated.js +4 -3
- package/esm/shaders/coverageSnp.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageSnp.glsl.generated.js +4 -0
- package/esm/shaders/coverageSnp.iface.generated.js +1 -1
- package/esm/shaders/coverageSnp.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageSnp.wgsl.generated.js +3 -0
- package/esm/shaders/curveDistance.js.generated.d.ts +5 -0
- package/esm/shaders/curveDistance.js.generated.js +87 -0
- package/esm/shaders/hpmath.js.generated.d.ts +2 -1
- package/esm/shaders/hpmath.js.generated.js +5 -2
- package/esm/shaders/lineCenterMark.generated.d.ts +3 -0
- package/esm/shaders/lineCenterMark.generated.js +7 -0
- package/esm/shaders/lineCenterMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/lineCenterMark.glsl.generated.js +4 -0
- package/esm/shaders/lineCenterMark.iface.generated.d.ts +104 -0
- package/esm/shaders/lineCenterMark.iface.generated.js +237 -0
- package/esm/shaders/lineCenterMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/lineCenterMark.wgsl.generated.js +3 -0
- package/esm/shaders/lineCommon.generated.d.ts +2 -0
- package/esm/shaders/lineCommon.generated.js +4 -0
- package/esm/shaders/lineStepMark.generated.d.ts +3 -0
- package/esm/shaders/lineStepMark.generated.js +7 -0
- package/esm/shaders/lineStepMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/lineStepMark.glsl.generated.js +4 -0
- package/esm/shaders/lineStepMark.iface.generated.d.ts +98 -0
- package/esm/shaders/lineStepMark.iface.generated.js +225 -0
- package/esm/shaders/lineStepMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/lineStepMark.wgsl.generated.js +3 -0
- package/esm/shaders/linkMark.consts.generated.d.ts +14 -0
- package/esm/shaders/linkMark.consts.generated.js +16 -0
- package/esm/shaders/linkMark.generated.d.ts +4 -0
- package/esm/shaders/linkMark.generated.js +8 -0
- package/esm/shaders/linkMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/linkMark.glsl.generated.js +4 -0
- package/esm/shaders/linkMark.iface.generated.d.ts +142 -0
- package/esm/shaders/linkMark.iface.generated.js +1829 -0
- package/esm/shaders/linkMark.js.generated.d.ts +7 -0
- package/esm/shaders/linkMark.js.generated.js +159 -0
- package/esm/shaders/linkMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/linkMark.wgsl.generated.js +3 -0
- package/esm/shaders/markColor.generated.d.ts +9 -0
- package/esm/shaders/markColor.generated.js +11 -0
- package/esm/shaders/pointGlyph.js.generated.d.ts +2 -0
- package/esm/shaders/pointGlyph.js.generated.js +15 -0
- package/esm/shaders/pointMark.consts.generated.d.ts +7 -0
- package/esm/shaders/pointMark.consts.generated.js +9 -0
- package/esm/shaders/pointMark.generated.d.ts +4 -0
- package/esm/shaders/pointMark.generated.js +8 -0
- package/esm/shaders/pointMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/pointMark.glsl.generated.js +4 -0
- package/esm/shaders/pointMark.iface.generated.d.ts +98 -0
- package/esm/shaders/pointMark.iface.generated.js +219 -0
- package/esm/shaders/pointMark.js.generated.d.ts +3 -0
- package/esm/shaders/pointMark.js.generated.js +93 -0
- package/esm/shaders/pointMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/pointMark.wgsl.generated.js +3 -0
- package/esm/shaders/rowRect.generated.d.ts +0 -1
- package/esm/shaders/rowRect.generated.js +0 -1
- package/esm/shaders/rowTable.generated.d.ts +1 -0
- package/esm/shaders/rowTable.generated.js +3 -0
- package/esm/shaders/rowTable.js.generated.d.ts +5 -0
- package/esm/shaders/rowTable.js.generated.js +29 -0
- package/esm/shaders/scoreScale.generated.d.ts +2 -0
- package/esm/shaders/scoreScale.generated.js +4 -0
- package/esm/shaders/scoreScale.js.generated.d.ts +1 -0
- package/esm/shaders/scoreScale.js.generated.js +50 -23
- package/esm/shaders/spanMark.generated.d.ts +3 -0
- package/esm/shaders/spanMark.generated.js +7 -0
- package/esm/shaders/spanMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/spanMark.glsl.generated.js +4 -0
- package/esm/shaders/spanMark.iface.generated.d.ts +81 -0
- package/esm/shaders/spanMark.iface.generated.js +215 -0
- package/esm/shaders/spanMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/spanMark.wgsl.generated.js +3 -0
- package/esm/sharedBackendKey.d.ts +18 -0
- package/esm/{keyedRenderingBackend.js → sharedBackendKey.js} +5 -0
- package/esm/slangPass.d.ts +18 -11
- package/esm/slangPass.js +12 -4
- package/esm/useGraphicsCapabilities.d.ts +1 -1
- package/esm/useGraphicsCapabilities.js +1 -1
- package/esm/useRenderingBackend.d.ts +13 -13
- package/esm/useRenderingBackend.js +58 -20
- package/esm/webgpuUtils.d.ts +3 -11
- package/esm/webgpuUtils.js +12 -33
- package/package.json +32 -7
- package/src/shaders/antialias.slang +46 -0
- package/src/shaders/arcHull.test.ts +267 -0
- package/src/shaders/barMark.generated.ts +11 -0
- package/src/shaders/barMark.glsl.generated.ts +6 -0
- package/src/shaders/barMark.iface.generated.ts +285 -0
- package/src/shaders/barMark.slang +167 -0
- package/src/shaders/barMark.wgsl.generated.ts +4 -0
- package/src/shaders/capsule.js.generated.ts +14 -0
- package/src/shaders/capsule.slang +12 -4
- package/src/shaders/clipStrip.generated.ts +6 -0
- package/src/shaders/clipStrip.js.generated.ts +22 -0
- package/src/shaders/clipStrip.slang +34 -0
- package/src/shaders/clipStrip.test.ts +39 -0
- package/src/shaders/colorPack.slang +5 -1
- package/src/shaders/colorRampLut.js.generated.ts +22 -0
- package/src/shaders/colorRampLut.slang +15 -1
- package/src/shaders/coverageBand.slang +64 -32
- package/src/shaders/coverageBar.generated.ts +6 -5
- package/src/shaders/coverageBar.glsl.generated.ts +6 -0
- package/src/shaders/coverageBar.iface.generated.ts +1 -1
- package/src/shaders/coverageBar.slang +10 -10
- package/src/shaders/coverageBar.wgsl.generated.ts +4 -0
- package/src/shaders/coverageClip.generated.ts +11 -0
- package/src/shaders/coverageClip.glsl.generated.ts +6 -0
- package/src/shaders/coverageClip.iface.generated.ts +172 -0
- package/src/shaders/coverageClip.slang +38 -0
- package/src/shaders/coverageClip.wgsl.generated.ts +4 -0
- package/src/shaders/coverageIndicator.generated.ts +6 -5
- package/src/shaders/coverageIndicator.glsl.generated.ts +6 -0
- package/src/shaders/coverageIndicator.iface.generated.ts +1 -1
- package/src/shaders/coverageIndicator.wgsl.generated.ts +4 -0
- package/src/shaders/coverageInterbase.generated.ts +6 -5
- package/src/shaders/coverageInterbase.glsl.generated.ts +6 -0
- package/src/shaders/coverageInterbase.iface.generated.ts +1 -1
- package/src/shaders/coverageInterbase.wgsl.generated.ts +4 -0
- package/src/shaders/coverageMod.generated.ts +6 -5
- package/src/shaders/coverageMod.glsl.generated.ts +6 -0
- package/src/shaders/coverageMod.iface.generated.ts +1 -1
- package/src/shaders/coverageMod.wgsl.generated.ts +4 -0
- package/src/shaders/coverageSnp.generated.ts +6 -5
- package/src/shaders/coverageSnp.glsl.generated.ts +6 -0
- package/src/shaders/coverageSnp.iface.generated.ts +1 -1
- package/src/shaders/coverageSnp.wgsl.generated.ts +4 -0
- package/src/shaders/curveDistance.js.generated.ts +91 -0
- package/src/shaders/curveDistance.slang +265 -0
- package/src/shaders/hpClampFloor.test.ts +87 -0
- package/src/shaders/hpmath.js.generated.ts +6 -2
- package/src/shaders/hpmath.slang +100 -48
- package/src/shaders/insetValueScale.test.ts +67 -0
- package/src/shaders/lineCenterMark.generated.ts +11 -0
- package/src/shaders/lineCenterMark.glsl.generated.ts +6 -0
- package/src/shaders/lineCenterMark.iface.generated.ts +328 -0
- package/src/shaders/lineCenterMark.slang +127 -0
- package/src/shaders/lineCenterMark.wgsl.generated.ts +4 -0
- package/src/shaders/lineCommon.generated.ts +6 -0
- package/src/shaders/lineCommon.slang +102 -0
- package/src/shaders/lineStepMark.generated.ts +11 -0
- package/src/shaders/lineStepMark.glsl.generated.ts +6 -0
- package/src/shaders/lineStepMark.iface.generated.ts +311 -0
- package/src/shaders/lineStepMark.slang +125 -0
- package/src/shaders/lineStepMark.wgsl.generated.ts +4 -0
- package/src/shaders/linkMark.consts.generated.ts +30 -0
- package/src/shaders/linkMark.generated.ts +12 -0
- package/src/shaders/linkMark.glsl.generated.ts +6 -0
- package/src/shaders/linkMark.iface.generated.ts +1954 -0
- package/src/shaders/linkMark.js.generated.ts +167 -0
- package/src/shaders/linkMark.slang +439 -0
- package/src/shaders/linkMark.wgsl.generated.ts +4 -0
- package/src/shaders/markColor.generated.ts +20 -0
- package/src/shaders/markColor.slang +128 -0
- package/src/shaders/pointGlyph.js.generated.ts +20 -0
- package/src/shaders/pointGlyph.slang +23 -7
- package/src/shaders/pointGlyphPad.test.ts +242 -0
- package/src/shaders/pointMark.consts.generated.ts +16 -0
- package/src/shaders/pointMark.generated.ts +12 -0
- package/src/shaders/pointMark.glsl.generated.ts +6 -0
- package/src/shaders/pointMark.iface.generated.ts +304 -0
- package/src/shaders/pointMark.js.generated.ts +99 -0
- package/src/shaders/pointMark.slang +227 -0
- package/src/shaders/pointMark.wgsl.generated.ts +4 -0
- package/src/shaders/rowRect.generated.ts +0 -2
- package/src/shaders/rowRect.slang +39 -58
- package/src/shaders/rowTable.generated.ts +4 -0
- package/src/shaders/rowTable.js.generated.ts +37 -0
- package/src/shaders/rowTable.slang +98 -0
- package/src/shaders/scoreScale.generated.ts +6 -0
- package/src/shaders/scoreScale.js.generated.ts +48 -23
- package/src/shaders/scoreScale.slang +49 -55
- package/src/shaders/sdEllipse.test.ts +211 -0
- package/src/shaders/spanMark.generated.ts +11 -0
- package/src/shaders/spanMark.glsl.generated.ts +6 -0
- package/src/shaders/spanMark.iface.generated.ts +289 -0
- package/src/shaders/spanMark.slang +77 -0
- package/src/shaders/spanMark.wgsl.generated.ts +4 -0
- package/src/shaders/valueScale.slang +26 -0
- package/src/shaders/wideCircleLeg.test.ts +85 -0
- package/esm/globalRenderingBackend.d.ts +0 -90
- package/esm/globalRenderingBackend.js +0 -53
- package/esm/keyedRenderingBackend.d.ts +0 -41
|
@@ -1,120 +1,111 @@
|
|
|
1
1
|
/// <reference types="@webgpu/types" />
|
|
2
|
+
import { STANDARD_BLEND_STATE, stageVisibility, toGpuVertexFormat, } from '../webgpuUtils.js';
|
|
3
|
+
// A device's layouts and pipelines, shared by every WebGPUHal on it. Held per
|
|
4
|
+
// module copy rather than on the `globalThis` cell: a second bundled copy
|
|
5
|
+
// builds a duplicate set, never a wrong one, since WebGPU compares layouts
|
|
6
|
+
// structurally.
|
|
7
|
+
const perDevice = new WeakMap();
|
|
2
8
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* that linked it, and each display owns a context, so nothing there is
|
|
8
|
-
* shareable. WebGPU inverts that — `gpuDevice.ts` hands every display one
|
|
9
|
-
* device, and a `GPURenderPipeline` is a device object — and until this module
|
|
10
|
-
* the HAL kept building per-display copies anyway. Ten alignments tracks
|
|
11
|
-
* compiled 230 pipelines for 23 distinct programs.
|
|
12
|
-
*
|
|
13
|
-
* **The key is the descriptor object, and that is what makes it correct.** A
|
|
14
|
-
* plugin's pass list is a module-level const (`ALIGNMENTS_PASSES`) and
|
|
15
|
-
* `slangPass` reads `wgslSource` off a generated module const, so every display
|
|
16
|
-
* of a type hands the HAL the *same* `PipelineDescriptor` objects by reference.
|
|
17
|
-
* Identity therefore means "same shader, same layout, same blend, same
|
|
18
|
-
* topology" without comparing any of them, and two passes that merely share a
|
|
19
|
-
* `.slang` shape module (MAF and multi-row both draw `rowRect`) get separate
|
|
20
|
-
* entries because `slangPass` built them separate objects. The **sample count**
|
|
21
|
-
* is the one pipeline input the descriptor cannot express, so it is the inner
|
|
22
|
-
* key; see the `pipelines` field.
|
|
23
|
-
*
|
|
24
|
-
* The one field of a pipeline that is not on the descriptor is the uniform
|
|
25
|
-
* size, and it cannot make two HALs disagree here:
|
|
26
|
-
* `createUniformOnlyBindGroupLayout` declares no `minBindingSize`, so the
|
|
27
|
-
* layout — and thus the pipeline built against it — is the same whatever a
|
|
28
|
-
* display's `uniformByteSize` is. The size reaches the GPU through the bind
|
|
29
|
-
* group's `size` and the dynamic offset, both of which stay per-HAL.
|
|
30
|
-
*
|
|
31
|
-
* Per copy of this module rather than on the `globalThis` cell, for the reason
|
|
32
|
-
* `createHal.ts` gives for `warnedSoftwareRasterizer`: a second bundled copy
|
|
33
|
-
* builds a second set, which costs a duplicate and never a wrong answer.
|
|
34
|
-
* Layouts compare structurally in WebGPU, so a bind group from one copy is
|
|
35
|
-
* valid against a pipeline from the other.
|
|
9
|
+
* A render pass's bind-group layout, read off its shader's reflected table:
|
|
10
|
+
* each binding visible to exactly the stages that read it, so the layout
|
|
11
|
+
* cannot disagree with the shader about which stage reads what. The uniform
|
|
12
|
+
* block takes a dynamic offset into the HAL's ring.
|
|
36
13
|
*/
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
binding: 2,
|
|
52
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
53
|
-
texture: { sampleType: 'float' },
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
binding: 3,
|
|
57
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
58
|
-
sampler: { type: 'filtering' },
|
|
59
|
-
},
|
|
60
|
-
],
|
|
14
|
+
export function bindGroupLayoutEntries(bindings) {
|
|
15
|
+
return bindings.map((b) => {
|
|
16
|
+
const at = { binding: b.index, visibility: stageVisibility(b.stages) };
|
|
17
|
+
switch (b.kind) {
|
|
18
|
+
case 'uniform':
|
|
19
|
+
return { ...at, buffer: { type: 'uniform', hasDynamicOffset: true } };
|
|
20
|
+
case 'texture':
|
|
21
|
+
return { ...at, texture: { sampleType: 'float' } };
|
|
22
|
+
case 'sampler':
|
|
23
|
+
return { ...at, sampler: { type: 'filtering' } };
|
|
24
|
+
default:
|
|
25
|
+
throw new Error(`a render pass binds no ${b.kind}, and '${b.name}' is one at ` +
|
|
26
|
+
`binding ${b.index}`);
|
|
27
|
+
}
|
|
61
28
|
});
|
|
29
|
+
}
|
|
30
|
+
function gpuBlendState(bs) {
|
|
31
|
+
// WebGPU rejects any factor but 'one' under max and min, which ignore them.
|
|
32
|
+
// Alpha takes the same equation, as webgl2Hal's applyBlendState does.
|
|
33
|
+
const max = { srcFactor: 'one', dstFactor: 'one', operation: 'max' };
|
|
34
|
+
const min = { srcFactor: 'one', dstFactor: 'one', operation: 'min' };
|
|
35
|
+
const behind = { srcFactor: 'one-minus-dst-alpha', dstFactor: 'one' };
|
|
36
|
+
return bs.op === 'max'
|
|
37
|
+
? { color: max, alpha: max }
|
|
38
|
+
: bs.op === 'min'
|
|
39
|
+
? { color: min, alpha: min }
|
|
40
|
+
: bs.op === 'behind'
|
|
41
|
+
? { color: behind, alpha: behind }
|
|
42
|
+
: {
|
|
43
|
+
color: { srcFactor: bs.srcFactor, dstFactor: bs.dstFactor },
|
|
44
|
+
alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha' },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export function pipelineRecipe(desc, wgslSource, sampleCount) {
|
|
62
48
|
return {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
49
|
+
wgslSource,
|
|
50
|
+
bindGroupLayout: bindGroupLayoutEntries(desc.bindings),
|
|
51
|
+
vertexBuffer: {
|
|
52
|
+
arrayStride: desc.instanceStride,
|
|
53
|
+
stepMode: 'instance',
|
|
54
|
+
attributes: desc.vertexAttributes.map((attr, i) => ({
|
|
55
|
+
shaderLocation: i,
|
|
56
|
+
offset: attr.offsetBytes,
|
|
57
|
+
format: toGpuVertexFormat(attr),
|
|
58
|
+
})),
|
|
59
|
+
},
|
|
60
|
+
blend: desc.blend
|
|
61
|
+
? desc.blendState
|
|
62
|
+
? gpuBlendState(desc.blendState)
|
|
63
|
+
: STANDARD_BLEND_STATE
|
|
64
|
+
: undefined,
|
|
65
|
+
topology: desc.topology ?? 'triangle-list',
|
|
66
|
+
sampleCount,
|
|
71
67
|
};
|
|
72
68
|
}
|
|
73
69
|
function cacheFor(device) {
|
|
74
70
|
let entry = perDevice.get(device);
|
|
75
71
|
if (!entry) {
|
|
76
|
-
entry = { layouts:
|
|
72
|
+
entry = { layouts: new Map(), pipelines: new Map() };
|
|
77
73
|
perDevice.set(device, entry);
|
|
78
74
|
}
|
|
79
75
|
return entry;
|
|
80
76
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
77
|
+
export function getPassLayout(device, entries) {
|
|
78
|
+
const { layouts } = cacheFor(device);
|
|
79
|
+
const key = JSON.stringify(entries);
|
|
80
|
+
let layout = layouts.get(key);
|
|
81
|
+
if (!layout) {
|
|
82
|
+
const bindGroupLayout = device.createBindGroupLayout({ entries });
|
|
83
|
+
layout = {
|
|
84
|
+
bindGroupLayout,
|
|
85
|
+
pipelineLayout: device.createPipelineLayout({
|
|
86
|
+
bindGroupLayouts: [bindGroupLayout],
|
|
87
|
+
}),
|
|
88
|
+
};
|
|
89
|
+
layouts.set(key, layout);
|
|
90
|
+
}
|
|
91
|
+
return layout;
|
|
91
92
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
export function getOrBuildPipeline(device, desc, sampleCount, build) {
|
|
100
|
-
const { layouts, pipelines } = cacheFor(device);
|
|
101
|
-
let bySampleCount = pipelines.get(desc);
|
|
102
|
-
if (!bySampleCount) {
|
|
103
|
-
bySampleCount = new Map();
|
|
104
|
-
pipelines.set(desc, bySampleCount);
|
|
93
|
+
export function getOrBuildPipeline(device, recipe, build) {
|
|
94
|
+
const { pipelines } = cacheFor(device);
|
|
95
|
+
const { wgslSource, ...rest } = recipe;
|
|
96
|
+
let bySource = pipelines.get(wgslSource);
|
|
97
|
+
if (!bySource) {
|
|
98
|
+
bySource = new Map();
|
|
99
|
+
pipelines.set(wgslSource, bySource);
|
|
105
100
|
}
|
|
106
|
-
|
|
101
|
+
const key = JSON.stringify(rest);
|
|
102
|
+
let pipeline = bySource.get(key);
|
|
107
103
|
if (!pipeline) {
|
|
108
|
-
pipeline = build(
|
|
109
|
-
|
|
104
|
+
pipeline = build(recipe);
|
|
105
|
+
bySource.set(key, pipeline);
|
|
110
106
|
}
|
|
111
107
|
return pipeline;
|
|
112
108
|
}
|
|
113
|
-
/**
|
|
114
|
-
* Drop every device's entry. Tests only — nothing in the app invalidates this
|
|
115
|
-
* cache, because losing the device is what invalidates it (see
|
|
116
|
-
* {@link getDeviceLayouts}).
|
|
117
|
-
*/
|
|
118
109
|
export function resetDeviceGpuCacheForTests(device) {
|
|
119
110
|
perDevice.delete(device);
|
|
120
111
|
}
|
package/esm/hal/gpuHalBase.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { OomReporter } from './oomReporter.ts';
|
|
2
2
|
import { RegionRegistry } from './regionRegistry.ts';
|
|
3
|
-
import type { PipelineDescriptor, TextureBinding } from './types.ts';
|
|
3
|
+
import type { PipelineDescriptor, TextureBinding, TextureSource } from './types.ts';
|
|
4
4
|
/**
|
|
5
5
|
* The device ceilings the shared upload shells refuse past. WebGPU asks the
|
|
6
6
|
* device, WebGL2 has no such parameter for buffers and carries its own constant
|
|
@@ -31,6 +31,7 @@ export declare abstract class GpuHalBase<Buf extends {
|
|
|
31
31
|
protected descriptors: Map<string, PipelineDescriptor>;
|
|
32
32
|
protected regions: RegionRegistry<Buf>;
|
|
33
33
|
protected oom: OomReporter;
|
|
34
|
+
readonly uniformByteSize: number;
|
|
34
35
|
protected disposed: boolean;
|
|
35
36
|
constructor(descriptors: PipelineDescriptor[], halName: string);
|
|
36
37
|
protected abstract limits(): HalLimits;
|
|
@@ -41,7 +42,7 @@ export declare abstract class GpuHalBase<Buf extends {
|
|
|
41
42
|
* reached for a pass that declares a binding, and only within
|
|
42
43
|
* `maxTextureDimensionPx`.
|
|
43
44
|
*/
|
|
44
|
-
protected abstract createTexture(passId: string, binding: TextureBinding, data:
|
|
45
|
+
protected abstract createTexture(passId: string, binding: TextureBinding, data: TextureSource, width: number, height: number): void;
|
|
45
46
|
/** Release this HAL's own GPU objects. Runs exactly once, from `dispose`. */
|
|
46
47
|
protected abstract releaseResources(): void;
|
|
47
48
|
setErrorHandler(handler: (error: Error) => void): void;
|
|
@@ -49,7 +50,7 @@ export declare abstract class GpuHalBase<Buf extends {
|
|
|
49
50
|
getBufferCount(regionKey: number, passId: string): number;
|
|
50
51
|
deleteBuffer(regionKey: number, passId: string): void;
|
|
51
52
|
deleteRegion(regionKey: number): void;
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
uploadTexture(passId: string, data: TextureSource, width: number, height: number, sampler?: string): void;
|
|
54
|
+
protected textureBinding(passId: string, sampler?: string): TextureBinding;
|
|
54
55
|
dispose(): void;
|
|
55
56
|
}
|
package/esm/hal/gpuHalBase.js
CHANGED
|
@@ -19,11 +19,13 @@ export class GpuHalBase {
|
|
|
19
19
|
descriptors;
|
|
20
20
|
regions;
|
|
21
21
|
oom;
|
|
22
|
+
uniformByteSize;
|
|
22
23
|
// Guards dispose() against double invocation (pagehide + React cleanup can
|
|
23
24
|
// both fire).
|
|
24
25
|
disposed = false;
|
|
25
26
|
constructor(descriptors, halName) {
|
|
26
27
|
this.descriptors = new Map(descriptors.map(d => [d.id, d]));
|
|
28
|
+
this.uniformByteSize = Math.max(0, ...descriptors.map(d => d.uniformByteSize));
|
|
27
29
|
this.oom = new OomReporter(halName);
|
|
28
30
|
this.regions = new RegionRegistry(buf => {
|
|
29
31
|
this.destroyBuffer(buf);
|
|
@@ -55,22 +57,31 @@ export class GpuHalBase {
|
|
|
55
57
|
deleteRegion(regionKey) {
|
|
56
58
|
this.regions.deleteRegion(regionKey);
|
|
57
59
|
}
|
|
58
|
-
|
|
59
|
-
this.
|
|
60
|
+
uploadTexture(passId, data, width, height, sampler) {
|
|
61
|
+
const binding = this.textureBinding(passId, sampler);
|
|
62
|
+
const { maxTextureDimensionPx } = this.limits();
|
|
63
|
+
if (width > maxTextureDimensionPx || height > maxTextureDimensionPx) {
|
|
64
|
+
this.oom.report(`This region is too large to render on this GPU — zoom in. (texture ${width}×${height} exceeds max texture size ${maxTextureDimensionPx})`);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
this.createTexture(passId, binding, data, width, height);
|
|
68
|
+
}
|
|
60
69
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
textureBinding(passId, sampler) {
|
|
71
|
+
const textures = this.descriptors.get(passId)?.textures ?? [];
|
|
72
|
+
const binding = sampler === undefined
|
|
73
|
+
? textures.length === 1
|
|
74
|
+
? textures[0]
|
|
75
|
+
: undefined
|
|
76
|
+
: textures.find(t => t.name === sampler);
|
|
77
|
+
if (!binding) {
|
|
78
|
+
const names = textures.map(t => `'${t.name}'`).join(', ');
|
|
79
|
+
const has = names ? `samples ${names}` : 'samples no texture';
|
|
80
|
+
throw new Error(sampler === undefined
|
|
81
|
+
? `uploadTexture: pass '${passId}' ${has}; name the sampler this texture is for`
|
|
82
|
+
: `uploadTexture: pass '${passId}' has no sampler '${sampler}'; it ${has}`);
|
|
73
83
|
}
|
|
84
|
+
return binding;
|
|
74
85
|
}
|
|
75
86
|
dispose() {
|
|
76
87
|
if (!this.disposed) {
|
package/esm/hal/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { createGpuHal } from './createHal.ts';
|
|
2
|
-
export { MockHal } from './mockHal.ts';
|
|
2
|
+
export { MOCK_SHADER_SOURCE, MockHal } from './mockHal.ts';
|
|
3
3
|
export { assertUniquePassIds } from './passIds.ts';
|
|
4
4
|
export { WebGL2Hal } from './webgl2Hal.ts';
|
|
5
5
|
export { WebGPUHal } from './webgpuHal.ts';
|
|
6
6
|
export type { GpuHalOptions } from './createHal.ts';
|
|
7
|
-
export type { BlendState, VertexAttributeLayout, GpuHal, PipelineDescriptor, SampleCount, ShaderBinding, TextureBinding, } from './types.ts';
|
|
7
|
+
export type { BlendState, VertexAttributeLayout, GpuHal, PipelineDescriptor, SampleCount, ShaderBinding, ShaderSource, ShaderStage, TextureBinding, TextureSource, } from './types.ts';
|
package/esm/hal/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createGpuHal } from './createHal.js';
|
|
2
|
-
export { MockHal } from './mockHal.js';
|
|
2
|
+
export { MOCK_SHADER_SOURCE, MockHal } from './mockHal.js';
|
|
3
3
|
export { assertUniquePassIds } from './passIds.js';
|
|
4
4
|
export { WebGL2Hal } from './webgl2Hal.js';
|
|
5
5
|
export { WebGPUHal } from './webgpuHal.js';
|
package/esm/hal/mockHal.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { GpuHalBase } from './gpuHalBase.ts';
|
|
2
|
-
import type { GpuHal, PipelineDescriptor, TextureBinding } from './types.ts';
|
|
2
|
+
import type { GpuHal, PipelineDescriptor, ShaderSource, TextureBinding, TextureSource } from './types.ts';
|
|
3
|
+
/** Text for a pass built only for a `MockHal`, which never loads it. */
|
|
4
|
+
export declare const MOCK_SHADER_SOURCE: ShaderSource;
|
|
3
5
|
export interface MockCall {
|
|
4
6
|
method: string;
|
|
5
7
|
args: unknown[];
|
|
@@ -17,7 +19,7 @@ export interface MockRect {
|
|
|
17
19
|
/**
|
|
18
20
|
* One draw, with the state that was in force when it was issued — the clip, and
|
|
19
21
|
* which `writeUniforms` it reads. `null` scissor/viewport means unclipped, the
|
|
20
|
-
* full canvas,
|
|
22
|
+
* full canvas, the state both HALs must restore after a `clearScissor` /
|
|
21
23
|
* `clearViewport`.
|
|
22
24
|
*
|
|
23
25
|
* `uniformWrite` indexes {@link MockHal.getUniformWritesF32}, or is `-1` when
|
|
@@ -32,13 +34,15 @@ export interface MockRect {
|
|
|
32
34
|
* does an immediate `bufferSubData` into one UBO. They agree only while a
|
|
33
35
|
* renderer writes then draws, which is the convention every renderer in tree
|
|
34
36
|
* follows and nothing enforces: batching the writes and then issuing the draws
|
|
35
|
-
* is right on WebGL2 and Canvas2D and
|
|
36
|
-
*
|
|
37
|
+
* is right on WebGL2 and Canvas2D and wrong on WebGPU, where the draws read the
|
|
38
|
+
* last write. `uniformWrite` lets a backend test pin its renderer's pairing.
|
|
37
39
|
*/
|
|
38
40
|
export interface MockDraw {
|
|
39
41
|
passId: string;
|
|
40
42
|
regionKey: number;
|
|
41
43
|
bufferPassId: string | undefined;
|
|
44
|
+
/** The vertex count the draw asked for, its descriptor's where it asked for none. */
|
|
45
|
+
verticesPerInstance: number;
|
|
42
46
|
scissor: MockRect | null;
|
|
43
47
|
viewport: MockRect | null;
|
|
44
48
|
uniformWrite: number;
|
|
@@ -59,8 +63,8 @@ export declare class MockHal extends GpuHalBase<MockBuffer> implements GpuHal {
|
|
|
59
63
|
* rect without re-issuing a full-canvas one, so every draw after it went on
|
|
60
64
|
* being clipped to the previous block while WebGL2 drew them unclipped — right
|
|
61
65
|
* on Canvas2D, right on WebGL2, wrong on WebGPU alone. Nothing in tree clears
|
|
62
|
-
* mid-frame today,
|
|
63
|
-
*
|
|
66
|
+
* mid-frame today, so no test caught it. Recording the effective clip per draw
|
|
67
|
+
* makes that assertable.
|
|
64
68
|
*/
|
|
65
69
|
private scissor;
|
|
66
70
|
private viewport;
|
|
@@ -90,7 +94,7 @@ export declare class MockHal extends GpuHalBase<MockBuffer> implements GpuHal {
|
|
|
90
94
|
};
|
|
91
95
|
protected destroyBuffer(): void;
|
|
92
96
|
private textures;
|
|
93
|
-
protected createTexture(passId: string,
|
|
97
|
+
protected createTexture(passId: string, binding: TextureBinding, data: TextureSource, width: number, height: number): void;
|
|
94
98
|
protected releaseResources(): void;
|
|
95
99
|
private record;
|
|
96
100
|
errorHandler: ((error: Error) => void) | null;
|
|
@@ -99,15 +103,15 @@ export declare class MockHal extends GpuHalBase<MockBuffer> implements GpuHal {
|
|
|
99
103
|
x: number;
|
|
100
104
|
y: number;
|
|
101
105
|
};
|
|
106
|
+
releaseRenderTargets(): void;
|
|
102
107
|
uploadBuffer(regionKey: number, passId: string, data: ArrayBuffer | ArrayBufferView, count: number): void;
|
|
103
108
|
deleteBuffer(regionKey: number, passId: string): void;
|
|
104
109
|
deleteRegion(regionKey: number): void;
|
|
105
|
-
pruneRegions(active: Iterable<number>): void;
|
|
106
110
|
private noteReplaced;
|
|
107
111
|
private noteRegionReplaced;
|
|
108
112
|
writeUniforms(data: ArrayBuffer): void;
|
|
109
113
|
beginFrame(clearR: number, clearG: number, clearB: number, clearA?: number): void;
|
|
110
|
-
drawPass(passId: string, regionKey: number, bufferPassId?: string): void;
|
|
114
|
+
drawPass(passId: string, regionKey: number, bufferPassId?: string, verticesPerInstance?: number): void;
|
|
111
115
|
private assertRegistered;
|
|
112
116
|
endFrame(): void;
|
|
113
117
|
setScissor(x: number, y: number, w: number, h: number): void;
|
|
@@ -121,7 +125,8 @@ export declare class MockHal extends GpuHalBase<MockBuffer> implements GpuHal {
|
|
|
121
125
|
getUniformWritesF32(): Float32Array<ArrayBuffer>[];
|
|
122
126
|
getUniformWritesU32(): Uint32Array<ArrayBuffer>[];
|
|
123
127
|
getBuffer(regionKey: number, passId: string): MockBuffer | undefined;
|
|
124
|
-
|
|
128
|
+
/** What the pass's `sampler` samples, named as `uploadTexture` names it. */
|
|
129
|
+
getTexture(passId: string, sampler?: string): TextureSource | undefined;
|
|
125
130
|
callsOf(method: string): MockCall[];
|
|
126
131
|
/**
|
|
127
132
|
* Every draw of the frame with the state it went out under, in order — the
|
package/esm/hal/mockHal.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { getDpr } from '../canvas2dUtils.js';
|
|
2
2
|
import { GpuHalBase } from './gpuHalBase.js';
|
|
3
3
|
import { assertUniquePassIds } from './passIds.js';
|
|
4
|
+
/** Text for a pass built only for a `MockHal`, which never loads it. */
|
|
5
|
+
export const MOCK_SHADER_SOURCE = {
|
|
6
|
+
wgsl: () => Promise.resolve({ WGSL_SOURCE: '' }),
|
|
7
|
+
glsl: () => Promise.resolve({ GLSL_VERTEX: '', GLSL_FRAGMENT: '' }),
|
|
8
|
+
};
|
|
9
|
+
function textureKey(passId, sampler) {
|
|
10
|
+
return `${passId}\u0000${sampler}`;
|
|
11
|
+
}
|
|
4
12
|
export class MockHal extends GpuHalBase {
|
|
5
13
|
calls = [];
|
|
6
14
|
// Every write of the frame, in order, not just the last. A renderer that
|
|
@@ -23,8 +31,8 @@ export class MockHal extends GpuHalBase {
|
|
|
23
31
|
* rect without re-issuing a full-canvas one, so every draw after it went on
|
|
24
32
|
* being clipped to the previous block while WebGL2 drew them unclipped — right
|
|
25
33
|
* on Canvas2D, right on WebGL2, wrong on WebGPU alone. Nothing in tree clears
|
|
26
|
-
* mid-frame today,
|
|
27
|
-
*
|
|
34
|
+
* mid-frame today, so no test caught it. Recording the effective clip per draw
|
|
35
|
+
* makes that assertable.
|
|
28
36
|
*/
|
|
29
37
|
scissor = null;
|
|
30
38
|
viewport = null;
|
|
@@ -76,9 +84,10 @@ export class MockHal extends GpuHalBase {
|
|
|
76
84
|
// reason the real HALs keep their texture: a test asserting which LUT a pass
|
|
77
85
|
// samples needs the bytes, not the byteLength the call log records.
|
|
78
86
|
textures = new Map();
|
|
79
|
-
createTexture(passId,
|
|
80
|
-
|
|
81
|
-
this.
|
|
87
|
+
createTexture(passId, binding, data, width, height) {
|
|
88
|
+
const bytes = data instanceof Uint8Array;
|
|
89
|
+
this.textures.set(textureKey(passId, binding.name), bytes ? data.slice() : data);
|
|
90
|
+
this.record('uploadTexture', passId, bytes ? data.byteLength : 'canvas', width, height, binding.name);
|
|
82
91
|
}
|
|
83
92
|
releaseResources() {
|
|
84
93
|
this.record('dispose');
|
|
@@ -94,6 +103,9 @@ export class MockHal extends GpuHalBase {
|
|
|
94
103
|
this.record('setErrorHandler');
|
|
95
104
|
}
|
|
96
105
|
resize(width, height) {
|
|
106
|
+
if (this.disposed) {
|
|
107
|
+
return { x: getDpr(), y: getDpr() };
|
|
108
|
+
}
|
|
97
109
|
this.record('resize', width, height);
|
|
98
110
|
// The real HALs report the scale their backing store actually got, and
|
|
99
111
|
// every device-px rect a renderer builds comes from this — so a mock
|
|
@@ -101,6 +113,9 @@ export class MockHal extends GpuHalBase {
|
|
|
101
113
|
// the unclamped answer, which is what a mock canvas of any size would get.
|
|
102
114
|
return { x: getDpr(), y: getDpr() };
|
|
103
115
|
}
|
|
116
|
+
releaseRenderTargets() {
|
|
117
|
+
this.record('releaseRenderTargets');
|
|
118
|
+
}
|
|
104
119
|
// The overrides below log and then defer to the base's shells, so the buffer
|
|
105
120
|
// lifecycle a test observes (delete-before-count, prune) is the same code both
|
|
106
121
|
// real HALs run rather than a twin that can drift out of parity.
|
|
@@ -119,16 +134,6 @@ export class MockHal extends GpuHalBase {
|
|
|
119
134
|
this.noteRegionReplaced(regionKey);
|
|
120
135
|
super.deleteRegion(regionKey);
|
|
121
136
|
}
|
|
122
|
-
pruneRegions(active) {
|
|
123
|
-
const activeSet = new Set(active);
|
|
124
|
-
this.record('pruneRegions', [...activeSet]);
|
|
125
|
-
for (const regionKey of this.drawnThisFrame.keys()) {
|
|
126
|
-
if (!activeSet.has(regionKey)) {
|
|
127
|
-
this.noteRegionReplaced(regionKey);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
super.pruneRegions(activeSet);
|
|
131
|
-
}
|
|
132
137
|
noteReplaced(regionKey, passId) {
|
|
133
138
|
if (this.frameOpen && this.drawnThisFrame.get(regionKey)?.has(passId)) {
|
|
134
139
|
this.replacedWhileDrawnLog.push(`${regionKey}:${passId}`);
|
|
@@ -168,11 +173,15 @@ export class MockHal extends GpuHalBase {
|
|
|
168
173
|
// `bufferPassId` is checked too: `drawPass(a, key, b)` runs pass `a`'s
|
|
169
174
|
// pipeline over pass `b`'s buffer, and every such pair in tree names two
|
|
170
175
|
// registered passes (canvas's chevron over line, continuation over rect).
|
|
171
|
-
drawPass(passId, regionKey, bufferPassId) {
|
|
176
|
+
drawPass(passId, regionKey, bufferPassId, verticesPerInstance) {
|
|
172
177
|
this.assertRegistered(passId, 'passId');
|
|
173
178
|
if (bufferPassId !== undefined) {
|
|
174
179
|
this.assertRegistered(bufferPassId, 'bufferPassId');
|
|
175
180
|
}
|
|
181
|
+
const missing = (this.descriptors.get(passId)?.textures ?? []).some(t => !this.textures.has(textureKey(passId, t.name)));
|
|
182
|
+
if (missing) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
176
185
|
this.record('drawPass', passId, regionKey, bufferPassId);
|
|
177
186
|
// The buffer the draw reads, which `bufferPassId` renames — that is the
|
|
178
187
|
// resource a later upload in this frame would be replacing under it.
|
|
@@ -187,6 +196,8 @@ export class MockHal extends GpuHalBase {
|
|
|
187
196
|
passId,
|
|
188
197
|
regionKey,
|
|
189
198
|
bufferPassId,
|
|
199
|
+
verticesPerInstance: verticesPerInstance ??
|
|
200
|
+
this.descriptors.get(passId).verticesPerInstance,
|
|
190
201
|
scissor: this.scissor && { ...this.scissor },
|
|
191
202
|
viewport: this.viewport && { ...this.viewport },
|
|
192
203
|
uniformWrite: this.uniformWrites.length - 1,
|
|
@@ -244,8 +255,10 @@ export class MockHal extends GpuHalBase {
|
|
|
244
255
|
getBuffer(regionKey, passId) {
|
|
245
256
|
return this.regions.get(regionKey, passId);
|
|
246
257
|
}
|
|
247
|
-
|
|
248
|
-
|
|
258
|
+
/** What the pass's `sampler` samples, named as `uploadTexture` names it. */
|
|
259
|
+
getTexture(passId, sampler) {
|
|
260
|
+
const { name } = this.textureBinding(passId, sampler);
|
|
261
|
+
return this.textures.get(textureKey(passId, name));
|
|
249
262
|
}
|
|
250
263
|
callsOf(method) {
|
|
251
264
|
return this.calls.filter(c => c.method === method);
|
package/esm/hal/oomReporter.d.ts
CHANGED
|
@@ -12,4 +12,11 @@ export declare class OomReporter {
|
|
|
12
12
|
constructor(hal: string);
|
|
13
13
|
setHandler(handler: (error: Error) => void): void;
|
|
14
14
|
report(message: string): void;
|
|
15
|
+
/**
|
|
16
|
+
* Report an error the HAL has already classified, for a failure whose remedy
|
|
17
|
+
* is not `report`'s "zoom in". Kept separate so the classification stays with
|
|
18
|
+
* the caller that knows it — flagging every over-limit allocation as a context
|
|
19
|
+
* loss would offer "Use Canvas2D" for a view that only needs zooming.
|
|
20
|
+
*/
|
|
21
|
+
reportClassified(error: Error): void;
|
|
15
22
|
}
|
package/esm/hal/oomReporter.js
CHANGED
|
@@ -19,4 +19,14 @@ export class OomReporter {
|
|
|
19
19
|
console.error(`[${this.hal}] ${message}`);
|
|
20
20
|
this.handler?.(new Error(message));
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Report an error the HAL has already classified, for a failure whose remedy
|
|
24
|
+
* is not `report`'s "zoom in". Kept separate so the classification stays with
|
|
25
|
+
* the caller that knows it — flagging every over-limit allocation as a context
|
|
26
|
+
* loss would offer "Use Canvas2D" for a view that only needs zooming.
|
|
27
|
+
*/
|
|
28
|
+
reportClassified(error) {
|
|
29
|
+
console.error(`[${this.hal}] ${error.message}`);
|
|
30
|
+
this.handler?.(error);
|
|
31
|
+
}
|
|
22
32
|
}
|
package/esm/hal/passIds.d.ts
CHANGED
|
@@ -2,13 +2,14 @@ import type { PipelineDescriptor } from './types.ts';
|
|
|
2
2
|
/**
|
|
3
3
|
* Throw if two passes in one display's registry share an `id`.
|
|
4
4
|
*
|
|
5
|
-
* A pass id
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* backends while Canvas2D
|
|
5
|
+
* A pass id names a slot: the descriptor a draw of that id uses, its instance
|
|
6
|
+
* buffer per region, and its texture. Compiled pipelines and programs are keyed
|
|
7
|
+
* by content instead, so a second id over one shader costs no compile. A
|
|
8
|
+
* duplicate id collides the slot: the later descriptor answers every draw of
|
|
9
|
+
* it, both passes upload to one buffer so the last write wins, and whichever
|
|
10
|
+
* shader has the larger stride reads off the end of it. No validation error, no
|
|
11
|
+
* throw, no failing test — just wrong pixels on the GPU backends while Canvas2D
|
|
12
|
+
* keeps drawing correctly.
|
|
12
13
|
*
|
|
13
14
|
* Nothing structural stops it. A display's pass list is concatenated from
|
|
14
15
|
* several registries (`ALIGNMENTS_PASSES` merges three plus a standalone
|
package/esm/hal/passIds.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Throw if two passes in one display's registry share an `id`.
|
|
3
3
|
*
|
|
4
|
-
* A pass id
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* backends while Canvas2D
|
|
4
|
+
* A pass id names a slot: the descriptor a draw of that id uses, its instance
|
|
5
|
+
* buffer per region, and its texture. Compiled pipelines and programs are keyed
|
|
6
|
+
* by content instead, so a second id over one shader costs no compile. A
|
|
7
|
+
* duplicate id collides the slot: the later descriptor answers every draw of
|
|
8
|
+
* it, both passes upload to one buffer so the last write wins, and whichever
|
|
9
|
+
* shader has the larger stride reads off the end of it. No validation error, no
|
|
10
|
+
* throw, no failing test — just wrong pixels on the GPU backends while Canvas2D
|
|
11
|
+
* keeps drawing correctly.
|
|
11
12
|
*
|
|
12
13
|
* Nothing structural stops it. A display's pass list is concatenated from
|
|
13
14
|
* several registries (`ALIGNMENTS_PASSES` merges three plus a standalone
|
|
@@ -29,8 +30,8 @@ export function assertUniquePassIds(passes) {
|
|
|
29
30
|
}
|
|
30
31
|
if (duplicates.size > 0) {
|
|
31
32
|
throw new Error(`duplicate pass id(s) ${[...duplicates].map(id => `'${id}'`).join(', ')}` +
|
|
32
|
-
` — a pass id keys
|
|
33
|
-
` passes sharing one draw each other's instances
|
|
34
|
-
` shader. Rename one.`);
|
|
33
|
+
` — a pass id keys the descriptor, the instance buffer and the` +
|
|
34
|
+
` texture, so two passes sharing one draw each other's instances` +
|
|
35
|
+
` through one shader. Rename one.`);
|
|
35
36
|
}
|
|
36
37
|
}
|