@driftengine/core 3.63.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +122 -0
- package/NOTICE +20 -0
- package/README.md +1 -1
- package/dist/core/loop.js +18 -2
- package/dist/core/storage.js +5 -0
- package/dist/geometry/meshBuilder.d.ts +1 -1
- package/dist/geometry/meshBuilder.js +6 -2
- package/dist/index.d.ts +69 -4
- package/dist/index.js +112 -2
- package/dist/input/input.js +6 -1
- package/dist/math/exact.d.ts +13 -3
- package/dist/math/exact.js +68 -3
- package/dist/math/frustum.d.ts +17 -2
- package/dist/math/frustum.js +24 -0
- package/dist/render/backend/api.d.ts +34 -1
- package/dist/render/backend/api.js +22 -1
- package/dist/render/backend/budget.d.ts +7 -6
- package/dist/render/backend/budget.js +7 -6
- package/dist/render/backend/createRenderer.d.ts +57 -0
- package/dist/render/backend/createRenderer.js +51 -2
- package/dist/render/backend/materialChanges.d.ts +41 -0
- package/dist/render/backend/materialChanges.js +38 -0
- package/dist/render/backend/select.js +8 -0
- package/dist/render/backend/webgl2/renderer.d.ts +80 -1
- package/dist/render/backend/webgl2/renderer.js +208 -10
- package/dist/render/backend/webgpu/buffers.d.ts +20 -1
- package/dist/render/backend/webgpu/buffers.js +116 -58
- package/dist/render/backend/webgpu/fieldCompose.d.ts +156 -0
- package/dist/render/backend/webgpu/fieldCompose.js +396 -0
- package/dist/render/backend/webgpu/giFieldPass.d.ts +66 -0
- package/dist/render/backend/webgpu/giFieldPass.js +137 -0
- package/dist/render/backend/webgpu/gpuDrivenPass.d.ts +728 -0
- package/dist/render/backend/webgpu/gpuDrivenPass.js +2473 -0
- package/dist/render/backend/webgpu/linePass.d.ts +4 -14
- package/dist/render/backend/webgpu/linePass.js +4 -33
- package/dist/render/backend/webgpu/probeBake.d.ts +148 -0
- package/dist/render/backend/webgpu/probeBake.js +493 -0
- package/dist/render/backend/webgpu/renderer.d.ts +379 -24
- package/dist/render/backend/webgpu/renderer.js +1369 -76
- package/dist/render/backend/webgpu/scatterPass.js +15 -1
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +19 -9
- package/dist/render/backend/webgpu/surfaceTexturePass.js +58 -32
- package/dist/render/causticsRenderer.d.ts +3 -1
- package/dist/render/causticsRenderer.js +4 -1
- package/dist/render/depthConvention.d.ts +12 -0
- package/dist/render/depthConvention.js +14 -0
- package/dist/render/deviceFeatures.d.ts +32 -0
- package/dist/render/deviceFeatures.js +41 -0
- package/dist/render/fog.d.ts +79 -0
- package/dist/render/fog.js +138 -0
- package/dist/render/frame/alias.d.ts +30 -0
- package/dist/render/frame/alias.js +61 -0
- package/dist/render/frame/deps.d.ts +37 -0
- package/dist/render/frame/deps.js +122 -0
- package/dist/render/frame/flushGraph.d.ts +43 -0
- package/dist/render/frame/flushGraph.js +84 -0
- package/dist/render/frame/graphSchedule.d.ts +49 -0
- package/dist/render/frame/graphSchedule.js +120 -0
- package/dist/render/frame/index.d.ts +15 -0
- package/dist/render/frame/index.js +8 -0
- package/dist/render/frame/lifetime.d.ts +24 -0
- package/dist/render/frame/lifetime.js +36 -0
- package/dist/render/frame/passTimings.d.ts +42 -0
- package/dist/render/frame/passTimings.js +38 -0
- package/dist/render/frame/validate.d.ts +15 -0
- package/dist/render/frame/validate.js +22 -0
- package/dist/render/frame/virtual.d.ts +44 -0
- package/dist/render/frame/virtual.js +61 -0
- package/dist/render/gi/chain.d.ts +82 -0
- package/dist/render/gi/chain.js +135 -0
- package/dist/render/gi/denoise.d.ts +114 -0
- package/dist/render/gi/denoise.js +169 -0
- package/dist/render/gi/fieldScene.d.ts +125 -0
- package/dist/render/gi/fieldScene.js +219 -0
- package/dist/render/gi/globalField.d.ts +157 -0
- package/dist/render/gi/globalField.js +373 -0
- package/dist/render/gi/probeGridFit.d.ts +24 -0
- package/dist/render/gi/probeGridFit.js +71 -0
- package/dist/render/gi/probeTrace.d.ts +82 -0
- package/dist/render/gi/probeTrace.js +128 -0
- package/dist/render/gi/probeVolume.d.ts +136 -0
- package/dist/render/gi/probeVolume.js +191 -0
- package/dist/render/gi/reflection.d.ts +73 -0
- package/dist/render/gi/reflection.js +109 -0
- package/dist/render/gi/traceField.d.ts +91 -0
- package/dist/render/gi/traceField.js +129 -0
- package/dist/render/gi/traceScreen.d.ts +68 -0
- package/dist/render/gi/traceScreen.js +82 -0
- package/dist/render/gpuScene.d.ts +38 -0
- package/dist/render/gpuScene.js +41 -0
- package/dist/render/gpudriven/alphaTest.d.ts +28 -0
- package/dist/render/gpudriven/alphaTest.js +32 -0
- package/dist/render/gpudriven/clusterUpload.d.ts +59 -0
- package/dist/render/gpudriven/clusterUpload.js +75 -0
- package/dist/render/gpudriven/clusterWorld.d.ts +57 -0
- package/dist/render/gpudriven/clusterWorld.js +155 -0
- package/dist/render/gpudriven/compact.d.ts +51 -0
- package/dist/render/gpudriven/compact.js +68 -0
- package/dist/render/gpudriven/cullClusters.d.ts +129 -0
- package/dist/render/gpudriven/cullClusters.js +237 -0
- package/dist/render/gpudriven/decodeTables.d.ts +64 -0
- package/dist/render/gpudriven/decodeTables.js +219 -0
- package/dist/render/gpudriven/frustum.d.ts +25 -0
- package/dist/render/gpudriven/frustum.js +59 -0
- package/dist/render/gpudriven/geometryHarness.d.ts +15 -0
- package/dist/render/gpudriven/geometryHarness.js +31 -0
- package/dist/render/gpudriven/hzb.d.ts +60 -0
- package/dist/render/gpudriven/hzb.js +97 -0
- package/dist/render/gpudriven/ibl.d.ts +85 -0
- package/dist/render/gpudriven/ibl.js +129 -0
- package/dist/render/gpudriven/indirect.d.ts +67 -0
- package/dist/render/gpudriven/indirect.js +77 -0
- package/dist/render/gpudriven/instances.d.ts +43 -0
- package/dist/render/gpudriven/instances.js +172 -0
- package/dist/render/gpudriven/lit.d.ts +165 -0
- package/dist/render/gpudriven/lit.js +165 -0
- package/dist/render/gpudriven/lodCut.d.ts +28 -0
- package/dist/render/gpudriven/lodCut.js +38 -0
- package/dist/render/gpudriven/materialBin.d.ts +60 -0
- package/dist/render/gpudriven/materialBin.js +108 -0
- package/dist/render/gpudriven/materialTable.d.ts +88 -0
- package/dist/render/gpudriven/materialTable.js +115 -0
- package/dist/render/gpudriven/pipeline.d.ts +135 -0
- package/dist/render/gpudriven/pipeline.js +237 -0
- package/dist/render/gpudriven/rangeAlloc.d.ts +50 -0
- package/dist/render/gpudriven/rangeAlloc.js +112 -0
- package/dist/render/gpudriven/sceneUpload.d.ts +96 -0
- package/dist/render/gpudriven/sceneUpload.js +115 -0
- package/dist/render/gpudriven/shadeBins.d.ts +92 -0
- package/dist/render/gpudriven/shadeBins.js +182 -0
- package/dist/render/gpudriven/shadow.d.ts +136 -0
- package/dist/render/gpudriven/shadow.js +224 -0
- package/dist/render/gpudriven/shadowCamera.d.ts +87 -0
- package/dist/render/gpudriven/shadowCamera.js +345 -0
- package/dist/render/gpudriven/streamScene.d.ts +194 -0
- package/dist/render/gpudriven/streamScene.js +459 -0
- package/dist/render/gpudriven/surfaceFrame.d.ts +25 -0
- package/dist/render/gpudriven/surfaceFrame.js +51 -0
- package/dist/render/gpudriven/twoPhase.d.ts +122 -0
- package/dist/render/gpudriven/twoPhase.js +160 -0
- package/dist/render/gpudriven/visbuffer.d.ts +25 -0
- package/dist/render/gpudriven/visbuffer.js +37 -0
- package/dist/render/halfFloat.d.ts +10 -0
- package/dist/render/halfFloat.js +23 -4
- package/dist/render/inference/attentionTiled.d.ts +27 -0
- package/dist/render/inference/attentionTiled.js +117 -0
- package/dist/render/inference/denseKernels.d.ts +29 -0
- package/dist/render/inference/denseKernels.js +312 -0
- package/dist/render/inference/device.d.ts +21 -0
- package/dist/render/inference/device.js +32 -0
- package/dist/render/inference/deviceGraph.d.ts +34 -0
- package/dist/render/inference/deviceGraph.js +17 -0
- package/dist/render/inference/fuse.d.ts +15 -0
- package/dist/render/inference/fuse.js +37 -0
- package/dist/render/inference/kernelKit.d.ts +52 -0
- package/dist/render/inference/kernelKit.js +70 -0
- package/dist/render/inference/kernels.d.ts +3 -0
- package/dist/render/inference/kernels.js +11 -0
- package/dist/render/inference/plan.d.ts +13 -0
- package/dist/render/inference/plan.js +18 -0
- package/dist/render/inference/reuse.d.ts +39 -0
- package/dist/render/inference/reuse.js +65 -0
- package/dist/render/inference/runner.d.ts +31 -0
- package/dist/render/inference/runner.js +175 -0
- package/dist/render/inference/schedule.d.ts +39 -0
- package/dist/render/inference/schedule.js +59 -0
- package/dist/render/inference/shapeKernels.d.ts +10 -0
- package/dist/render/inference/shapeKernels.js +80 -0
- package/dist/render/inference/spatialKernels.d.ts +21 -0
- package/dist/render/inference/spatialKernels.js +179 -0
- package/dist/render/inference/splatRaster.wgsl.d.ts +75 -0
- package/dist/render/inference/splatRaster.wgsl.js +337 -0
- package/dist/render/inference/splatTiles.d.ts +79 -0
- package/dist/render/inference/splatTiles.js +161 -0
- package/dist/render/lineBatch.d.ts +2 -5
- package/dist/render/lineBatch.js +4 -24
- package/dist/render/mesh.d.ts +4 -0
- package/dist/render/mesh.js +45 -1
- package/dist/render/pass.d.ts +145 -8
- package/dist/render/prefilterEnvMap.d.ts +22 -0
- package/dist/render/prefilterEnvMap.js +31 -0
- package/dist/render/readback.d.ts +30 -0
- package/dist/render/readback.js +47 -0
- package/dist/render/recon/clamp.d.ts +36 -0
- package/dist/render/recon/clamp.js +92 -0
- package/dist/render/recon/disocclusion.d.ts +60 -0
- package/dist/render/recon/disocclusion.js +109 -0
- package/dist/render/recon/frameGen.d.ts +81 -0
- package/dist/render/recon/frameGen.js +150 -0
- package/dist/render/recon/frameSizes.d.ts +34 -0
- package/dist/render/recon/frameSizes.js +58 -0
- package/dist/render/recon/jitter.d.ts +60 -0
- package/dist/render/recon/jitter.js +118 -0
- package/dist/render/recon/motionVectors.d.ts +55 -0
- package/dist/render/recon/motionVectors.js +107 -0
- package/dist/render/recon/reproject.d.ts +41 -0
- package/dist/render/recon/reproject.js +131 -0
- package/dist/render/recon/resolve.d.ts +90 -0
- package/dist/render/recon/resolve.js +313 -0
- package/dist/render/recon/tier.d.ts +24 -0
- package/dist/render/recon/tier.js +8 -0
- package/dist/render/reflectionProbe.d.ts +26 -0
- package/dist/render/reflectionProbe.js +33 -0
- package/dist/render/renderQuality.d.ts +69 -0
- package/dist/render/renderQuality.js +22 -0
- package/dist/render/screenSpaceReflection.d.ts +23 -0
- package/dist/render/screenSpaceReflection.js +22 -3
- package/dist/render/sdfFont.js +2 -0
- package/dist/render/segmentQuads.d.ts +13 -0
- package/dist/render/segmentQuads.js +32 -0
- package/dist/render/shaders/flat/lobes.d.ts +27 -0
- package/dist/render/shaders/flat/lobes.js +33 -3
- package/dist/render/shaders/flat/preamble.d.ts +7 -0
- package/dist/render/shaders/flat/preamble.js +24 -1
- package/dist/render/shaders/flat/probeGrid.d.ts +1 -1
- package/dist/render/shaders/flat/probeGrid.js +71 -2
- package/dist/render/shaders/generated/flat.wgsl.d.ts +48 -8
- package/dist/render/shaders/generated/flat.wgsl.js +64 -24
- package/dist/render/shaders/gi/composeField.wgsl.d.ts +56 -0
- package/dist/render/shaders/gi/composeField.wgsl.js +231 -0
- package/dist/render/shaders/gi/marchField.wgsl.d.ts +30 -0
- package/dist/render/shaders/gi/marchField.wgsl.js +141 -0
- package/dist/render/shaders/gi/probeBake.wgsl.d.ts +113 -0
- package/dist/render/shaders/gi/probeBake.wgsl.js +635 -0
- package/dist/render/shaders/gi/probeTrace.wgsl.d.ts +72 -0
- package/dist/render/shaders/gi/probeTrace.wgsl.js +261 -0
- package/dist/render/shaders/gi/probeVolume.wgsl.d.ts +49 -0
- package/dist/render/shaders/gi/probeVolume.wgsl.js +242 -0
- package/dist/render/shaders/gi/sampleField.wgsl.d.ts +32 -0
- package/dist/render/shaders/gi/sampleField.wgsl.js +134 -0
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.d.ts +26 -0
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.js +339 -0
- package/dist/render/shaders/gpudriven/compact.wgsl.d.ts +29 -0
- package/dist/render/shaders/gpudriven/compact.wgsl.js +58 -0
- package/dist/render/shaders/gpudriven/cull.wgsl.d.ts +90 -0
- package/dist/render/shaders/gpudriven/cull.wgsl.js +423 -0
- package/dist/render/shaders/gpudriven/decode.wgsl.d.ts +72 -0
- package/dist/render/shaders/gpudriven/decode.wgsl.js +349 -0
- package/dist/render/shaders/gpudriven/environment.wgsl.d.ts +44 -0
- package/dist/render/shaders/gpudriven/environment.wgsl.js +137 -0
- package/dist/render/shaders/gpudriven/fog.wgsl.d.ts +28 -0
- package/dist/render/shaders/gpudriven/fog.wgsl.js +107 -0
- package/dist/render/shaders/gpudriven/frameBlock.wgsl.d.ts +13 -0
- package/dist/render/shaders/gpudriven/frameBlock.wgsl.js +62 -0
- package/dist/render/shaders/gpudriven/materialBin.wgsl.d.ts +51 -0
- package/dist/render/shaders/gpudriven/materialBin.wgsl.js +112 -0
- package/dist/render/shaders/gpudriven/materialTable.wgsl.d.ts +25 -0
- package/dist/render/shaders/gpudriven/materialTable.wgsl.js +43 -0
- package/dist/render/shaders/gpudriven/meshTransform.wgsl.d.ts +18 -0
- package/dist/render/shaders/gpudriven/meshTransform.wgsl.js +37 -0
- package/dist/render/shaders/gpudriven/present.wgsl.d.ts +43 -0
- package/dist/render/shaders/gpudriven/present.wgsl.js +127 -0
- package/dist/render/shaders/gpudriven/shade.wgsl.d.ts +127 -0
- package/dist/render/shaders/gpudriven/shade.wgsl.js +874 -0
- package/dist/render/shaders/gpudriven/shadow.wgsl.d.ts +44 -0
- package/dist/render/shaders/gpudriven/shadow.wgsl.js +308 -0
- package/dist/render/shaders/gpudriven/visbufferRaster.wgsl.d.ts +28 -0
- package/dist/render/shaders/gpudriven/visbufferRaster.wgsl.js +245 -0
- package/dist/render/shaders/network.wgsl.d.ts +101 -0
- package/dist/render/shaders/network.wgsl.js +206 -0
- package/dist/render/shaders/recon/motion.wgsl.d.ts +44 -0
- package/dist/render/shaders/recon/motion.wgsl.js +96 -0
- package/dist/render/shaders/recon/resolve.wgsl.d.ts +51 -0
- package/dist/render/shaders/recon/resolve.wgsl.js +733 -0
- package/dist/render/temporalAa.js +8 -33
- package/dist/render/textLayout.js +12 -6
- package/dist/render/textRenderer.d.ts +3 -1
- package/dist/render/textRenderer.js +4 -1
- package/dist/render/translucentQueue.d.ts +6 -0
- package/dist/render/translucentQueue.js +11 -0
- package/dist/render/windStreakRenderer.d.ts +2 -1
- package/dist/render/windStreakRenderer.js +3 -1
- package/dist/world/cell.d.ts +63 -0
- package/dist/world/cell.js +181 -0
- package/dist/world/cellStream.d.ts +103 -0
- package/dist/world/cellStream.js +198 -0
- package/dist/world/freeze.d.ts +81 -0
- package/dist/world/freeze.js +114 -0
- package/dist/world/rebase.d.ts +29 -0
- package/dist/world/rebase.js +41 -0
- package/package.json +8 -3
- package/scripts/frames.mjs +92 -0
- package/scripts/gpuCompute.mjs +323 -0
- package/scripts/png.d.mts +16 -0
- package/scripts/png.mjs +25 -0
- package/src/core/loop.ts +19 -2
- package/src/core/storage.ts +5 -0
- package/src/geometry/meshBuilder.ts +5 -1
- package/src/index.ts +246 -4
- package/src/input/input.ts +6 -1
- package/src/math/exact.ts +69 -3
- package/src/math/frustum.ts +52 -3
- package/src/render/backend/api.ts +42 -1
- package/src/render/backend/budget.ts +7 -6
- package/src/render/backend/createRenderer.ts +92 -3
- package/src/render/backend/materialChanges.ts +54 -0
- package/src/render/backend/select.ts +8 -0
- package/src/render/backend/webgl2/renderer.ts +211 -9
- package/src/render/backend/webgpu/buffers.ts +182 -69
- package/src/render/backend/webgpu/fieldCompose.ts +482 -0
- package/src/render/backend/webgpu/giFieldPass.ts +200 -0
- package/src/render/backend/webgpu/gpuDrivenPass.ts +2993 -0
- package/src/render/backend/webgpu/linePass.ts +4 -39
- package/src/render/backend/webgpu/probeBake.ts +588 -0
- package/src/render/backend/webgpu/renderer.ts +1481 -76
- package/src/render/backend/webgpu/scatterPass.ts +15 -1
- package/src/render/backend/webgpu/surfaceTexturePass.ts +63 -36
- package/src/render/causticsRenderer.ts +5 -2
- package/src/render/depthConvention.ts +15 -0
- package/src/render/deviceFeatures.ts +77 -0
- package/src/render/fog.ts +185 -0
- package/src/render/frame/alias.ts +97 -0
- package/src/render/frame/deps.ts +155 -0
- package/src/render/frame/flushGraph.ts +135 -0
- package/src/render/frame/graphSchedule.ts +170 -0
- package/src/render/frame/index.ts +52 -0
- package/src/render/frame/lifetime.ts +61 -0
- package/src/render/frame/passTimings.ts +69 -0
- package/src/render/frame/validate.ts +40 -0
- package/src/render/frame/virtual.ts +91 -0
- package/src/render/gi/chain.ts +225 -0
- package/src/render/gi/denoise.ts +276 -0
- package/src/render/gi/fieldScene.ts +264 -0
- package/src/render/gi/globalField.ts +543 -0
- package/src/render/gi/probeGridFit.ts +89 -0
- package/src/render/gi/probeTrace.ts +143 -0
- package/src/render/gi/probeVolume.ts +288 -0
- package/src/render/gi/reflection.ts +163 -0
- package/src/render/gi/traceField.ts +223 -0
- package/src/render/gi/traceScreen.ts +106 -0
- package/src/render/gpuScene.ts +80 -0
- package/src/render/gpudriven/alphaTest.ts +33 -0
- package/src/render/gpudriven/clusterUpload.ts +123 -0
- package/src/render/gpudriven/clusterWorld.ts +239 -0
- package/src/render/gpudriven/compact.ts +80 -0
- package/src/render/gpudriven/cullClusters.ts +333 -0
- package/src/render/gpudriven/decodeTables.ts +332 -0
- package/src/render/gpudriven/frustum.ts +70 -0
- package/src/render/gpudriven/geometryHarness.ts +51 -0
- package/src/render/gpudriven/hzb.ts +113 -0
- package/src/render/gpudriven/ibl.ts +147 -0
- package/src/render/gpudriven/indirect.ts +89 -0
- package/src/render/gpudriven/instances.ts +234 -0
- package/src/render/gpudriven/lit.ts +329 -0
- package/src/render/gpudriven/lodCut.ts +62 -0
- package/src/render/gpudriven/materialBin.ts +131 -0
- package/src/render/gpudriven/materialTable.ts +164 -0
- package/src/render/gpudriven/pipeline.ts +336 -0
- package/src/render/gpudriven/rangeAlloc.ts +122 -0
- package/src/render/gpudriven/sceneUpload.ts +173 -0
- package/src/render/gpudriven/shadeBins.ts +222 -0
- package/src/render/gpudriven/shadow.ts +285 -0
- package/src/render/gpudriven/shadowCamera.ts +406 -0
- package/src/render/gpudriven/streamScene.ts +575 -0
- package/src/render/gpudriven/surfaceFrame.ts +68 -0
- package/src/render/gpudriven/twoPhase.ts +214 -0
- package/src/render/gpudriven/visbuffer.ts +41 -0
- package/src/render/halfFloat.ts +22 -4
- package/src/render/inference/attentionTiled.ts +132 -0
- package/src/render/inference/denseKernels.ts +369 -0
- package/src/render/inference/device.ts +44 -0
- package/src/render/inference/deviceGraph.ts +39 -0
- package/src/render/inference/fuse.ts +47 -0
- package/src/render/inference/kernelKit.ts +120 -0
- package/src/render/inference/kernels.ts +18 -0
- package/src/render/inference/plan.ts +26 -0
- package/src/render/inference/reuse.ts +79 -0
- package/src/render/inference/runner.ts +204 -0
- package/src/render/inference/schedule.ts +80 -0
- package/src/render/inference/shapeKernels.ts +112 -0
- package/src/render/inference/spatialKernels.ts +220 -0
- package/src/render/inference/splatRaster.wgsl.ts +348 -0
- package/src/render/inference/splatTiles.ts +186 -0
- package/src/render/lineBatch.ts +4 -24
- package/src/render/mesh.ts +46 -1
- package/src/render/pass.ts +155 -10
- package/src/render/prefilterEnvMap.ts +33 -0
- package/src/render/readback.ts +73 -0
- package/src/render/recon/clamp.ts +113 -0
- package/src/render/recon/disocclusion.ts +143 -0
- package/src/render/recon/frameGen.ts +191 -0
- package/src/render/recon/frameSizes.ts +64 -0
- package/src/render/recon/jitter.ts +126 -0
- package/src/render/recon/motionVectors.ts +138 -0
- package/src/render/recon/reproject.ts +179 -0
- package/src/render/recon/resolve.ts +444 -0
- package/src/render/recon/tier.ts +31 -0
- package/src/render/reflectionProbe.ts +34 -0
- package/src/render/renderQuality.ts +87 -0
- package/src/render/screenSpaceReflection.ts +37 -3
- package/src/render/sdfFont.ts +2 -0
- package/src/render/segmentQuads.ts +39 -0
- package/src/render/shaders/flat/lobes.ts +35 -3
- package/src/render/shaders/flat/preamble.ts +25 -1
- package/src/render/shaders/flat/probeGrid.ts +77 -2
- package/src/render/shaders/generated/flat.wgsl.ts +64 -24
- package/src/render/shaders/gi/composeField.wgsl.ts +239 -0
- package/src/render/shaders/gi/marchField.wgsl.ts +146 -0
- package/src/render/shaders/gi/probeBake.wgsl.ts +649 -0
- package/src/render/shaders/gi/probeTrace.wgsl.ts +269 -0
- package/src/render/shaders/gi/probeVolume.wgsl.ts +246 -0
- package/src/render/shaders/gi/sampleField.wgsl.ts +140 -0
- package/src/render/shaders/gpudriven/blendRaster.wgsl.ts +343 -0
- package/src/render/shaders/gpudriven/compact.wgsl.ts +59 -0
- package/src/render/shaders/gpudriven/cull.wgsl.ts +433 -0
- package/src/render/shaders/gpudriven/decode.wgsl.ts +373 -0
- package/src/render/shaders/gpudriven/environment.wgsl.ts +141 -0
- package/src/render/shaders/gpudriven/fog.wgsl.ts +110 -0
- package/src/render/shaders/gpudriven/frameBlock.wgsl.ts +62 -0
- package/src/render/shaders/gpudriven/materialBin.wgsl.ts +116 -0
- package/src/render/shaders/gpudriven/materialTable.wgsl.ts +46 -0
- package/src/render/shaders/gpudriven/meshTransform.wgsl.ts +37 -0
- package/src/render/shaders/gpudriven/present.wgsl.ts +129 -0
- package/src/render/shaders/gpudriven/shade.wgsl.ts +884 -0
- package/src/render/shaders/gpudriven/shadow.wgsl.ts +322 -0
- package/src/render/shaders/gpudriven/visbufferRaster.wgsl.ts +251 -0
- package/src/render/shaders/network.wgsl.ts +238 -0
- package/src/render/shaders/recon/motion.wgsl.ts +101 -0
- package/src/render/shaders/recon/resolve.wgsl.ts +741 -0
- package/src/render/temporalAa.ts +9 -33
- package/src/render/textLayout.ts +12 -6
- package/src/render/textRenderer.ts +5 -2
- package/src/render/translucentQueue.ts +11 -0
- package/src/render/windStreakRenderer.ts +4 -2
- package/src/world/cell.ts +231 -0
- package/src/world/cellStream.ts +278 -0
- package/src/world/freeze.ts +157 -0
- package/src/world/rebase.ts +56 -0
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
export { startLoop } from './core/loop.js';
|
|
4
4
|
export { StepBudget } from './core/stepBudget.js';
|
|
5
5
|
export { hashToUnit, mulberry32, pickBySeed, savableMulberry32 } from './core/rng.js';
|
|
6
|
-
export { exactAcos, exactCos, exactExp, exactSin } from './math/exact.js';
|
|
6
|
+
export { exactAcos, exactCos, exactExp, exactLog, exactSin } from './math/exact.js';
|
|
7
7
|
export { TickTrace } from './core/tickTrace.js';
|
|
8
8
|
export { BrowserStore, MemoryStore, defaultStore } from './core/storage.js';
|
|
9
9
|
/* The same seam over a backend that answers later, with the queue, the retry and the status. */
|
|
@@ -60,7 +60,7 @@ export { MAX_DEPTH_LAYER, Renderer, WebGL2Renderer } from './render/backend/webg
|
|
|
60
60
|
export { PickableSet } from './render/pickable.js';
|
|
61
61
|
/* How big a piece of geometry is, which everything that culls or picks a detail level starts from. */
|
|
62
62
|
export { boundsOfBox, boundsOfPositions, createBounds } from './math/bounds.js';
|
|
63
|
-
export { createFrustum, frustumFromViewProjection, sphereInFrustum } from './math/frustum.js';
|
|
63
|
+
export { boxInFrustum, createFrustum, frustumFromViewProjection, sphereInFrustum, } from './math/frustum.js';
|
|
64
64
|
export { boundsVisible } from './render/visibility.js';
|
|
65
65
|
export { apparentSize, lodForBounds } from './render/lod.js';
|
|
66
66
|
/* A transform hierarchy. Additive: nothing in the renderer knows a node exists. */
|
|
@@ -79,6 +79,11 @@ export { createVisitResult, visitVisible } from './scene/visit.js';
|
|
|
79
79
|
*/
|
|
80
80
|
export { generateMipChain, mipLevelCount, } from './render/backend/webgpu/surfaceTexturePass.js';
|
|
81
81
|
export { createPassAttachment } from './render/passTarget.js';
|
|
82
|
+
/*
|
|
83
|
+
* What a pass drawing the world does with `PrepareContext.jitter`, so a reconstructed frame's
|
|
84
|
+
* resolve finds its geometry where the renderer's own verbs put theirs.
|
|
85
|
+
*/
|
|
86
|
+
export { jitterClip } from './render/recon/jitter.js';
|
|
82
87
|
export { OcclusionBuffer } from './render/occlusion.js';
|
|
83
88
|
/*
|
|
84
89
|
* `Renderer` above stays exported and is not deprecated. `createRenderer` is the way to get
|
|
@@ -87,6 +92,80 @@ export { OcclusionBuffer } from './render/occlusion.js';
|
|
|
87
92
|
* take one.
|
|
88
93
|
*/
|
|
89
94
|
export { createRenderer } from './render/backend/createRenderer.js';
|
|
95
|
+
/*
|
|
96
|
+
* The second pipeline, as the two things a consumer assembles: the scene packing and the pass
|
|
97
|
+
* that draws it.
|
|
98
|
+
*
|
|
99
|
+
* **Exported here and reached by nobody who does not ask for it.** `pipeline: 'gpu-driven'` on
|
|
100
|
+
* `createRenderer` is the permission — it fails at boot where the backend cannot run this — and
|
|
101
|
+
* `GpuDrivenPass` is the implementation, registered the way `@driftengine/splats` registers one.
|
|
102
|
+
* A consumer who names neither pays nothing: `core-only` is measured with these exported and does
|
|
103
|
+
* not move, because nothing in the forward path reaches them.
|
|
104
|
+
*
|
|
105
|
+
* It draws vertex colour, one directional term, a hemispheric ambient and an emissive add — not
|
|
106
|
+
* the standard material. `DRAFT_SCENES`, never `SCENES`, until it draws the six published ones.
|
|
107
|
+
*/
|
|
108
|
+
export { GPU_DRIVEN_LISTS, GpuDrivenPass, MATERIAL_FLOATS, } from './render/backend/webgpu/gpuDrivenPass.js';
|
|
109
|
+
/*
|
|
110
|
+
* **One environment, one haze, on both pipelines.** `GpuDrivenView.fog` is the medium the forward
|
|
111
|
+
* path binds, and a consumer drawing both in one frame fills it from `atmosphereFog` rather than
|
|
112
|
+
* working the numbers out again — the voxel sandbox's port is the first.
|
|
113
|
+
*/
|
|
114
|
+
export { atmosphereFog, createFogTarget } from './render/fog.js';
|
|
115
|
+
export { buildGpuDrivenScene } from './render/gpudriven/sceneUpload.js';
|
|
116
|
+
/*
|
|
117
|
+
* **The scene a `GpuDrivenPass` takes**, which is a streaming one since 2026-09-18 — a static
|
|
118
|
+
* scene is one filled once, so there is a single path rather than two. `buildGpuDrivenScene` stays
|
|
119
|
+
* exported because it is the packer `streamScene.test.ts` holds the streaming layout to.
|
|
120
|
+
*/
|
|
121
|
+
export { StreamingScene, streamingScene } from './render/gpudriven/streamScene.js';
|
|
122
|
+
export { packDecodeTables, programFromEncoded } from './render/gpudriven/decodeTables.js';
|
|
123
|
+
/*
|
|
124
|
+
* **A network graph on a device**: the one neural runtime's device half. `@driftengine/texture`
|
|
125
|
+
* holds the references and validates a graph; this runs the validated graph, whose shapes it takes
|
|
126
|
+
* as given, on a device opened from whichever `GPU` the caller has — a browser's or the native
|
|
127
|
+
* host's Dawn. Exported because the device may not leave `render/`, so a package that runs a
|
|
128
|
+
* network does so through here or not at all.
|
|
129
|
+
*/
|
|
130
|
+
export { openInferenceDevice } from './render/inference/device.js';
|
|
131
|
+
export { createGraphRunner } from './render/inference/runner.js';
|
|
132
|
+
/* The buffer-reuse rule, exported because `@driftengine/texture`'s evaluator plans by this one
|
|
133
|
+
rather than by a second copy of it — see `reuse.ts` for why it is on this side of the arrow. */
|
|
134
|
+
export { planReuse } from './render/inference/reuse.js';
|
|
135
|
+
/* The tile lists a device draws a splat cloud from, beside the shader that walks them. */
|
|
136
|
+
export { countSplatTiles, fillSplatTiles, splatPixelBox, splatTileGrid, splatTileOffsets, SPLAT_BIN_FLOATS, SPLAT_TILE, } from './render/inference/splatTiles.js';
|
|
137
|
+
/**
|
|
138
|
+
* **Indirect light, as three levels that fall back to each other and never off the end.**
|
|
139
|
+
*
|
|
140
|
+
* `ROADMAP.md` refused screen-space global illumination because its error is unbounded — a ray
|
|
141
|
+
* that leaves the frame has no answer, and every technique that ships one anyway invents one from
|
|
142
|
+
* whatever happened to be on screen. This does not reverse that refusal: the screen is an
|
|
143
|
+
* accelerator with a world-space distance field behind it, whose error is bounded by its own
|
|
144
|
+
* resolution, and a probe volume behind *that*, which is never wrong and only ever coarse.
|
|
145
|
+
*
|
|
146
|
+
* **CPU-side, and reached by nobody who does not ask.** There is no WGSL, no pass and no renderer
|
|
147
|
+
* option yet, so no scene renders differently for these existing — this wave's first constraint,
|
|
148
|
+
* measured rather than asserted: the eight published scenes are 0 of 921,600 pixels against the
|
|
149
|
+
* build before them, and `core-only` is byte-identical with these exported and without them.
|
|
150
|
+
* Exported anyway, for the reason `bake/cluster.ts` was not: a capability with no route out of its
|
|
151
|
+
* package is one the first consumer finds by failing a boundary test.
|
|
152
|
+
*/
|
|
153
|
+
export { GI_SOURCE_FIELD, GI_SOURCE_PROBES, GI_SOURCE_SCREEN, newIndirectResult, traceIndirect, } from './render/gi/chain.js';
|
|
154
|
+
export { GLOBAL_FIELD_BLEND, composeGlobalField, createGlobalField, sampleGlobalField, } from './render/gi/globalField.js';
|
|
155
|
+
export { GI_SCREEN_MARCH, SCREEN_TRACE_BIAS_M, screenRayOrigin, traceScreen, } from './render/gi/traceScreen.js';
|
|
156
|
+
export { FIELD_MARCH, coneRadiusAt, newFieldHit, traceField } from './render/gi/traceField.js';
|
|
157
|
+
export { PROBE_VISIBILITY_SHARPNESS, bakeProbeVisibility, createProbeVisibility, probeUpdateSchedule, probeVisibilityWeight, sampleProbeVolume, visibleProbes, } from './render/gi/probeVolume.js';
|
|
158
|
+
export { DENOISE_MIN_ALPHA, filterStepFor, newTemporalPixel, spatialDenoise, temporalDenoise, } from './render/gi/denoise.js';
|
|
159
|
+
export { reflectDirection, reflectionCone, traceReflection } from './render/gi/reflection.js';
|
|
160
|
+
/*
|
|
161
|
+
* The pass that draws the renderer's field on a device. WebGPU only, and it says so at
|
|
162
|
+
* registration rather than at the first frame: a distance field is composed by compute and WebGL2
|
|
163
|
+
* has none. It no longer composes one of its own — `addDistanceField` is how a scene declares
|
|
164
|
+
* what its indirect light may be traced against, and this marches what the renderer made of them.
|
|
165
|
+
*/
|
|
166
|
+
export { GiFieldPass } from './render/backend/webgpu/giFieldPass.js';
|
|
167
|
+
export { DistanceFieldScene, MAX_DISTANCE_FIELDS } from './render/gi/fieldScene.js';
|
|
168
|
+
export { placeCascade } from './render/gi/globalField.js';
|
|
90
169
|
/*
|
|
91
170
|
* The acceptance probe, exported because a consumer may want to ask the question itself — an
|
|
92
171
|
* editor deciding whether to offer a backend, a shell deciding what to tell the player — and
|
|
@@ -225,6 +304,13 @@ export { DebugLines } from './render/debugLines.js';
|
|
|
225
304
|
* over and what a drag does, and fills line buffers the caller draws with `drawLines`.
|
|
226
305
|
* Nothing here touches a context.
|
|
227
306
|
*/
|
|
307
|
+
/*
|
|
308
|
+
* Ray intersection, exported because a consumer building a tool needs the same arithmetic the
|
|
309
|
+
* gizmo does. `editor/src/viewport/gizmo.ts` reaching into `src/math/intersect.ts` by path would
|
|
310
|
+
* be the editor using a private hook, which `ARCHITECTURE.md` treats as a hole in the engine
|
|
311
|
+
* rather than as the editor's problem — so the hole is closed here.
|
|
312
|
+
*/
|
|
313
|
+
export { rayClosestOnLine, rayPlane, raySphere } from './math/intersect.js';
|
|
228
314
|
export { GIZMO_GROUP_ACTIVE, GIZMO_GROUP_COLORS, GIZMO_GROUP_COUNT, GIZMO_GROUP_NEUTRAL, GIZMO_GROUP_X, GIZMO_GROUP_Y, GIZMO_GROUP_Z, GIZMO_NONE, GIZMO_ROTATE_X, GIZMO_ROTATE_Y, GIZMO_ROTATE_Z, GIZMO_SCALE_UNIFORM, GIZMO_SCALE_X, GIZMO_SCALE_Y, GIZMO_SCALE_Z, GIZMO_TRANSLATE_X, GIZMO_TRANSLATE_XY, GIZMO_TRANSLATE_Y, GIZMO_TRANSLATE_YZ, GIZMO_TRANSLATE_Z, GIZMO_TRANSLATE_ZX, Gizmo, gizmoScaleFor, } from './render/gizmo.js';
|
|
229
315
|
export { RainField } from './render/rainField.js';
|
|
230
316
|
export { coveredAbove } from './physics/heightSurface.js';
|
|
@@ -286,6 +372,21 @@ export { bakeOverlay, drawPixelText, pixelTextCells, pixelTextSize } from './ui/
|
|
|
286
372
|
export { FpsMeter } from './dev/fpsMeter.js';
|
|
287
373
|
export { CONTACT_LIMIT, createContactReports, describeContacts } from './dev/contactProbe.js';
|
|
288
374
|
export { GPU_SLOTS, GpuTimer } from './render/gpuTimer.js';
|
|
375
|
+
/*
|
|
376
|
+
* Per-pass timings, which are a readout rather than a frame graph.
|
|
377
|
+
*
|
|
378
|
+
* **`render/frame/index.ts` says nothing under it may be reached from outside `render/` yet, and
|
|
379
|
+
* this module is the exception with a reason.** The rest of that directory is the graph's
|
|
380
|
+
* construction — declarations, lifetimes, aliasing, scheduling — whose public shape the design
|
|
381
|
+
* leaves to a later phase, and exporting it now would fix a shape nobody has had to live with.
|
|
382
|
+
* A timing readout is not that: it is seven functions over three arrays, its own header argues why
|
|
383
|
+
* it is not a widening of `GpuTimer`, and anything that profiles a frame needs it.
|
|
384
|
+
*
|
|
385
|
+
* The editor is what made this concrete. `AGENTS.md`'s rule is that a consumer needing a private
|
|
386
|
+
* import has found a hole in the engine, and the hole is fixed here rather than worked around
|
|
387
|
+
* there — which is the whole reason the editor was built outside `packages/`.
|
|
388
|
+
*/
|
|
389
|
+
export { createPassTimings, passLabel, passMs, recordPassLabel, recordPassSample, resetPassTimings, } from './render/frame/passTimings.js';
|
|
289
390
|
export { classifyRightGesture } from './input/rightGesture.js';
|
|
290
391
|
export { createWindState, sampleWind } from './render/wind.js';
|
|
291
392
|
export { advanceWindField, createWindField } from './render/windField.js';
|
|
@@ -329,3 +430,12 @@ export { parseSdfFont } from './render/sdfFont.js';
|
|
|
329
430
|
export { DEFAULT_SDF_TEXT_STYLE, SdfTextLayout } from './render/sdfTextLayout.js';
|
|
330
431
|
export { WindStreakRenderer } from './render/windStreakRenderer.js';
|
|
331
432
|
export { buildTree } from './geometry/treeBuilder.js';
|
|
433
|
+
/*
|
|
434
|
+
* Large worlds: the cell grid that streams and freezes, and the origin that rendering rebases
|
|
435
|
+
* against while the simulation never does. See `world/rebase.ts` for why that asymmetry is the
|
|
436
|
+
* rule the whole design hangs on.
|
|
437
|
+
*/
|
|
438
|
+
export { cellBounds, cellCoord, cellCoordInRange, cellCoordsOf, cellIdFor, cellIdFrom, cellsInFrustum, cellsInRadius, createCellGrid, } from './world/cell.js';
|
|
439
|
+
export { renderOrigin, toRenderSpace, toWorldSpace } from './world/rebase.js';
|
|
440
|
+
export { cameraPositionFrom, cellPredictor, createCellStream, pumpCellStream, setCellStreamOrigin, } from './world/cellStream.js';
|
|
441
|
+
export { createFrozenCells, freezeCell, frozenEntities, frozenFingerprintContribution, isCellFrozen, thawCell, } from './world/freeze.js';
|
package/dist/input/input.js
CHANGED
|
@@ -317,7 +317,12 @@ export class InputSource {
|
|
|
317
317
|
constructor(target, preventDefaultCodes = [], options = {}) {
|
|
318
318
|
this.target = target;
|
|
319
319
|
this.preventDefaultCodes = new Set(preventDefaultCodes);
|
|
320
|
-
|
|
320
|
+
/* Guarded, and `ui/fullscreen.ts` guards the identical query with the identical test. This
|
|
321
|
+
line is in a constructor, so unguarded it did not degrade a hint — it threw, and an embedder
|
|
322
|
+
without `matchMedia` could not construct input at all. False is what a runtime with no
|
|
323
|
+
pointer media query honestly is. */
|
|
324
|
+
this.isCoarse =
|
|
325
|
+
typeof window.matchMedia === 'function' && window.matchMedia('(pointer: coarse)').matches;
|
|
321
326
|
this.deadzone = options.deadzone ?? DEFAULT_DEADZONE;
|
|
322
327
|
this.autoPoll = options.autoPoll ?? true;
|
|
323
328
|
for (const name of ['keyboard', 'mouse', 'touch', 'gamepad']) {
|
package/dist/math/exact.d.ts
CHANGED
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
*
|
|
19
19
|
* ## What is here, and what is deliberately not
|
|
20
20
|
*
|
|
21
|
-
* `exactSin`, `exactCos`, `exactExp`, `exactAcos`.
|
|
22
|
-
* first consumer actually reach for: the terrain binding's slope angle needs `acos`,
|
|
23
|
-
* fixture rotating anything needs `sin` and `cos`,
|
|
21
|
+
* `exactSin`, `exactCos`, `exactExp`, `exactAcos` and `exactLog`. Five, because five is what the
|
|
22
|
+
* engine and its first consumer actually reach for: the terrain binding's slope angle needs `acos`,
|
|
23
|
+
* a lockstep fixture rotating anything needs `sin` and `cos`, exponential decay needs `exp`, and a
|
|
24
|
+
* detector's box prior is a logit of the patch grid, which needs `log`.
|
|
24
25
|
*
|
|
25
26
|
* **`atan2` is absent.** It is the obvious fifth and nothing here needs one: `shape.ts` sorts by a
|
|
26
27
|
* comparison key computed from two in-plane axes rather than by an angle, and `joints.ts` compares
|
|
@@ -55,6 +56,15 @@ export declare function exactCos(x: number): number;
|
|
|
55
56
|
* representation and there is nothing a fitted polynomial would buy.
|
|
56
57
|
*/
|
|
57
58
|
export declare function exactExp(x: number): number;
|
|
59
|
+
/**
|
|
60
|
+
* `Math.log`, reproducibly: fdlibm's algorithm, which is also V8's.
|
|
61
|
+
*
|
|
62
|
+
* Take the power of two out as `k` and leave a significand in [√2/2, √2), so that `f = m - 1` is
|
|
63
|
+
* small either side of zero; then log(1 + f) = f - f²/2 + s·(f²/2 + R(s²)) with s = f/(2 + f), and
|
|
64
|
+
* `k·ln 2` added back in two parts so the large part loses nothing. The exponent is read and the
|
|
65
|
+
* significand rescaled through the double's own words — integer operations, not transcendentals.
|
|
66
|
+
*/
|
|
67
|
+
export declare function exactLog(x: number): number;
|
|
58
68
|
/**
|
|
59
69
|
* `Math.acos`, reproducibly. Outside [-1, 1] this answers NaN, as `Math.acos` does.
|
|
60
70
|
*
|
package/dist/math/exact.js
CHANGED
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
*
|
|
19
19
|
* ## What is here, and what is deliberately not
|
|
20
20
|
*
|
|
21
|
-
* `exactSin`, `exactCos`, `exactExp`, `exactAcos`.
|
|
22
|
-
* first consumer actually reach for: the terrain binding's slope angle needs `acos`,
|
|
23
|
-
* fixture rotating anything needs `sin` and `cos`,
|
|
21
|
+
* `exactSin`, `exactCos`, `exactExp`, `exactAcos` and `exactLog`. Five, because five is what the
|
|
22
|
+
* engine and its first consumer actually reach for: the terrain binding's slope angle needs `acos`,
|
|
23
|
+
* a lockstep fixture rotating anything needs `sin` and `cos`, exponential decay needs `exp`, and a
|
|
24
|
+
* detector's box prior is a logit of the patch grid, which needs `log`.
|
|
24
25
|
*
|
|
25
26
|
* **`atan2` is absent.** It is the obvious fifth and nothing here needs one: `shape.ts` sorts by a
|
|
26
27
|
* comparison key computed from two in-plane axes rather than by an angle, and `joints.ts` compares
|
|
@@ -226,6 +227,70 @@ export function exactExp(x) {
|
|
|
226
227
|
sum = 1 + r * sum;
|
|
227
228
|
return sum * pow2(k);
|
|
228
229
|
}
|
|
230
|
+
/* fdlibm's `log` polynomial in s², for log(1 + f) around f = 0 by way of s = f / (2 + f). */
|
|
231
|
+
const LG1 = 6.66666666666673513e-1;
|
|
232
|
+
const LG2 = 3.999999999940941908e-1;
|
|
233
|
+
const LG3 = 2.857142874366239149e-1;
|
|
234
|
+
const LG4 = 2.222219843214978396e-1;
|
|
235
|
+
const LG5 = 1.818357216161805012e-1;
|
|
236
|
+
const LG6 = 1.531383769920937332e-1;
|
|
237
|
+
const LG7 = 1.479819860511658591e-1;
|
|
238
|
+
const TWO54 = 1.8014398509481984e16;
|
|
239
|
+
const SMALLEST_NORMAL = 2.2250738585072014e-308;
|
|
240
|
+
/* A double's two words, for reading and setting an exponent; one view, reused. */
|
|
241
|
+
const words = new DataView(new ArrayBuffer(8));
|
|
242
|
+
/**
|
|
243
|
+
* `Math.log`, reproducibly: fdlibm's algorithm, which is also V8's.
|
|
244
|
+
*
|
|
245
|
+
* Take the power of two out as `k` and leave a significand in [√2/2, √2), so that `f = m - 1` is
|
|
246
|
+
* small either side of zero; then log(1 + f) = f - f²/2 + s·(f²/2 + R(s²)) with s = f/(2 + f), and
|
|
247
|
+
* `k·ln 2` added back in two parts so the large part loses nothing. The exponent is read and the
|
|
248
|
+
* significand rescaled through the double's own words — integer operations, not transcendentals.
|
|
249
|
+
*/
|
|
250
|
+
export function exactLog(x) {
|
|
251
|
+
if (Number.isNaN(x) || x < 0)
|
|
252
|
+
return Number.NaN;
|
|
253
|
+
if (x === 0)
|
|
254
|
+
return Number.NEGATIVE_INFINITY;
|
|
255
|
+
if (x === Number.POSITIVE_INFINITY)
|
|
256
|
+
return x;
|
|
257
|
+
let k = 0;
|
|
258
|
+
let value = x;
|
|
259
|
+
if (value < SMALLEST_NORMAL) {
|
|
260
|
+
k = -54;
|
|
261
|
+
value *= TWO54;
|
|
262
|
+
}
|
|
263
|
+
words.setFloat64(0, value);
|
|
264
|
+
let hx = words.getUint32(0);
|
|
265
|
+
k += (hx >>> 20) - 1023;
|
|
266
|
+
hx &= 0x000fffff;
|
|
267
|
+
/* Keep the significand at or above √2/2: past √2, halve it and count one more power of two. */
|
|
268
|
+
const i = (hx + 0x95f64) & 0x100000;
|
|
269
|
+
words.setUint32(0, hx | (i ^ 0x3ff00000));
|
|
270
|
+
k += i >>> 20;
|
|
271
|
+
const f = words.getFloat64(0) - 1;
|
|
272
|
+
if ((0x000fffff & (2 + hx)) < 3) {
|
|
273
|
+
/* |f| < 2^-20: two terms of the series are the whole answer. */
|
|
274
|
+
if (f === 0)
|
|
275
|
+
return k === 0 ? 0 : k * LN2_HI + k * LN2_LO;
|
|
276
|
+
const r = f * f * (0.5 - 0.33333333333333333 * f);
|
|
277
|
+
return k === 0 ? f - r : k * LN2_HI - (r - k * LN2_LO - f);
|
|
278
|
+
}
|
|
279
|
+
const s = f / (2 + f);
|
|
280
|
+
const z = s * s;
|
|
281
|
+
const w = z * z;
|
|
282
|
+
const t1 = w * (LG2 + w * (LG4 + w * LG6));
|
|
283
|
+
const t2 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7)));
|
|
284
|
+
const r = t2 + t1;
|
|
285
|
+
/* Far enough from one that f²/2 is worth carrying apart from f. */
|
|
286
|
+
if (((hx - 0x6147a) | (0x6b851 - hx)) > 0) {
|
|
287
|
+
const half = 0.5 * f * f;
|
|
288
|
+
return k === 0
|
|
289
|
+
? f - (half - s * (half + r))
|
|
290
|
+
: k * LN2_HI - (half - (s * (half + r) + k * LN2_LO) - f);
|
|
291
|
+
}
|
|
292
|
+
return k === 0 ? f - s * (f - r) : k * LN2_HI - (s * (f - r) - k * LN2_LO - f);
|
|
293
|
+
}
|
|
229
294
|
/** fdlibm's `asin` rational on `z = x²`, valid where `z` is small. */
|
|
230
295
|
function asinRational(z) {
|
|
231
296
|
const numerator = z * (P0 + z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5)))));
|
package/dist/math/frustum.d.ts
CHANGED
|
@@ -10,6 +10,11 @@ import type { ReadonlyMat4 } from 'gl-matrix';
|
|
|
10
10
|
* the frustum when `n · p + d >= 0` for all six.
|
|
11
11
|
*/
|
|
12
12
|
export type Frustum = Float32Array;
|
|
13
|
+
/**
|
|
14
|
+
* Planes in either precision. **Double precision is for a world past 2^24 units**, where a plane's
|
|
15
|
+
* offset is a number a single float cannot hold to the metre; `cellsInFrustum` asks for it.
|
|
16
|
+
*/
|
|
17
|
+
export type FrustumPlanes = Float32Array | Float64Array;
|
|
13
18
|
export declare function createFrustum(): Frustum;
|
|
14
19
|
/**
|
|
15
20
|
* Pull the six planes out of a view-projection matrix.
|
|
@@ -28,7 +33,7 @@ export declare function createFrustum(): Frustum;
|
|
|
28
33
|
*
|
|
29
34
|
* gl-matrix stores column-major, so `m[column * 4 + row]`.
|
|
30
35
|
*/
|
|
31
|
-
export declare function frustumFromViewProjection(m: ReadonlyMat4, out:
|
|
36
|
+
export declare function frustumFromViewProjection<T extends FrustumPlanes>(m: ReadonlyMat4 | Float64Array, out: T): T;
|
|
32
37
|
/**
|
|
33
38
|
* Whether a world-space sphere is anywhere inside the frustum.
|
|
34
39
|
*
|
|
@@ -41,4 +46,14 @@ export declare function frustumFromViewProjection(m: ReadonlyMat4, out: Frustum)
|
|
|
41
46
|
* all six planes, near an edge. That costs a draw that turns out to be invisible and never costs
|
|
42
47
|
* a draw that was visible, which is the only asymmetry a cull may have.
|
|
43
48
|
*/
|
|
44
|
-
export declare function sphereInFrustum(frustum:
|
|
49
|
+
export declare function sphereInFrustum(frustum: FrustumPlanes, x: number, y: number, z: number, radius: number): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Whether an axis-aligned box is anywhere inside the frustum, by the same question the sphere test
|
|
52
|
+
* asks: outside only when wholly beyond one plane.
|
|
53
|
+
*
|
|
54
|
+
* **The corner that decides it is chosen per plane** — the one furthest along that plane's normal.
|
|
55
|
+
* A fixed corner answers correctly for the planes whose normals happen to point its way and culls a
|
|
56
|
+
* box straddling any of the others. Conservative at the edges, as the sphere test is: a box near a
|
|
57
|
+
* corner of the frustum can be outside it and still kept.
|
|
58
|
+
*/
|
|
59
|
+
export declare function boxInFrustum(frustum: FrustumPlanes, minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number): boolean;
|
package/dist/math/frustum.js
CHANGED
|
@@ -88,3 +88,27 @@ export function sphereInFrustum(frustum, x, y, z, radius) {
|
|
|
88
88
|
}
|
|
89
89
|
return true;
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Whether an axis-aligned box is anywhere inside the frustum, by the same question the sphere test
|
|
93
|
+
* asks: outside only when wholly beyond one plane.
|
|
94
|
+
*
|
|
95
|
+
* **The corner that decides it is chosen per plane** — the one furthest along that plane's normal.
|
|
96
|
+
* A fixed corner answers correctly for the planes whose normals happen to point its way and culls a
|
|
97
|
+
* box straddling any of the others. Conservative at the edges, as the sphere test is: a box near a
|
|
98
|
+
* corner of the frustum can be outside it and still kept.
|
|
99
|
+
*/
|
|
100
|
+
export function boxInFrustum(frustum, minX, minY, minZ, maxX, maxY, maxZ) {
|
|
101
|
+
for (let plane = 0; plane < PLANE_COUNT; plane += 1) {
|
|
102
|
+
const at = plane * 4;
|
|
103
|
+
const nx = frustum[at] ?? 0;
|
|
104
|
+
const ny = frustum[at + 1] ?? 0;
|
|
105
|
+
const nz = frustum[at + 2] ?? 0;
|
|
106
|
+
const reach = nx * (nx >= 0 ? maxX : minX) +
|
|
107
|
+
ny * (ny >= 0 ? maxY : minY) +
|
|
108
|
+
nz * (nz >= 0 ? maxZ : minZ) +
|
|
109
|
+
(frustum[at + 3] ?? 0);
|
|
110
|
+
if (reach < 0)
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
@@ -464,7 +464,20 @@ export type RendererApi = Omit<{
|
|
|
464
464
|
*/
|
|
465
465
|
updateMesh(mesh: MeshHandle, positions: Float32Array, normals?: Float32Array): void;
|
|
466
466
|
/** Draw a handle this renderer made. Passing one from the other backend is a caller error. */
|
|
467
|
-
drawMesh(mesh: MeshHandle, model: ReadonlyMat4, depthLayer?: number, tint?: Vec3 | null
|
|
467
|
+
drawMesh(mesh: MeshHandle, model: ReadonlyMat4, depthLayer?: number, tint?: Vec3 | null,
|
|
468
|
+
/**
|
|
469
|
+
* Where this mesh's surface was last frame, for a reconstruction's motion target.
|
|
470
|
+
*
|
|
471
|
+
* **Only a reconstruction reads it**, and only on WebGPU: it is what turns a moving object's
|
|
472
|
+
* stale history from a smear into a reprojection. A draw that says nothing gets the camera's
|
|
473
|
+
* motion, derived from the depth, which is exactly right for anything that did not move and
|
|
474
|
+
* wrong in proportion to how far a mover moved. Null and omitted mean the same thing.
|
|
475
|
+
*
|
|
476
|
+
* It is the *model* matrix this mesh was drawn with last frame, not a velocity: the pass
|
|
477
|
+
* transforms each vertex twice and lets the perspective divide do the rest, so a rotation and a
|
|
478
|
+
* scale are as correct as a translation.
|
|
479
|
+
*/
|
|
480
|
+
previousModel?: ReadonlyMat4 | null): void;
|
|
468
481
|
/** Release the geometry behind a handle. */
|
|
469
482
|
disposeMesh(mesh: MeshHandle): void;
|
|
470
483
|
/**
|
|
@@ -494,3 +507,23 @@ export type RendererApi = Omit<{
|
|
|
494
507
|
};
|
|
495
508
|
/** Which backend is actually drawing. Reported, never inferred. */
|
|
496
509
|
export type RenderBackend = 'webgl2' | 'webgpu';
|
|
510
|
+
/**
|
|
511
|
+
* Whether this backend can be driven from buffers the GPU itself wrote.
|
|
512
|
+
*
|
|
513
|
+
* **A fact about the backend, not a method on this surface, and that is the finding rather than
|
|
514
|
+
* the shortcut.** Indirect execution needs a render or compute pass encoder, and both are already
|
|
515
|
+
* in the hands of the code that would use them: `PassContext` hands a contributed pass the
|
|
516
|
+
* `GPURenderPassEncoder`, and `ComputeDefinition.dispatch` hands a definition the
|
|
517
|
+
* `GPUComputePassEncoder` while saying in as many words that the workgroup count is the
|
|
518
|
+
* definition's and does not cross this surface. A `drawIndexedIndirect` here would be a second
|
|
519
|
+
* way to reach an encoder a caller already holds.
|
|
520
|
+
*
|
|
521
|
+
* So what is missing is not a verb. It is an answer to *may I*, which a GPU-driven pipeline has
|
|
522
|
+
* to ask before it builds an argument buffer nothing can consume.
|
|
523
|
+
*
|
|
524
|
+
* **WebGL2 is a refusal rather than an omission.** It has no compute stage to write an argument
|
|
525
|
+
* buffer and no indirect draw to read one. Emulating it means reading the buffer back to the
|
|
526
|
+
* processor and issuing the draws from there, which is slower than the ordinary path it would be
|
|
527
|
+
* pretending to replace — so this reports false and the GPU-driven pipeline is WebGPU-only.
|
|
528
|
+
*/
|
|
529
|
+
export declare function indirectSupport(backend: 'webgl2' | 'webgpu'): boolean;
|
|
@@ -1 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Whether this backend can be driven from buffers the GPU itself wrote.
|
|
3
|
+
*
|
|
4
|
+
* **A fact about the backend, not a method on this surface, and that is the finding rather than
|
|
5
|
+
* the shortcut.** Indirect execution needs a render or compute pass encoder, and both are already
|
|
6
|
+
* in the hands of the code that would use them: `PassContext` hands a contributed pass the
|
|
7
|
+
* `GPURenderPassEncoder`, and `ComputeDefinition.dispatch` hands a definition the
|
|
8
|
+
* `GPUComputePassEncoder` while saying in as many words that the workgroup count is the
|
|
9
|
+
* definition's and does not cross this surface. A `drawIndexedIndirect` here would be a second
|
|
10
|
+
* way to reach an encoder a caller already holds.
|
|
11
|
+
*
|
|
12
|
+
* So what is missing is not a verb. It is an answer to *may I*, which a GPU-driven pipeline has
|
|
13
|
+
* to ask before it builds an argument buffer nothing can consume.
|
|
14
|
+
*
|
|
15
|
+
* **WebGL2 is a refusal rather than an omission.** It has no compute stage to write an argument
|
|
16
|
+
* buffer and no indirect draw to read one. Emulating it means reading the buffer back to the
|
|
17
|
+
* processor and issuing the draws from there, which is slower than the ordinary path it would be
|
|
18
|
+
* pretending to replace — so this reports false and the GPU-driven pipeline is WebGPU-only.
|
|
19
|
+
*/
|
|
20
|
+
export function indirectSupport(backend) {
|
|
21
|
+
return backend === 'webgpu';
|
|
22
|
+
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* What a frame asked of a backend, against what that backend allows.
|
|
3
3
|
*
|
|
4
|
-
* **This exists because a ceiling firing was unobservable.** The WebGPU backend holds
|
|
5
|
-
* ceilings — draws, material changes,
|
|
6
|
-
* effect batch and
|
|
7
|
-
* `console.warn` for the lifetime of the renderer. WebGL2 holds none of them and
|
|
8
|
-
* So a scene over a ceiling renders differently on the two backends, silently,
|
|
9
|
-
* developing against WebGL2
|
|
4
|
+
* **This exists because a ceiling firing was unobservable.** The WebGPU backend holds fourteen
|
|
5
|
+
* per-frame ceilings — draws, material changes, two kinds of shadow draw, water bodies, light
|
|
6
|
+
* volumes, four kinds of effect batch and four kinds of overlay — and past any of them it skips the
|
|
7
|
+
* work and writes one `console.warn` for the lifetime of the renderer. WebGL2 holds none of them and
|
|
8
|
+
* draws everything. So a scene over a ceiling renders differently on the two backends, silently,
|
|
9
|
+
* and a consumer developing against WebGL2 had no way to see it coming — which is why WebGL2 counts
|
|
10
|
+
* the same fifteen lines by the same rules, and reports the number the other backend rations.
|
|
10
11
|
*
|
|
11
12
|
* **The cost of that was measured from outside.** A consumer spent weeks on ground that
|
|
12
13
|
* vanished and reappeared as the camera moved; its own report still lists, as the decisive
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* What a frame asked of a backend, against what that backend allows.
|
|
3
3
|
*
|
|
4
|
-
* **This exists because a ceiling firing was unobservable.** The WebGPU backend holds
|
|
5
|
-
* ceilings — draws, material changes,
|
|
6
|
-
* effect batch and
|
|
7
|
-
* `console.warn` for the lifetime of the renderer. WebGL2 holds none of them and
|
|
8
|
-
* So a scene over a ceiling renders differently on the two backends, silently,
|
|
9
|
-
* developing against WebGL2
|
|
4
|
+
* **This exists because a ceiling firing was unobservable.** The WebGPU backend holds fourteen
|
|
5
|
+
* per-frame ceilings — draws, material changes, two kinds of shadow draw, water bodies, light
|
|
6
|
+
* volumes, four kinds of effect batch and four kinds of overlay — and past any of them it skips the
|
|
7
|
+
* work and writes one `console.warn` for the lifetime of the renderer. WebGL2 holds none of them and
|
|
8
|
+
* draws everything. So a scene over a ceiling renders differently on the two backends, silently,
|
|
9
|
+
* and a consumer developing against WebGL2 had no way to see it coming — which is why WebGL2 counts
|
|
10
|
+
* the same fifteen lines by the same rules, and reports the number the other backend rations.
|
|
10
11
|
*
|
|
11
12
|
* **The cost of that was measured from outside.** A consumer spent weeks on ground that
|
|
12
13
|
* vanished and reappeared as the camera moved; its own report still lists, as the decisive
|
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
import { type RenderQualityOptions } from '../renderQuality.ts';
|
|
2
2
|
import type { RenderBackend, RendererApi } from './api.ts';
|
|
3
3
|
import { type SplashOptions } from '../../ui/splash.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Which of the two pipelines is drawing.
|
|
6
|
+
*
|
|
7
|
+
* A union rather than a boolean because a third is foreseeable and a boolean named for one of them
|
|
8
|
+
* is what makes the third awkward — `ROADMAP.md`'s own note about `hdrScene` starting life as
|
|
9
|
+
* `bool hdr`.
|
|
10
|
+
*/
|
|
11
|
+
export type RenderPipeline = 'forward' | 'gpu-driven';
|
|
12
|
+
/**
|
|
13
|
+
* What a caller who says nothing gets.
|
|
14
|
+
*
|
|
15
|
+
* **A named constant rather than a literal in the `??`**, because the literal is unreachable from
|
|
16
|
+
* a test here: nothing in this environment resolves a renderer, so flipping it changed no answer
|
|
17
|
+
* and no test noticed. The constant is where the decision lives and it is asserted directly.
|
|
18
|
+
*
|
|
19
|
+
* Forward, and it stays forward until the second pipeline has drawn the six published scenes.
|
|
20
|
+
*/
|
|
21
|
+
export declare const DEFAULT_PIPELINE: RenderPipeline;
|
|
22
|
+
/**
|
|
23
|
+
* Why a requested pipeline cannot run on the backend that is about to draw, or null where it can.
|
|
24
|
+
*
|
|
25
|
+
* **Its own function because it is the only part of the decision a test in this environment can
|
|
26
|
+
* reach.** Nothing here can resolve a renderer — there is no GL context and no adapter — so every
|
|
27
|
+
* test of `createRenderer` ends in a rejection, and a check that lives only inside the factory is
|
|
28
|
+
* a check nothing exercises. `built` is this function's one caller and every return from the
|
|
29
|
+
* factory passes through it.
|
|
30
|
+
*
|
|
31
|
+
* **The backend is the one that will draw, not the one that was asked for.** Three paths into
|
|
32
|
+
* `built` arrive having fallen back from WebGPU, and a check written against the request passes on
|
|
33
|
+
* all three.
|
|
34
|
+
*/
|
|
35
|
+
export declare function pipelineRefusal(pipeline: RenderPipeline, backend: RenderBackend, reason: string): string | null;
|
|
4
36
|
/** Everything about selection a caller may want to decide instead of inherit. */
|
|
5
37
|
export interface CreateRendererOptions {
|
|
6
38
|
/**
|
|
@@ -19,6 +51,23 @@ export interface CreateRendererOptions {
|
|
|
19
51
|
* shows that, and the fallback is silent when it happens.
|
|
20
52
|
*/
|
|
21
53
|
readonly preferWebGpu?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Which pipeline to draw with. **Defaults to `'forward'`.**
|
|
56
|
+
*
|
|
57
|
+
* `'gpu-driven'` selects the cluster pipeline: instances and clusters culled on the device
|
|
58
|
+
* against a depth pyramid built this frame, a visibility buffer, and one shading dispatch per
|
|
59
|
+
* material. It needs indirect draws and dispatches, which WebGL2 does not have.
|
|
60
|
+
*
|
|
61
|
+
* **Asking for it where it cannot run throws.** Not a warning and not a fallback: a silent
|
|
62
|
+
* fallback means a consumer ships believing they have a pipeline they do not, and the difference
|
|
63
|
+
* only shows as a frame time on somebody else's machine. The throw carries the reason in words,
|
|
64
|
+
* from `gpuDrivenRefusal`.
|
|
65
|
+
*
|
|
66
|
+
* **This includes a WebGPU request that fell back**, which is the case a check written against
|
|
67
|
+
* the *asked-for* backend would miss: every fallback path here is a path where the pipeline
|
|
68
|
+
* became unavailable after the choice was made.
|
|
69
|
+
*/
|
|
70
|
+
readonly pipeline?: RenderPipeline;
|
|
22
71
|
/**
|
|
23
72
|
* The query string to read `?backend=` from. Defaults to the document's own.
|
|
24
73
|
*
|
|
@@ -116,6 +165,14 @@ export interface CreatedRenderer {
|
|
|
116
165
|
* renderer knows.
|
|
117
166
|
*/
|
|
118
167
|
readonly reversedDepth: boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Which pipeline is drawing: the forward path, or the one driven from buffers the GPU wrote.
|
|
170
|
+
*
|
|
171
|
+
* Reported for the same reason `backend` is — a consumer who asked for one and got the other
|
|
172
|
+
* has to be able to find out. They cannot, here: asking for `gpu-driven` on a backend that
|
|
173
|
+
* cannot run it throws rather than answering `forward`. See `CreateRendererOptions.pipeline`.
|
|
174
|
+
*/
|
|
175
|
+
readonly pipeline: RenderPipeline;
|
|
119
176
|
}
|
|
120
177
|
/**
|
|
121
178
|
* Build a renderer on the best backend this browser will actually give us.
|
|
@@ -3,6 +3,35 @@ import { resolveRenderQuality } from '../renderQuality.js';
|
|
|
3
3
|
import { BACKEND_TIMEOUT_MS, forcedBackend, selectBackend } from './select.js';
|
|
4
4
|
import { TIMED_OUT, withDeadline } from './deadline.js';
|
|
5
5
|
import { mountSplash } from '../../ui/splash.js';
|
|
6
|
+
import { gpuDrivenRefusal, gpuDrivenSupported } from '../gpudriven/pipeline.js';
|
|
7
|
+
/**
|
|
8
|
+
* What a caller who says nothing gets.
|
|
9
|
+
*
|
|
10
|
+
* **A named constant rather than a literal in the `??`**, because the literal is unreachable from
|
|
11
|
+
* a test here: nothing in this environment resolves a renderer, so flipping it changed no answer
|
|
12
|
+
* and no test noticed. The constant is where the decision lives and it is asserted directly.
|
|
13
|
+
*
|
|
14
|
+
* Forward, and it stays forward until the second pipeline has drawn the six published scenes.
|
|
15
|
+
*/
|
|
16
|
+
export const DEFAULT_PIPELINE = 'forward';
|
|
17
|
+
/**
|
|
18
|
+
* Why a requested pipeline cannot run on the backend that is about to draw, or null where it can.
|
|
19
|
+
*
|
|
20
|
+
* **Its own function because it is the only part of the decision a test in this environment can
|
|
21
|
+
* reach.** Nothing here can resolve a renderer — there is no GL context and no adapter — so every
|
|
22
|
+
* test of `createRenderer` ends in a rejection, and a check that lives only inside the factory is
|
|
23
|
+
* a check nothing exercises. `built` is this function's one caller and every return from the
|
|
24
|
+
* factory passes through it.
|
|
25
|
+
*
|
|
26
|
+
* **The backend is the one that will draw, not the one that was asked for.** Three paths into
|
|
27
|
+
* `built` arrive having fallen back from WebGPU, and a check written against the request passes on
|
|
28
|
+
* all three.
|
|
29
|
+
*/
|
|
30
|
+
export function pipelineRefusal(pipeline, backend, reason) {
|
|
31
|
+
if (pipeline !== 'gpu-driven' || gpuDrivenSupported(backend))
|
|
32
|
+
return null;
|
|
33
|
+
return `[driftengine] ${gpuDrivenRefusal(backend)} (${reason})`;
|
|
34
|
+
}
|
|
6
35
|
/**
|
|
7
36
|
* Hand the badge the one fact it is waiting for: a frame reached the screen.
|
|
8
37
|
*
|
|
@@ -60,7 +89,22 @@ export async function createRenderer(canvas, quality = {}, options = {}) {
|
|
|
60
89
|
* the two failure paths — a fallback still paints, and a badge that outlived a fallback would
|
|
61
90
|
* sit on the screen until the cap for a game that was running perfectly well underneath it.
|
|
62
91
|
*/
|
|
92
|
+
const pipeline = options.pipeline ?? DEFAULT_PIPELINE;
|
|
63
93
|
const built = (result) => {
|
|
94
|
+
/*
|
|
95
|
+
* **Checked here rather than at the top, because every return passes through here.** The
|
|
96
|
+
* question is not which backend was *asked for* — it is which one is about to draw, and three
|
|
97
|
+
* of the paths into this function arrive having fallen back. A check against the request would
|
|
98
|
+
* pass on all three and hand back a forward renderer with `pipeline: 'gpu-driven'` on it.
|
|
99
|
+
*
|
|
100
|
+
* The splash goes down first. A page that throws out of `createRenderer` with a badge mounted
|
|
101
|
+
* leaves it on screen over nothing, for as long as the tab is open.
|
|
102
|
+
*/
|
|
103
|
+
const refused = pipelineRefusal(pipeline, result.backend, result.reason);
|
|
104
|
+
if (refused !== null) {
|
|
105
|
+
splash?.present();
|
|
106
|
+
throw new Error(refused);
|
|
107
|
+
}
|
|
64
108
|
if (splash !== null)
|
|
65
109
|
presentOnFirstFrame(result.renderer, splash);
|
|
66
110
|
/*
|
|
@@ -80,6 +124,7 @@ export async function createRenderer(canvas, quality = {}, options = {}) {
|
|
|
80
124
|
...result,
|
|
81
125
|
rendererName: result.renderer.rendererName,
|
|
82
126
|
reversedDepth: result.renderer.reversedDepth,
|
|
127
|
+
pipeline,
|
|
83
128
|
};
|
|
84
129
|
};
|
|
85
130
|
/*
|
|
@@ -93,7 +138,11 @@ export async function createRenderer(canvas, quality = {}, options = {}) {
|
|
|
93
138
|
* the promise the deadline was racing.
|
|
94
139
|
*/
|
|
95
140
|
const budgetMs = options.backendTimeoutMs ?? BACKEND_TIMEOUT_MS;
|
|
96
|
-
|
|
141
|
+
/* Monotonic, and it has to be: `budgetMs - spent` below subtracts two readings. The wall clock
|
|
142
|
+
steps — daylight saving, an NTP correction, a laptop resuming with a stale clock — and a
|
|
143
|
+
forward step makes `spent` exceed the budget, so the engine falls back to WebGL2 reporting
|
|
144
|
+
"WebGPU stalled" about a device that was fine. */
|
|
145
|
+
const startedAt = performance.now();
|
|
97
146
|
const choice = await selectBackend(search, options.preferWebGpu ?? true, quality.gpuTiming ?? false, options.probeShaders ?? [], budgetMs);
|
|
98
147
|
if (choice.backend === 'webgpu' && choice.device !== null) {
|
|
99
148
|
/*
|
|
@@ -131,7 +180,7 @@ export async function createRenderer(canvas, quality = {}, options = {}) {
|
|
|
131
180
|
stage = 'constructing the renderer';
|
|
132
181
|
return { surface, WebGPURenderer };
|
|
133
182
|
})();
|
|
134
|
-
const spent =
|
|
183
|
+
const spent = performance.now() - startedAt;
|
|
135
184
|
const settled = await withDeadline(construction, budgetMs - spent);
|
|
136
185
|
if (settled === TIMED_OUT) {
|
|
137
186
|
device.destroy();
|