@pexip/media-processor 20.3.4 → 21.0.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.md +47 -0
- package/api-docs/README.mdx +438 -0
- package/api-docs/enumerations/AbortReason.mdx +5 -0
- package/api-docs/functions/avg.mdx +15 -0
- package/api-docs/functions/calculateDistance.mdx +18 -0
- package/api-docs/functions/closedCurve.mdx +27 -0
- package/api-docs/functions/copyByteBufferToFloatBuffer.mdx +16 -0
- package/api-docs/functions/createAnalyzerGraphNode.mdx +19 -0
- package/api-docs/functions/createAnalyzerSubscribableGraphNode.mdx +15 -0
- package/api-docs/functions/createAsyncCallbackLoop.mdx +35 -0
- package/api-docs/functions/createAudioContext.mdx +22 -0
- package/api-docs/functions/createAudioDestinationGraphNode.mdx +9 -0
- package/api-docs/functions/createAudioGraph.mdx +28 -0
- package/api-docs/functions/createAudioGraphProxy.mdx +14 -0
- package/api-docs/functions/createAudioSignalDetector.mdx +51 -0
- package/api-docs/functions/createAudioStats.mdx +19 -0
- package/api-docs/functions/createBenchmark.mdx +26 -0
- package/api-docs/functions/createCanvas.mdx +16 -0
- package/api-docs/functions/createCanvasTransform.mdx +14 -0
- package/api-docs/functions/createChannelMergerGraphNode.mdx +19 -0
- package/api-docs/functions/createChannelSplitterGraphNode.mdx +19 -0
- package/api-docs/functions/createDelayGraphNode.mdx +19 -0
- package/api-docs/functions/createDenoiseWorkletGraphNode.mdx +16 -0
- package/api-docs/functions/createFrameCallbackRequest.mdx +29 -0
- package/api-docs/functions/createGainGraphNode.mdx +15 -0
- package/api-docs/functions/createMediaElementSourceGraphNode.mdx +15 -0
- package/api-docs/functions/createSegmenter.mdx +14 -0
- package/api-docs/functions/createStreamDestinationGraphNode.mdx +15 -0
- package/api-docs/functions/createStreamSourceGraphNode.mdx +16 -0
- package/api-docs/functions/createVADetector.mdx +54 -0
- package/api-docs/functions/createVideoProcessor.mdx +14 -0
- package/api-docs/functions/createVideoTrackProcessor.mdx +9 -0
- package/api-docs/functions/createVideoTrackProcessorWithFallback.mdx +15 -0
- package/api-docs/functions/createVoiceDetectorFromProbability.mdx +15 -0
- package/api-docs/functions/createVoiceDetectorFromTimeData.mdx +19 -0
- package/api-docs/functions/createWindowedStats.mdx +23 -0
- package/api-docs/functions/curve.mdx +15 -0
- package/api-docs/functions/fromByteToFloat.mdx +27 -0
- package/api-docs/functions/fromFloatToByte.mdx +27 -0
- package/api-docs/functions/getAudioStats.mdx +19 -0
- package/api-docs/functions/getBezierCurveControlPoints.mdx +26 -0
- package/api-docs/functions/iou.mdx +19 -0
- package/api-docs/functions/isAnalyzerNodeInit.mdx +13 -0
- package/api-docs/functions/isAudioNode.mdx +13 -0
- package/api-docs/functions/isAudioNodeInit.mdx +13 -0
- package/api-docs/functions/isAudioParam.mdx +13 -0
- package/api-docs/functions/isClipping.mdx +18 -0
- package/api-docs/functions/isEqualSize.mdx +22 -0
- package/api-docs/functions/isLowVolume.mdx +19 -0
- package/api-docs/functions/isMono.mdx +22 -0
- package/api-docs/functions/isRenderEffects.mdx +13 -0
- package/api-docs/functions/isSilent.mdx +22 -0
- package/api-docs/functions/isVoiceActivity.mdx +29 -0
- package/api-docs/functions/labelComponents.mdx +20 -0
- package/api-docs/functions/line.mdx +15 -0
- package/api-docs/functions/loadScript.mdx +14 -0
- package/api-docs/functions/loadWasms.mdx +13 -0
- package/api-docs/functions/nearestPowerOfTwo.mdx +21 -0
- package/api-docs/functions/playVideo.mdx +16 -0
- package/api-docs/functions/pow.mdx +29 -0
- package/api-docs/functions/processAverageVolume.mdx +15 -0
- package/api-docs/functions/resumeAudioOnInterruption.mdx +23 -0
- package/api-docs/functions/resumeAudioOnUnmute.mdx +27 -0
- package/api-docs/functions/rms.mdx +15 -0
- package/api-docs/functions/round.mdx +23 -0
- package/api-docs/functions/scoreComponent.mdx +22 -0
- package/api-docs/functions/setVideoElementSrc.mdx +14 -0
- package/api-docs/functions/subscribeTimeoutAnalyzerNode.mdx +22 -0
- package/api-docs/functions/subscribeWorkletNode.mdx +28 -0
- package/api-docs/functions/sum.mdx +15 -0
- package/api-docs/functions/toDecibel.mdx +18 -0
- package/api-docs/interfaces/Analyzer.mdx +368 -0
- package/api-docs/interfaces/AnalyzerSubscribableOptions.mdx +11 -0
- package/api-docs/interfaces/AsyncAssets.mdx +7 -0
- package/api-docs/interfaces/AudioGraph.mdx +92 -0
- package/api-docs/interfaces/AudioGraphOptions.mdx +6 -0
- package/api-docs/interfaces/AudioNodeInit.mdx +127 -0
- package/api-docs/interfaces/AudioNodeProps.mdx +15 -0
- package/api-docs/interfaces/AudioStats.mdx +16 -0
- package/api-docs/interfaces/BackgroundImage.mdx +6 -0
- package/api-docs/interfaces/Benchmark.mdx +47 -0
- package/api-docs/interfaces/Clock.mdx +11 -0
- package/api-docs/interfaces/Denoise.mdx +50 -0
- package/api-docs/interfaces/Detector.mdx +81 -0
- package/api-docs/interfaces/Frame.mdx +11 -0
- package/api-docs/interfaces/Gain.mdx +227 -0
- package/api-docs/interfaces/ImageRecord.mdx +6 -0
- package/api-docs/interfaces/ImageSegmenterOptions.mdx +8 -0
- package/api-docs/interfaces/MPMask.mdx +145 -0
- package/api-docs/interfaces/Point.mdx +10 -0
- package/api-docs/interfaces/Process.mdx +46 -0
- package/api-docs/interfaces/ProcessEventClose.mdx +7 -0
- package/api-docs/interfaces/ProcessEventDebug.mdx +14 -0
- package/api-docs/interfaces/ProcessEventDestroy.mdx +7 -0
- package/api-docs/interfaces/ProcessEventOpen.mdx +14 -0
- package/api-docs/interfaces/ProcessEventProcess.mdx +14 -0
- package/api-docs/interfaces/ProcessEventUpdate.mdx +14 -0
- package/api-docs/interfaces/ProcessWorkerDebugMessage.mdx +6 -0
- package/api-docs/interfaces/ProcessWorkerEvent.mdx +12 -0
- package/api-docs/interfaces/ProcessWorkerEventDebug.mdx +12 -0
- package/api-docs/interfaces/ProcessWorkerEventOpened.mdx +5 -0
- package/api-docs/interfaces/ProcessWorkerEventProcessed.mdx +12 -0
- package/api-docs/interfaces/ProcessWorkerEventUpdated.mdx +5 -0
- package/api-docs/interfaces/ProcessorEvent.mdx +7 -0
- package/api-docs/interfaces/ProcessorOptions.mdx +16 -0
- package/api-docs/interfaces/ProcessorProcessOptions.mdx +6 -0
- package/api-docs/interfaces/Rect.mdx +8 -0
- package/api-docs/interfaces/RenderEventHandlers.mdx +7 -0
- package/api-docs/interfaces/Renderer.mdx +64 -0
- package/api-docs/interfaces/RendererOptions.mdx +32 -0
- package/api-docs/interfaces/Runner.mdx +41 -0
- package/api-docs/interfaces/Segmentation.mdx +5 -0
- package/api-docs/interfaces/SegmentationModelAsset.mdx +8 -0
- package/api-docs/interfaces/SegmentationParams.mdx +35 -0
- package/api-docs/interfaces/SegmentationSmoothingConfig.mdx +5 -0
- package/api-docs/interfaces/Segmenter.mdx +121 -0
- package/api-docs/interfaces/SegmenterOptions.mdx +13 -0
- package/api-docs/interfaces/SelectionOptions.mdx +15 -0
- package/api-docs/interfaces/Size.mdx +10 -0
- package/api-docs/interfaces/Stats.mdx +11 -0
- package/api-docs/interfaces/StatsOptions.mdx +10 -0
- package/api-docs/interfaces/SubscribableOptions.mdx +9 -0
- package/api-docs/interfaces/ThrottleOptions.mdx +8 -0
- package/api-docs/interfaces/Transform.mdx +62 -0
- package/api-docs/interfaces/VideoFrameLike.mdx +8 -0
- package/api-docs/interfaces/VideoProcessor.mdx +38 -0
- package/api-docs/interfaces/Weights.mdx +12 -0
- package/api-docs/interfaces/WorkletMessagePortOptions.mdx +16 -0
- package/api-docs/interfaces/WorkletModule.mdx +6 -0
- package/api-docs/type-aliases/AnalyzerNodeInit.mdx +3 -0
- package/api-docs/type-aliases/AsyncCallback.mdx +7 -0
- package/api-docs/type-aliases/AudioBufferBytes.mdx +5 -0
- package/api-docs/type-aliases/AudioBufferFloats.mdx +6 -0
- package/api-docs/type-aliases/AudioDestinationNodeInit.mdx +3 -0
- package/api-docs/type-aliases/AudioNodeConnectParam.mdx +3 -0
- package/api-docs/type-aliases/AudioNodeInitConnectParam.mdx +3 -0
- package/api-docs/type-aliases/AudioNodeInitConnection.mdx +3 -0
- package/api-docs/type-aliases/AudioNodeInitConnections.mdx +3 -0
- package/api-docs/type-aliases/AudioNodeParam.mdx +3 -0
- package/api-docs/type-aliases/AudioSamples.mdx +17 -0
- package/api-docs/type-aliases/BaseAudioNode.mdx +3 -0
- package/api-docs/type-aliases/Callback.mdx +20 -0
- package/api-docs/type-aliases/Canvas.mdx +3 -0
- package/api-docs/type-aliases/CanvasContext.mdx +3 -0
- package/api-docs/type-aliases/ChannelSplitterNodeInit.mdx +3 -0
- package/api-docs/type-aliases/Color.mdx +12 -0
- package/api-docs/type-aliases/ConnectInitParamBaseType.mdx +3 -0
- package/api-docs/type-aliases/ConnectInitParamType.mdx +3 -0
- package/api-docs/type-aliases/ConnectParamBase.mdx +11 -0
- package/api-docs/type-aliases/ConnectParamBaseType.mdx +3 -0
- package/api-docs/type-aliases/ConnectParamType.mdx +3 -0
- package/api-docs/type-aliases/DelayNodeInit.mdx +3 -0
- package/api-docs/type-aliases/Delegate.mdx +3 -0
- package/api-docs/type-aliases/DenoiseWorkletNodeInit.mdx +3 -0
- package/api-docs/type-aliases/ExtractMessageEventType.mdx +9 -0
- package/api-docs/type-aliases/GainNodeInit.mdx +3 -0
- package/api-docs/type-aliases/ImageMapIterable.mdx +3 -0
- package/api-docs/type-aliases/ImageType.mdx +6 -0
- package/api-docs/type-aliases/IncludeMessageEventDataType.mdx +10 -0
- package/api-docs/type-aliases/InputFrame.mdx +3 -0
- package/api-docs/type-aliases/IsVoice.mdx +19 -0
- package/api-docs/type-aliases/MediaElementAudioSourceNodeInit.mdx +3 -0
- package/api-docs/type-aliases/MediaStreamAudioDestinationNodeInit.mdx +3 -0
- package/api-docs/type-aliases/MediaStreamAudioSourceNodeInit.mdx +3 -0
- package/api-docs/type-aliases/Node.mdx +3 -0
- package/api-docs/type-aliases/NodeConnectionAction.mdx +3 -0
- package/api-docs/type-aliases/Nodes.mdx +3 -0
- package/api-docs/type-aliases/OptionalKeys.mdx +10 -0
- package/api-docs/type-aliases/ProcessEvents.mdx +17 -0
- package/api-docs/type-aliases/ProcessInputType.mdx +3 -0
- package/api-docs/type-aliases/ProcessStatus.mdx +3 -0
- package/api-docs/type-aliases/ProcessVideoTrack.mdx +15 -0
- package/api-docs/type-aliases/ProcessWorkerEvents.mdx +18 -0
- package/api-docs/type-aliases/ProcessorEvents.mdx +3 -0
- package/api-docs/type-aliases/ProcessorWorkerEvents.mdx +3 -0
- package/api-docs/type-aliases/RenderBackend.mdx +3 -0
- package/api-docs/type-aliases/RenderEffects.mdx +3 -0
- package/api-docs/type-aliases/RenderingEvents.mdx +3 -0
- package/api-docs/type-aliases/RunnerCreator.mdx +21 -0
- package/api-docs/type-aliases/SegmentationModel.mdx +3 -0
- package/api-docs/type-aliases/SegmentationTransform.mdx +3 -0
- package/api-docs/type-aliases/TupleOf.mdx +12 -0
- package/api-docs/type-aliases/UniversalAudioContextState.mdx +6 -0
- package/api-docs/type-aliases/Unsubscribe.mdx +9 -0
- package/api-docs/type-aliases/WasmPaths.mdx +3 -0
- package/api-docs/variables/BACKGROUND_BLUR_AMOUNT.mdx +3 -0
- package/api-docs/variables/BACKGROUND_THRESHOLD.mdx +3 -0
- package/api-docs/variables/CLIP_COUNT_THRESHOLD.mdx +6 -0
- package/api-docs/variables/CLIP_THRESHOLD.mdx +5 -0
- package/api-docs/variables/DOWN_SAMPLE_FACTOR.mdx +3 -0
- package/api-docs/variables/EDGE_BLUR_AMOUNT.mdx +3 -0
- package/api-docs/variables/EXCLUDE_BYSTANDERS.mdx +3 -0
- package/api-docs/variables/FOREGROUND_THRESHOLD.mdx +3 -0
- package/api-docs/variables/FRAME_RATE.mdx +3 -0
- package/api-docs/variables/LIGHT_WRAP_BLUR_AMOUNT.mdx +3 -0
- package/api-docs/variables/LIGHT_WRAP_EDGE_BAND.mdx +3 -0
- package/api-docs/variables/LIGHT_WRAP_INTENSITY.mdx +3 -0
- package/api-docs/variables/LIGHT_WRAP_TIGHTNESS.mdx +3 -0
- package/api-docs/variables/LOW_VOLUME_THRESHOLD.mdx +5 -0
- package/api-docs/variables/MASK_COMBINE_RATIO.mdx +3 -0
- package/api-docs/variables/MONO_THRESHOLD.mdx +6 -0
- package/api-docs/variables/MORPH_DILATE_RADIUS_PX.mdx +3 -0
- package/api-docs/variables/MORPH_ERODE_RADIUS_PX.mdx +3 -0
- package/api-docs/variables/MORPH_PASS.mdx +3 -0
- package/api-docs/variables/PERSON_CENTER.mdx +3 -0
- package/api-docs/variables/PLAY_VIDEO_TIMEOUT.mdx +3 -0
- package/api-docs/variables/PROCESSING_HEIGHT.mdx +3 -0
- package/api-docs/variables/PROCESSING_WIDTH.mdx +3 -0
- package/api-docs/variables/PROCESS_STATUS.mdx +22 -0
- package/api-docs/variables/RENDERING_EVENTS.mdx +14 -0
- package/api-docs/variables/RENDER_BACKEND.mdx +10 -0
- package/api-docs/variables/RENDER_EFFECT.mdx +11 -0
- package/api-docs/variables/SEGMENTATION_MODELS.mdx +10 -0
- package/api-docs/variables/SIGMA_RANGE.mdx +3 -0
- package/api-docs/variables/SIGMA_SPACE.mdx +3 -0
- package/api-docs/variables/SILENT_THRESHOLD.mdx +6 -0
- package/api-docs/variables/STRONG_EDGE_BLUR_AMOUNT.mdx +3 -0
- package/api-docs/variables/VOICE_PROBABILITY_THRESHOLD.mdx +5 -0
- package/api-docs/variables/calculateMaxBlurPass.mdx +13 -0
- package/api-docs/variables/clamping.mdx +26 -0
- package/api-docs/variables/createLazyProps.mdx +19 -0
- package/api-docs/variables/createObjectUpdater.mdx +31 -0
- package/api-docs/variables/createRemoteImageBitmap.mdx +21 -0
- package/api-docs/variables/getCanvasRenderingContext2D.mdx +14 -0
- package/api-docs/variables/getErrorMessage.mdx +13 -0
- package/api-docs/variables/getImageSize.mdx +13 -0
- package/api-docs/variables/handleWebGLContextLoss.mdx +21 -0
- package/api-docs/variables/isRenderingEvents.mdx +13 -0
- package/api-docs/variables/isSegmentationModel.mdx +13 -0
- package/api-docs/variables/resize.mdx +30 -0
- package/api-docs/variables/toRenderingEvents.mdx +13 -0
- package/api-docs/variables/urls.mdx +10 -0
- package/dist/common/backends/webgl/binaryMask.d.ts +8 -0
- package/dist/common/backends/webgl/binaryMask.js +95 -0
- package/dist/common/backends/webgl/blender.d.ts +2 -1
- package/dist/common/backends/webgl/blender.js +18 -15
- package/dist/common/backends/webgl/blur.d.ts +1 -1
- package/dist/common/backends/webgl/blur.js +23 -16
- package/dist/common/backends/webgl/canvas.js +9 -4
- package/dist/common/backends/webgl/diffAbsMask.d.ts +10 -0
- package/dist/common/backends/webgl/diffAbsMask.js +103 -0
- package/dist/common/backends/webgl/geodesicReconstruction.d.ts +13 -0
- package/dist/common/backends/webgl/geodesicReconstruction.js +176 -0
- package/dist/common/backends/webgl/jointBilateralFilter.d.ts +12 -0
- package/dist/common/backends/webgl/jointBilateralFilter.js +108 -0
- package/dist/common/backends/webgl/morphErode.d.ts +13 -0
- package/dist/common/backends/webgl/morphErode.js +121 -0
- package/dist/common/backends/webgl/renderer.js +194 -34
- package/dist/common/backends/webgl/replace.d.ts +17 -0
- package/dist/common/backends/webgl/replace.js +126 -0
- package/dist/common/backends/webgl/selectComponent.d.ts +15 -0
- package/dist/common/backends/webgl/selectComponent.js +102 -0
- package/dist/common/backends/webgl/smoothingMask.d.ts +3 -3
- package/dist/common/backends/webgl/smoothingMask.js +22 -21
- package/dist/common/backends/webgl/tentBlur.d.ts +9 -0
- package/dist/common/backends/webgl/tentBlur.js +118 -0
- package/dist/common/backends/webgl/texture.d.ts +1 -1
- package/dist/common/backends/webgl/texture.js +19 -17
- package/dist/common/backends/webgl/textureToTexture.d.ts +1 -1
- package/dist/common/backends/webgl/textureToTexture.js +19 -16
- package/dist/common/backends/webgl/webglUtils.d.ts +7 -1
- package/dist/common/backends/webgl/webglUtils.js +64 -6
- package/dist/common/backends/webgpu/blender.d.ts +6 -1
- package/dist/common/backends/webgpu/blender.js +96 -51
- package/dist/common/backends/webgpu/constants.js +1 -1
- package/dist/common/backends/webgpu/dualFilterBlur.d.ts +2 -3
- package/dist/common/backends/webgpu/dualFilterBlur.js +146 -140
- package/dist/common/backends/webgpu/jointBilateralFilter.d.ts +7 -0
- package/dist/common/backends/webgpu/jointBilateralFilter.js +162 -0
- package/dist/common/backends/webgpu/renderer.js +211 -39
- package/dist/common/backends/webgpu/replace.d.ts +11 -0
- package/dist/common/backends/webgpu/replace.js +175 -0
- package/dist/common/backends/webgpu/resize.d.ts +4 -0
- package/dist/common/backends/webgpu/resize.js +76 -0
- package/dist/common/backends/webgpu/smoothingMask.d.ts +2 -2
- package/dist/common/backends/webgpu/smoothingMask.js +74 -40
- package/dist/common/backends/webgpu/tentBlur.d.ts +5 -0
- package/dist/common/backends/webgpu/tentBlur.js +131 -0
- package/dist/common/backends/webgpu/texture.d.ts +2 -2
- package/dist/common/backends/webgpu/texture.js +24 -19
- package/dist/common/backends/webgpu/textureToTexture.d.ts +1 -1
- package/dist/common/backends/webgpu/textureToTexture.js +28 -15
- package/dist/common/backends/webgpu/types.d.ts +2 -0
- package/dist/common/backends/webgpu/webgpuUtils.d.ts +24 -4
- package/dist/common/backends/webgpu/webgpuUtils.js +60 -11
- package/dist/common/constants.d.ts +19 -5
- package/dist/common/constants.js +19 -5
- package/dist/common/index.d.ts +1 -0
- package/dist/common/index.js +1 -0
- package/dist/common/tsconfig.tsbuildinfo +1 -1
- package/dist/common/types/render.d.ts +142 -13
- package/dist/common/types/utils.d.ts +21 -0
- package/dist/common/utils.d.ts +16 -0
- package/dist/common/utils.js +152 -0
- package/dist/main/benchUtils.d.ts +33 -1
- package/dist/main/benchUtils.js +145 -11
- package/dist/main/tsconfig.tsbuildinfo +1 -1
- package/dist/main/video/canvasTransform.d.ts +1 -1
- package/dist/main/video/canvasTransform.js +135 -47
- package/dist/main/video/index.d.ts +1 -1
- package/dist/main/video/index.js +1 -1
- package/dist/workers/mediaWorker.js +35 -162
- package/dist/workers/tsconfig.tsbuildinfo +1 -1
- package/package.json +16 -10
- package/dist/common/backends/webgl/shaders/blendFragmentShader.d.ts +0 -1
- package/dist/common/backends/webgl/shaders/blendFragmentShader.js +0 -21
- package/dist/common/backends/webgl/shaders/dualFilterBlurFragmentShader.d.ts +0 -1
- package/dist/common/backends/webgl/shaders/dualFilterBlurFragmentShader.js +0 -45
- package/dist/common/backends/webgl/shaders/smoothingMaskFragmentShader.d.ts +0 -1
- package/dist/common/backends/webgl/shaders/smoothingMaskFragmentShader.js +0 -57
- package/dist/common/backends/webgl/shaders/textureFragmentShader.d.ts +0 -1
- package/dist/common/backends/webgl/shaders/textureFragmentShader.js +0 -16
- package/dist/common/backends/webgl/shaders/vertexShader.d.ts +0 -1
- package/dist/common/backends/webgl/shaders/vertexShader.js +0 -19
|
@@ -1,43 +1,95 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { assert } from '@pexip/utils';
|
|
2
|
+
import { PROCESSING_WIDTH, PROCESSING_HEIGHT, STRONG_EDGE_BLUR_AMOUNT, } from '../../constants';
|
|
2
3
|
import { createObjectUpdater, createLazyProps } from '../../utils';
|
|
3
4
|
import { createTextureRenderer } from './texture';
|
|
4
5
|
import { createBlendRenderer } from './blender';
|
|
5
|
-
import { getGPUDevice,
|
|
6
|
+
import { getGPUDevice, hasR16FloatTextureStorage, supportsTextureFormat, hasF16, } from './webgpuUtils';
|
|
6
7
|
import { createBlurRenderer } from './dualFilterBlur';
|
|
7
8
|
import { createSmoothingMaskRenderer } from './smoothingMask';
|
|
8
9
|
import { createTextureToTextureRenderer } from './textureToTexture';
|
|
10
|
+
import { createJointBilateralFilterRenderer } from './jointBilateralFilter';
|
|
11
|
+
import { createTextureResizeRenderer } from './resize';
|
|
12
|
+
import { createTentBlurRenderer } from './tentBlur';
|
|
13
|
+
import { createReplaceRenderer } from './replace';
|
|
9
14
|
export const createRenderer = (adapter, renderEventHandlers, canvas = new OffscreenCanvas(PROCESSING_WIDTH, PROCESSING_HEIGHT)) => {
|
|
15
|
+
const halfWidth = Math.trunc(canvas.width / 2);
|
|
16
|
+
const halfHeight = Math.trunc(canvas.height / 2);
|
|
17
|
+
const quarterWidth = Math.trunc(canvas.width / 4);
|
|
18
|
+
const quarterHeight = Math.trunc(canvas.height / 4);
|
|
19
|
+
const fullChannelTextureFormat = 'rgba8unorm';
|
|
10
20
|
const rendererCreator = {
|
|
21
|
+
edgeBlurRenderer: () => {
|
|
22
|
+
assert(props.device);
|
|
23
|
+
return createTentBlurRenderer(props.device, isContextLost, canvas.width, canvas.height, props.maskFormat, props.supportF16);
|
|
24
|
+
},
|
|
11
25
|
videoFrameRenderer: () => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
26
|
+
assert(props.device);
|
|
27
|
+
return createTextureRenderer(props.device, isContextLost, fullChannelTextureFormat, canvas.width, canvas.height, 'linear');
|
|
28
|
+
},
|
|
29
|
+
maskRenderer: () => {
|
|
30
|
+
assert(props.device);
|
|
31
|
+
return createTextureRenderer(props.device, isContextLost, props.maskFormat, canvas.width, canvas.height, 'nearest');
|
|
32
|
+
},
|
|
33
|
+
maskDownsampler2: () => {
|
|
34
|
+
assert(props.device);
|
|
35
|
+
return createTextureResizeRenderer(props.device, isContextLost, halfWidth, halfHeight, props.maskFormat, 'nearest');
|
|
36
|
+
},
|
|
37
|
+
maskDownsampler4: () => {
|
|
38
|
+
assert(props.device);
|
|
39
|
+
return createTextureResizeRenderer(props.device, isContextLost, quarterWidth, quarterHeight, props.maskFormat, 'nearest');
|
|
40
|
+
},
|
|
41
|
+
maskUpsampler: () => {
|
|
42
|
+
assert(props.device);
|
|
43
|
+
return createTextureResizeRenderer(props.device, isContextLost, canvas.width, canvas.height, props.maskFormat, 'nearest');
|
|
44
|
+
},
|
|
45
|
+
frameDownsampler2: () => {
|
|
46
|
+
assert(props.device);
|
|
47
|
+
return createTextureResizeRenderer(props.device, isContextLost, halfWidth, halfHeight, fullChannelTextureFormat, 'linear');
|
|
48
|
+
},
|
|
49
|
+
frameDownsampler4: () => {
|
|
50
|
+
assert(props.device);
|
|
51
|
+
return createTextureResizeRenderer(props.device, isContextLost, quarterWidth, quarterHeight, fullChannelTextureFormat, 'linear');
|
|
16
52
|
},
|
|
17
53
|
backgroundImageRenderer: () => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
54
|
+
assert(props.device);
|
|
55
|
+
return createTextureRenderer(props.device, isContextLost, fullChannelTextureFormat, canvas.width, canvas.height, 'linear');
|
|
56
|
+
},
|
|
57
|
+
blendRenderer: () => {
|
|
58
|
+
assert(props.device);
|
|
21
59
|
return createBlendRenderer(canvas, props.device, props.presentationFormat, isContextLost);
|
|
22
60
|
},
|
|
23
61
|
blurRenderer: () => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
return createBlurRenderer(canvas, props.device, props.presentationFormat, isContextLost);
|
|
62
|
+
assert(props.device);
|
|
63
|
+
return createBlurRenderer(props.device, canvas.width, canvas.height, fullChannelTextureFormat, isContextLost);
|
|
28
64
|
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
65
|
+
jointBilateralFilterRenderer2: () => {
|
|
66
|
+
assert(props.device);
|
|
67
|
+
return createJointBilateralFilterRenderer(canvas, props.device, isContextLost, halfWidth, halfHeight, props.maskFormat);
|
|
68
|
+
},
|
|
69
|
+
jointBilateralFilterRenderer4: () => {
|
|
70
|
+
assert(props.device);
|
|
71
|
+
return createJointBilateralFilterRenderer(canvas, props.device, isContextLost, quarterWidth, quarterHeight, props.maskFormat);
|
|
72
|
+
},
|
|
73
|
+
maskSmoothingRenderer2: () => {
|
|
74
|
+
assert(props.device);
|
|
75
|
+
return createSmoothingMaskRenderer(props.device, isContextLost, props.maskFormat, halfWidth, halfHeight, props.supportF16);
|
|
76
|
+
},
|
|
77
|
+
maskSmoothingRenderer4: () => {
|
|
78
|
+
assert(props.device);
|
|
79
|
+
return createSmoothingMaskRenderer(props.device, isContextLost, props.maskFormat, quarterWidth, quarterHeight, props.supportF16);
|
|
34
80
|
},
|
|
35
81
|
prevMaskRenderer: () => {
|
|
36
|
-
|
|
37
|
-
throw new Error('No device.');
|
|
38
|
-
}
|
|
82
|
+
assert(props.device);
|
|
39
83
|
return createTextureToTextureRenderer(props.device, isContextLost);
|
|
40
84
|
},
|
|
85
|
+
strongMaskBlurRenderer: () => {
|
|
86
|
+
assert(props.device);
|
|
87
|
+
return createBlurRenderer(props.device, canvas.width, canvas.height, props.maskFormat, isContextLost);
|
|
88
|
+
},
|
|
89
|
+
replaceRenderer: () => {
|
|
90
|
+
assert(props.device);
|
|
91
|
+
return createReplaceRenderer(canvas, props.device, props.presentationFormat, isContextLost);
|
|
92
|
+
},
|
|
41
93
|
release: (states) => () => {
|
|
42
94
|
for (const key of Object.keys(states)) {
|
|
43
95
|
key !== 'release' && states[key]?.release();
|
|
@@ -48,33 +100,80 @@ export const createRenderer = (adapter, renderEventHandlers, canvas = new Offscr
|
|
|
48
100
|
const props = {
|
|
49
101
|
canvas,
|
|
50
102
|
presentationFormat: 'rgba8unorm',
|
|
103
|
+
supportR16FloatTextureStorage: false,
|
|
104
|
+
maskFormat: 'rgba16float',
|
|
105
|
+
supportF16: false,
|
|
51
106
|
backend: 'webgpu',
|
|
52
107
|
deviceLost: false,
|
|
53
108
|
get videoFrameRenderer() {
|
|
54
109
|
return lazyProps.videoFrameRenderer;
|
|
55
110
|
},
|
|
111
|
+
get edgeBlurRenderer() {
|
|
112
|
+
return lazyProps.edgeBlurRenderer;
|
|
113
|
+
},
|
|
114
|
+
get maskRenderer() {
|
|
115
|
+
return lazyProps.maskRenderer;
|
|
116
|
+
},
|
|
117
|
+
get maskDownsampler2() {
|
|
118
|
+
return lazyProps.maskDownsampler2;
|
|
119
|
+
},
|
|
120
|
+
get maskDownsampler4() {
|
|
121
|
+
return lazyProps.maskDownsampler4;
|
|
122
|
+
},
|
|
123
|
+
get maskUpsampler() {
|
|
124
|
+
return lazyProps.maskUpsampler;
|
|
125
|
+
},
|
|
126
|
+
get frameDownsampler2() {
|
|
127
|
+
return lazyProps.frameDownsampler2;
|
|
128
|
+
},
|
|
129
|
+
get frameDownsampler4() {
|
|
130
|
+
return lazyProps.frameDownsampler4;
|
|
131
|
+
},
|
|
56
132
|
get blendRenderer() {
|
|
57
|
-
return lazyProps.
|
|
133
|
+
return lazyProps.blendRenderer;
|
|
58
134
|
},
|
|
59
135
|
get blurRenderer() {
|
|
60
136
|
return lazyProps.blurRenderer;
|
|
61
137
|
},
|
|
62
|
-
get
|
|
63
|
-
return lazyProps.
|
|
138
|
+
get backgroundImageRenderer() {
|
|
139
|
+
return lazyProps.backgroundImageRenderer;
|
|
140
|
+
},
|
|
141
|
+
get maskSmoothingRenderer2() {
|
|
142
|
+
return lazyProps.maskSmoothingRenderer2;
|
|
143
|
+
},
|
|
144
|
+
get maskSmoothingRenderer4() {
|
|
145
|
+
return lazyProps.maskSmoothingRenderer4;
|
|
64
146
|
},
|
|
65
147
|
get prevMaskRenderer() {
|
|
66
148
|
return lazyProps.prevMaskRenderer;
|
|
67
149
|
},
|
|
150
|
+
get jointBilateralFilterRenderer2() {
|
|
151
|
+
return lazyProps.jointBilateralFilterRenderer2;
|
|
152
|
+
},
|
|
153
|
+
get jointBilateralFilterRenderer4() {
|
|
154
|
+
return lazyProps.jointBilateralFilterRenderer4;
|
|
155
|
+
},
|
|
156
|
+
get strongMaskBlurRenderer() {
|
|
157
|
+
return lazyProps.strongMaskBlurRenderer;
|
|
158
|
+
},
|
|
159
|
+
get replaceRenderer() {
|
|
160
|
+
return lazyProps.replaceRenderer;
|
|
161
|
+
},
|
|
68
162
|
};
|
|
69
163
|
const updateProps = createObjectUpdater(props);
|
|
70
164
|
const init = async () => {
|
|
71
165
|
if (!navigator.gpu) {
|
|
72
166
|
throw Error('WebGPU not supported.');
|
|
73
167
|
}
|
|
74
|
-
props.presentationFormat =
|
|
75
|
-
? navigator.gpu.getPreferredCanvasFormat()
|
|
76
|
-
: 'rgba8unorm';
|
|
168
|
+
props.presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
77
169
|
props.device = await getGPUDevice(adapter);
|
|
170
|
+
props.supportR16FloatTextureStorage =
|
|
171
|
+
hasR16FloatTextureStorage(adapter) &&
|
|
172
|
+
supportsTextureFormat(props.device, 'r16float');
|
|
173
|
+
if (props.supportR16FloatTextureStorage) {
|
|
174
|
+
props.maskFormat = 'r16float';
|
|
175
|
+
}
|
|
176
|
+
props.supportF16 = hasF16(adapter);
|
|
78
177
|
props.device.lost.then(info => {
|
|
79
178
|
if (info.reason === 'destroyed') {
|
|
80
179
|
return;
|
|
@@ -88,34 +187,107 @@ export const createRenderer = (adapter, renderEventHandlers, canvas = new Offscr
|
|
|
88
187
|
if (options) {
|
|
89
188
|
updateProps(options);
|
|
90
189
|
}
|
|
91
|
-
|
|
92
|
-
const
|
|
190
|
+
assert(props.device);
|
|
191
|
+
const encoder = props.device.createCommandEncoder({
|
|
192
|
+
label: 'Renderer Encoder',
|
|
193
|
+
});
|
|
194
|
+
const frameUploadPass = encoder.beginComputePass({
|
|
195
|
+
label: 'frame upload pass',
|
|
196
|
+
});
|
|
197
|
+
const frameTexture = props.videoFrameRenderer.render(frame, frameUploadPass);
|
|
198
|
+
const maskTexture = props.maskRenderer.render({
|
|
93
199
|
frame: mask,
|
|
94
|
-
width:
|
|
95
|
-
height:
|
|
200
|
+
width: mask.width,
|
|
201
|
+
height: mask.height,
|
|
96
202
|
timestamp: frame.timestamp,
|
|
97
|
-
});
|
|
98
|
-
|
|
203
|
+
}, frameUploadPass);
|
|
204
|
+
frameUploadPass.end();
|
|
205
|
+
let smoothedMask;
|
|
206
|
+
let compositeInputMask;
|
|
207
|
+
switch (options.downSampleFactor) {
|
|
208
|
+
case 4: {
|
|
209
|
+
const downsamplePass = encoder.beginComputePass({
|
|
210
|
+
label: 'downsample pass',
|
|
211
|
+
});
|
|
212
|
+
const maskLowRes = props.maskDownsampler4.render(downsamplePass, maskTexture);
|
|
213
|
+
const frameLowRes = props.frameDownsampler4.render(downsamplePass, frameTexture);
|
|
214
|
+
downsamplePass.end();
|
|
215
|
+
const filteredMask = props.jointBilateralFilterRenderer4.render(encoder, maskLowRes, frameLowRes, options);
|
|
216
|
+
smoothedMask = props.maskSmoothingRenderer4.render(encoder, filteredMask, props.prevMask4 ?? filteredMask, options);
|
|
217
|
+
const upsamplePass = encoder.beginComputePass({
|
|
218
|
+
label: 'upsample pass',
|
|
219
|
+
});
|
|
220
|
+
const upsampledMask = props.maskUpsampler.render(upsamplePass, smoothedMask);
|
|
221
|
+
upsamplePass.end();
|
|
222
|
+
compositeInputMask = props.strongMaskBlurRenderer.render(encoder, upsampledMask, STRONG_EDGE_BLUR_AMOUNT);
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
default: {
|
|
226
|
+
const downsamplePass = encoder.beginComputePass({
|
|
227
|
+
label: 'downsample pass',
|
|
228
|
+
});
|
|
229
|
+
const maskLowRes = props.maskDownsampler2.render(downsamplePass, maskTexture);
|
|
230
|
+
const frameLowRes = props.frameDownsampler2.render(downsamplePass, frameTexture);
|
|
231
|
+
downsamplePass.end();
|
|
232
|
+
const filteredMask = props.jointBilateralFilterRenderer2.render(encoder, maskLowRes, frameLowRes, options);
|
|
233
|
+
smoothedMask = props.maskSmoothingRenderer2.render(encoder, filteredMask, props.prevMask2 ?? filteredMask, options);
|
|
234
|
+
const upsamplePass = encoder.beginComputePass({
|
|
235
|
+
label: 'upsample pass',
|
|
236
|
+
});
|
|
237
|
+
const upsampledMask = props.maskUpsampler.render(upsamplePass, smoothedMask);
|
|
238
|
+
upsamplePass.end();
|
|
239
|
+
compositeInputMask = props.edgeBlurRenderer.render(encoder, upsampledMask, options);
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
99
243
|
if (options.effects === 'blur') {
|
|
100
|
-
const blurredTexture = props.blurRenderer.render(
|
|
101
|
-
props.blendRenderer.render(
|
|
244
|
+
const blurredTexture = props.blurRenderer.render(encoder, frameTexture, options.backgroundBlurAmount);
|
|
245
|
+
props.blendRenderer.render(encoder, {
|
|
246
|
+
foreground: frameTexture,
|
|
247
|
+
background: blurredTexture,
|
|
248
|
+
mask: compositeInputMask,
|
|
249
|
+
}, options);
|
|
102
250
|
}
|
|
103
251
|
else if (options.effects === 'overlay') {
|
|
104
252
|
if (options.backgroundImage) {
|
|
105
|
-
const
|
|
253
|
+
const bgImgUploadPass = encoder.beginComputePass({
|
|
254
|
+
label: 'background image upload pass',
|
|
255
|
+
});
|
|
256
|
+
const bgTexture = props.backgroundImageRenderer.render({
|
|
106
257
|
frame: options.backgroundImage,
|
|
107
258
|
width: options.backgroundImage.width,
|
|
108
259
|
height: options.backgroundImage.height,
|
|
109
260
|
timestamp: frame.timestamp,
|
|
110
|
-
});
|
|
111
|
-
|
|
261
|
+
}, bgImgUploadPass);
|
|
262
|
+
bgImgUploadPass.end();
|
|
263
|
+
const blurredBackgroundImageTexture = props.blurRenderer.render(encoder, bgTexture, options.backgroundBlurAmount);
|
|
264
|
+
props.replaceRenderer.render(encoder, {
|
|
265
|
+
foreground: frameTexture,
|
|
266
|
+
background: bgTexture,
|
|
267
|
+
mask: compositeInputMask,
|
|
268
|
+
blurBackground: blurredBackgroundImageTexture,
|
|
269
|
+
timestamp: frame.timestamp,
|
|
270
|
+
}, options);
|
|
112
271
|
}
|
|
113
272
|
}
|
|
114
|
-
|
|
273
|
+
switch (options.downSampleFactor) {
|
|
274
|
+
case 4:
|
|
275
|
+
props.prevMask4 = props.prevMaskRenderer.render(encoder, smoothedMask);
|
|
276
|
+
break;
|
|
277
|
+
default:
|
|
278
|
+
props.prevMask2 = props.prevMaskRenderer.render(encoder, smoothedMask);
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
props.device.queue.submit([encoder.finish()]);
|
|
115
282
|
};
|
|
116
283
|
const release = () => {
|
|
117
284
|
lazyProps.release();
|
|
118
285
|
props.deviceLost = false;
|
|
286
|
+
props.prevMask2 = undefined;
|
|
287
|
+
props.prevMask4 = undefined;
|
|
288
|
+
props.presentationFormat = 'rgba8unorm';
|
|
289
|
+
props.supportR16FloatTextureStorage = false;
|
|
290
|
+
props.maskFormat = 'rgba16float';
|
|
119
291
|
lazyProps = createLazyProps(rendererCreator);
|
|
120
292
|
};
|
|
121
293
|
const isContextLost = () => props.deviceLost;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RendererOptions } from '../../types/render';
|
|
2
|
+
export declare const createReplaceRenderer: (processor: OffscreenCanvas, device: GPUDevice, presentationFormat: GPUTextureFormat, isContextLost: () => boolean) => {
|
|
3
|
+
render: (encoder: GPUCommandEncoder, { foreground, background, blurBackground, mask, timestamp, }: {
|
|
4
|
+
foreground: GPUTexture;
|
|
5
|
+
background: GPUTexture;
|
|
6
|
+
blurBackground: GPUTexture;
|
|
7
|
+
mask: GPUTexture;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
}, options: RendererOptions) => void;
|
|
10
|
+
release: () => void;
|
|
11
|
+
};
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { makeShaderDataDefinitions, makeStructuredView } from 'webgpu-utils';
|
|
2
|
+
import { assert } from '@pexip/utils';
|
|
3
|
+
import { RENDERING_EVENTS } from '../../constants';
|
|
4
|
+
import shaderCode from './shaders/replace.wgsl';
|
|
5
|
+
export const createReplaceRenderer = (processor, device, presentationFormat, isContextLost) => {
|
|
6
|
+
const context = processor.getContext('webgpu');
|
|
7
|
+
if (!context) {
|
|
8
|
+
throw Error('WebGPU not supported on the canvas.');
|
|
9
|
+
}
|
|
10
|
+
context.configure({
|
|
11
|
+
device,
|
|
12
|
+
format: presentationFormat,
|
|
13
|
+
alphaMode: 'premultiplied',
|
|
14
|
+
});
|
|
15
|
+
const defs = makeShaderDataDefinitions(shaderCode);
|
|
16
|
+
// @ts-expect-error This is what we get from the API
|
|
17
|
+
const uniformsSparams = makeStructuredView(defs.uniforms.sparams);
|
|
18
|
+
// @ts-expect-error This is what we get from the API
|
|
19
|
+
const uniformsDparams = makeStructuredView(defs.uniforms.dparams);
|
|
20
|
+
// Cache shader module and pipeline at init time
|
|
21
|
+
const shaderModule = device.createShaderModule({
|
|
22
|
+
label: 'replace shader',
|
|
23
|
+
code: shaderCode,
|
|
24
|
+
});
|
|
25
|
+
const pipeline = device.createRenderPipeline({
|
|
26
|
+
label: 'replace pipeline',
|
|
27
|
+
layout: 'auto',
|
|
28
|
+
vertex: {
|
|
29
|
+
module: shaderModule,
|
|
30
|
+
},
|
|
31
|
+
fragment: {
|
|
32
|
+
module: shaderModule,
|
|
33
|
+
targets: [{ format: presentationFormat }],
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
// Cache sampler at init time
|
|
37
|
+
const linearSampler = device.createSampler({
|
|
38
|
+
addressModeU: 'clamp-to-edge',
|
|
39
|
+
addressModeV: 'clamp-to-edge',
|
|
40
|
+
magFilter: 'linear',
|
|
41
|
+
minFilter: 'linear',
|
|
42
|
+
});
|
|
43
|
+
const nearestSampler = device.createSampler({
|
|
44
|
+
addressModeU: 'clamp-to-edge',
|
|
45
|
+
addressModeV: 'clamp-to-edge',
|
|
46
|
+
magFilter: 'nearest',
|
|
47
|
+
minFilter: 'nearest',
|
|
48
|
+
});
|
|
49
|
+
const sparamsBuffer = device.createBuffer({
|
|
50
|
+
size: uniformsSparams.arrayBuffer.byteLength,
|
|
51
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
52
|
+
});
|
|
53
|
+
const dparamsBuffer = device.createBuffer({
|
|
54
|
+
size: uniformsDparams.arrayBuffer.byteLength,
|
|
55
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
56
|
+
});
|
|
57
|
+
const updateSparams = (options) => {
|
|
58
|
+
uniformsSparams.set({
|
|
59
|
+
background: options.backgroundThreshold,
|
|
60
|
+
foreground: options.foregroundThreshold,
|
|
61
|
+
lightWrap: options.lightWrapIntensity,
|
|
62
|
+
lightWrapTightness: options.lightWrapTightness,
|
|
63
|
+
lightWrapEdgeBand: options.lightWrapEdgeBand,
|
|
64
|
+
width: options.width,
|
|
65
|
+
height: options.height,
|
|
66
|
+
});
|
|
67
|
+
device.queue.writeBuffer(sparamsBuffer, 0, uniformsSparams.arrayBuffer);
|
|
68
|
+
};
|
|
69
|
+
const updateDparams = ({ time, parity }) => {
|
|
70
|
+
uniformsDparams.set({ time, parity });
|
|
71
|
+
device.queue.writeBuffer(dparamsBuffer, 0, uniformsDparams.arrayBuffer);
|
|
72
|
+
};
|
|
73
|
+
const colorAttachment0 = {
|
|
74
|
+
loadOp: 'load',
|
|
75
|
+
storeOp: 'store',
|
|
76
|
+
};
|
|
77
|
+
const renderPassDescriptor = {
|
|
78
|
+
label: 'replace renderPass',
|
|
79
|
+
colorAttachments: [colorAttachment0],
|
|
80
|
+
};
|
|
81
|
+
const bindGroup0 = device.createBindGroup({
|
|
82
|
+
layout: pipeline.getBindGroupLayout(0),
|
|
83
|
+
entries: [
|
|
84
|
+
{ binding: 0, resource: linearSampler },
|
|
85
|
+
{ binding: 1, resource: nearestSampler },
|
|
86
|
+
{ binding: 2, resource: { buffer: sparamsBuffer } },
|
|
87
|
+
{ binding: 3, resource: { buffer: dparamsBuffer } },
|
|
88
|
+
],
|
|
89
|
+
});
|
|
90
|
+
let cachedBindGroup1 = null;
|
|
91
|
+
let cachedMask = null;
|
|
92
|
+
let cachedBackground = null;
|
|
93
|
+
let cachedForeground = null;
|
|
94
|
+
let cachedBlurBackground = null;
|
|
95
|
+
let cachedBackgroundThreshold = -1;
|
|
96
|
+
let cachedForegroundThreshold = -1;
|
|
97
|
+
let cachedLightWrapIntensity = -1;
|
|
98
|
+
let cachedLightWrapTightness = -1;
|
|
99
|
+
let cachedLightWrapEdgeBand = -1;
|
|
100
|
+
let cachedWidth = -1;
|
|
101
|
+
let cachedHeight = -1;
|
|
102
|
+
let parity = -1;
|
|
103
|
+
return {
|
|
104
|
+
render: (encoder, { foreground, background, blurBackground, mask, timestamp, }, options) => {
|
|
105
|
+
assert(!isContextLost(), RENDERING_EVENTS.ContextLost);
|
|
106
|
+
colorAttachment0.view = context.getCurrentTexture().createView();
|
|
107
|
+
if (!(cachedBackground === background &&
|
|
108
|
+
cachedForeground === foreground &&
|
|
109
|
+
cachedMask === mask &&
|
|
110
|
+
cachedBlurBackground === blurBackground)) {
|
|
111
|
+
cachedBindGroup1 = device.createBindGroup({
|
|
112
|
+
layout: pipeline.getBindGroupLayout(1),
|
|
113
|
+
entries: [
|
|
114
|
+
{ binding: 0, resource: foreground.createView() },
|
|
115
|
+
{ binding: 1, resource: background.createView() },
|
|
116
|
+
{ binding: 2, resource: mask.createView() },
|
|
117
|
+
{ binding: 3, resource: blurBackground.createView() },
|
|
118
|
+
],
|
|
119
|
+
});
|
|
120
|
+
cachedForeground = foreground;
|
|
121
|
+
cachedBackground = background;
|
|
122
|
+
cachedMask = mask;
|
|
123
|
+
cachedBlurBackground = blurBackground;
|
|
124
|
+
}
|
|
125
|
+
if (!(cachedBackgroundThreshold === options.backgroundThreshold &&
|
|
126
|
+
cachedForegroundThreshold === options.foregroundThreshold &&
|
|
127
|
+
cachedLightWrapIntensity === options.lightWrapIntensity &&
|
|
128
|
+
cachedLightWrapTightness === options.lightWrapTightness &&
|
|
129
|
+
cachedLightWrapEdgeBand === options.lightWrapEdgeBand &&
|
|
130
|
+
cachedWidth === background.width &&
|
|
131
|
+
cachedHeight === background.height)) {
|
|
132
|
+
updateSparams({
|
|
133
|
+
backgroundThreshold: options.backgroundThreshold,
|
|
134
|
+
foregroundThreshold: options.foregroundThreshold,
|
|
135
|
+
lightWrapIntensity: options.lightWrapIntensity,
|
|
136
|
+
lightWrapTightness: options.lightWrapTightness,
|
|
137
|
+
lightWrapEdgeBand: options.lightWrapEdgeBand,
|
|
138
|
+
width: background.width,
|
|
139
|
+
height: background.height,
|
|
140
|
+
});
|
|
141
|
+
cachedBackgroundThreshold = options.backgroundThreshold;
|
|
142
|
+
cachedForegroundThreshold = options.foregroundThreshold;
|
|
143
|
+
cachedLightWrapIntensity = options.lightWrapIntensity;
|
|
144
|
+
cachedLightWrapTightness = options.lightWrapTightness;
|
|
145
|
+
cachedLightWrapEdgeBand = options.lightWrapEdgeBand;
|
|
146
|
+
cachedWidth = background.width;
|
|
147
|
+
cachedHeight = background.height;
|
|
148
|
+
}
|
|
149
|
+
parity = -parity;
|
|
150
|
+
updateDparams({ time: (timestamp * 1e-6) % 1024.0, parity });
|
|
151
|
+
const pass = encoder.beginRenderPass(renderPassDescriptor);
|
|
152
|
+
pass.setPipeline(pipeline);
|
|
153
|
+
pass.setBindGroup(0, bindGroup0);
|
|
154
|
+
pass.setBindGroup(1, cachedBindGroup1);
|
|
155
|
+
pass.draw(6); // call our vertex shader 6 times
|
|
156
|
+
pass.end();
|
|
157
|
+
},
|
|
158
|
+
release: () => {
|
|
159
|
+
sparamsBuffer.destroy();
|
|
160
|
+
dparamsBuffer.destroy();
|
|
161
|
+
cachedBackgroundThreshold = -1;
|
|
162
|
+
cachedForegroundThreshold = -1;
|
|
163
|
+
cachedLightWrapIntensity = -1;
|
|
164
|
+
cachedLightWrapTightness = -1;
|
|
165
|
+
cachedLightWrapEdgeBand = -1;
|
|
166
|
+
cachedWidth = -1;
|
|
167
|
+
cachedHeight = -1;
|
|
168
|
+
cachedBlurBackground = null;
|
|
169
|
+
cachedBackground = null;
|
|
170
|
+
cachedForeground = null;
|
|
171
|
+
cachedMask = null;
|
|
172
|
+
cachedBindGroup1 = null;
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const createTextureResizeRenderer: (device: GPUDevice, isContextLost: () => boolean, width: number, height: number, textureFormat: GPUTextureFormat, filterMode: GPUFilterMode) => {
|
|
2
|
+
render(pass: GPUComputePassEncoder, texture: GPUTexture): GPUTexture;
|
|
3
|
+
release(): void;
|
|
4
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { makeShaderDataDefinitions, makeStructuredView } from 'webgpu-utils';
|
|
2
|
+
import { assert } from '@pexip/utils';
|
|
3
|
+
import { RENDERING_EVENTS } from '../../constants';
|
|
4
|
+
import { updateTextureStorageFormat, syncWorkgroupSizeWithShader, } from './webgpuUtils';
|
|
5
|
+
import resizeShader from './shaders/resize.wgsl';
|
|
6
|
+
export const createTextureResizeRenderer = (device, isContextLost, width, height, textureFormat, filterMode) => {
|
|
7
|
+
let shaderCode = updateTextureStorageFormat(resizeShader, textureFormat);
|
|
8
|
+
const WORKGROUP_SIZE_X = 16;
|
|
9
|
+
const WORKGROUP_SIZE_Y = 16;
|
|
10
|
+
const WORKGROUP_COUNT_X = Math.ceil(width / WORKGROUP_SIZE_X);
|
|
11
|
+
const WORKGROUP_COUNT_Y = Math.ceil(height / WORKGROUP_SIZE_Y);
|
|
12
|
+
shaderCode = syncWorkgroupSizeWithShader(shaderCode, {
|
|
13
|
+
workgroupSizeX: WORKGROUP_SIZE_X,
|
|
14
|
+
workgroupSizeY: WORKGROUP_SIZE_Y,
|
|
15
|
+
});
|
|
16
|
+
const defs = makeShaderDataDefinitions(shaderCode);
|
|
17
|
+
// @ts-expect-error This is what we get from the API
|
|
18
|
+
const uniforms = makeStructuredView(defs.uniforms.params);
|
|
19
|
+
const uniformsBuffer = device.createBuffer({
|
|
20
|
+
size: uniforms.arrayBuffer.byteLength,
|
|
21
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
22
|
+
});
|
|
23
|
+
uniforms.set({ outWidth: width, outHeight: height });
|
|
24
|
+
device.queue.writeBuffer(uniformsBuffer, 0, uniforms.arrayBuffer);
|
|
25
|
+
const shaderModule = device.createShaderModule({
|
|
26
|
+
label: `Resize shader module to ${width}x${height} with ${textureFormat} & ${filterMode}`,
|
|
27
|
+
code: shaderCode,
|
|
28
|
+
});
|
|
29
|
+
const pipeline = device.createComputePipeline({
|
|
30
|
+
layout: 'auto',
|
|
31
|
+
label: `Resize shader pipeline to ${width}x${height} with ${textureFormat} & ${filterMode}`,
|
|
32
|
+
compute: { module: shaderModule },
|
|
33
|
+
});
|
|
34
|
+
const outTexture = device.createTexture({
|
|
35
|
+
label: `Resize out texture to ${width}x${height} with ${textureFormat} & ${filterMode}`,
|
|
36
|
+
format: textureFormat,
|
|
37
|
+
size: [width, height],
|
|
38
|
+
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING,
|
|
39
|
+
});
|
|
40
|
+
const outTextureView = outTexture.createView();
|
|
41
|
+
const sampler = device.createSampler({
|
|
42
|
+
magFilter: filterMode,
|
|
43
|
+
minFilter: filterMode,
|
|
44
|
+
addressModeU: 'clamp-to-edge',
|
|
45
|
+
addressModeV: 'clamp-to-edge',
|
|
46
|
+
});
|
|
47
|
+
let cachedBindGroup0 = null;
|
|
48
|
+
let cachedInputTexture = null;
|
|
49
|
+
return {
|
|
50
|
+
render(pass, texture) {
|
|
51
|
+
assert(!isContextLost(), RENDERING_EVENTS.ContextLost);
|
|
52
|
+
if (texture !== cachedInputTexture) {
|
|
53
|
+
cachedBindGroup0 = device.createBindGroup({
|
|
54
|
+
layout: pipeline.getBindGroupLayout(0),
|
|
55
|
+
entries: [
|
|
56
|
+
{ binding: 0, resource: sampler },
|
|
57
|
+
{ binding: 1, resource: texture.createView() },
|
|
58
|
+
{ binding: 2, resource: outTextureView },
|
|
59
|
+
{ binding: 3, resource: { buffer: uniformsBuffer } },
|
|
60
|
+
],
|
|
61
|
+
});
|
|
62
|
+
cachedInputTexture = texture;
|
|
63
|
+
}
|
|
64
|
+
pass.setPipeline(pipeline);
|
|
65
|
+
pass.setBindGroup(0, cachedBindGroup0);
|
|
66
|
+
pass.dispatchWorkgroups(WORKGROUP_COUNT_X, WORKGROUP_COUNT_Y);
|
|
67
|
+
return outTexture;
|
|
68
|
+
},
|
|
69
|
+
release() {
|
|
70
|
+
uniformsBuffer.destroy();
|
|
71
|
+
outTexture.destroy();
|
|
72
|
+
cachedBindGroup0 = null;
|
|
73
|
+
cachedInputTexture = null;
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RendererOptions } from '../../types/render';
|
|
2
|
-
export declare const createSmoothingMaskRenderer: (
|
|
3
|
-
render: (currMask: GPUTexture, prevMask: GPUTexture
|
|
2
|
+
export declare const createSmoothingMaskRenderer: (device: GPUDevice, isContextLost: () => boolean, maskFormat: GPUTextureFormat, width: number, height: number, supportF16: boolean) => {
|
|
3
|
+
render: (encoder: GPUCommandEncoder, currMask: GPUTexture, prevMask: GPUTexture, options: RendererOptions) => GPUTexture;
|
|
4
4
|
release: () => void;
|
|
5
5
|
};
|