@pexip/media-processor 20.3.5 → 22.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 +109 -0
- package/README.md +17 -10
- package/api-docs/README.mdx +69 -23
- package/api-docs/functions/assertMediaStreamVideoTrack.mdx +13 -0
- package/api-docs/functions/createBenchmark.mdx +17 -5
- package/api-docs/functions/createFrameCallbackRequest.mdx +8 -2
- package/api-docs/functions/createMediaStreamTrackInputProcessAdaptor.mdx +10 -0
- package/api-docs/functions/createReadWritableStreamFallbackInputProcessAdaptor.mdx +17 -0
- package/api-docs/functions/createReadWritableStreamInputProcessAdaptor.mdx +10 -0
- package/api-docs/functions/createVideoProcessor.mdx +3 -3
- package/api-docs/functions/createWindowedStats.mdx +23 -0
- package/api-docs/functions/getDefaultInputProcessAdaptor.mdx +17 -0
- package/api-docs/functions/iou.mdx +19 -0
- package/api-docs/functions/isMediaStreamVideoTrack.mdx +13 -0
- package/api-docs/functions/labelComponents.mdx +20 -0
- package/api-docs/functions/nearestPowerOfTwo.mdx +21 -0
- package/api-docs/functions/playVideo.mdx +16 -0
- package/api-docs/functions/scoreComponent.mdx +22 -0
- package/api-docs/functions/setVideoElementSrc.mdx +14 -0
- package/api-docs/interfaces/Analyzer.mdx +4 -0
- package/api-docs/interfaces/Benchmark.mdx +26 -2
- package/api-docs/interfaces/FrameTransformStats.mdx +9 -0
- package/api-docs/interfaces/Gain.mdx +4 -0
- package/api-docs/interfaces/ImageSegmenterOptions.mdx +0 -2
- package/api-docs/interfaces/InputProcessAdaptor.mdx +28 -0
- package/api-docs/interfaces/Process.mdx +8 -3
- package/api-docs/interfaces/ProcessEventMute.mdx +6 -0
- package/api-docs/interfaces/ProcessWorkerEventOpened.mdx +7 -0
- package/api-docs/interfaces/ProcessWorkerEventStats.mdx +6 -0
- package/api-docs/interfaces/ProcessWorkerEventUpdated.mdx +7 -0
- package/api-docs/interfaces/ProcessorEvent.mdx +1 -1
- package/api-docs/interfaces/ProcessorOptions.mdx +0 -1
- package/api-docs/interfaces/ProcessorProcessOptions.mdx +3 -1
- package/api-docs/interfaces/ProcessorUpdateOptions.mdx +15 -0
- package/api-docs/interfaces/ReadWritableStream.mdx +12 -0
- package/api-docs/interfaces/Renderer.mdx +2 -2
- package/api-docs/interfaces/RendererOptions.mdx +25 -12
- package/api-docs/interfaces/Segmenter.mdx +89 -10
- package/api-docs/interfaces/SegmenterOptions.mdx +0 -1
- package/api-docs/interfaces/SelectionOptions.mdx +15 -0
- package/api-docs/interfaces/Stats.mdx +11 -0
- package/api-docs/interfaces/VideoProcessor.mdx +49 -5
- package/api-docs/interfaces/Weights.mdx +12 -0
- package/api-docs/type-aliases/OptionalKeys.mdx +10 -0
- package/api-docs/type-aliases/ProcessEvents.mdx +1 -0
- package/api-docs/type-aliases/ProcessInputType.mdx +3 -1
- package/api-docs/type-aliases/ProcessWorkerEvents.mdx +6 -4
- package/api-docs/type-aliases/ProcessorWorkerEvents.mdx +1 -1
- package/api-docs/type-aliases/Struct.mdx +9 -0
- package/api-docs/variables/BACKGROUND_THRESHOLD.mdx +3 -0
- package/api-docs/variables/DOWN_SAMPLE_FACTOR.mdx +3 -0
- package/api-docs/variables/EDGE_BLUR_AMOUNT.mdx +1 -1
- package/api-docs/variables/EXCLUDE_BYSTANDERS.mdx +3 -0
- package/api-docs/variables/FOREGROUND_THRESHOLD.mdx +1 -1
- package/api-docs/variables/FRAME_RATE.mdx +1 -1
- package/api-docs/variables/ImageFetchError.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/MASK_COMBINE_RATIO.mdx +1 -1
- 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/MediaStreamTrackTransferable.mdx +5 -0
- package/api-docs/variables/PERSON_CENTER.mdx +3 -0
- package/api-docs/variables/RENDERER_OPTIONS_STRUCT.mdx +3 -0
- package/api-docs/variables/SIGMA_RANGE.mdx +3 -0
- package/api-docs/variables/SIGMA_SPACE.mdx +3 -0
- package/api-docs/variables/STRONG_EDGE_BLUR_AMOUNT.mdx +3 -0
- package/api-docs/variables/cloneImageRecord.mdx +19 -0
- package/api-docs/variables/compareImageRecords.mdx +18 -0
- package/api-docs/variables/createRemoteImageBitmap.mdx +1 -1
- package/api-docs/variables/getCanvasRenderingContext2D.mdx +14 -0
- package/api-docs/variables/getImageSize.mdx +13 -0
- package/api-docs/variables/isRenderOptionsKey.mdx +13 -0
- package/api-docs/variables/isValidGpuAPI.mdx +13 -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 -44
- 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 +2 -3
- package/dist/common/backends/webgl/texture.js +21 -19
- 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 +72 -10
- 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 +205 -43
- 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 -3
- package/dist/common/backends/webgpu/texture.js +29 -20
- 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 +22 -5
- package/dist/common/constants.js +23 -5
- package/dist/common/index.d.ts +2 -0
- package/dist/common/index.js +2 -0
- package/dist/common/tsconfig.tsbuildinfo +1 -1
- package/dist/common/typeGuards.d.ts +2 -0
- package/dist/common/typeGuards.js +7 -0
- package/dist/common/types/media.d.ts +5 -1
- package/dist/common/types/messageEvents.d.ts +31 -4
- package/dist/common/types/processor.d.ts +6 -4
- package/dist/common/types/render.d.ts +147 -15
- package/dist/common/types/render.js +23 -1
- package/dist/common/types/segmentation.d.ts +0 -12
- package/dist/common/types/utils.d.ts +21 -0
- package/dist/common/utils.d.ts +29 -2
- package/dist/common/utils.js +206 -10
- package/dist/main/audio.js +3 -3
- package/dist/main/benchUtils.d.ts +35 -3
- package/dist/main/benchUtils.js +149 -15
- package/dist/main/index.d.ts +1 -1
- package/dist/main/index.js +1 -1
- package/dist/main/tsconfig.tsbuildinfo +1 -1
- package/dist/main/types.d.ts +0 -6
- package/dist/main/utils.d.ts +4 -0
- package/dist/main/utils.js +31 -0
- package/dist/main/video/constants.d.ts +1 -4
- package/dist/main/video/constants.js +1 -5
- package/dist/main/video/index.d.ts +3 -4
- package/dist/main/video/index.js +3 -4
- package/dist/main/video/inputProcessAdaptor.d.ts +30 -0
- package/dist/main/video/inputProcessAdaptor.js +198 -0
- package/dist/main/video/segmenter.d.ts +35 -0
- package/dist/main/video/{segmenters/mediapipe.js → segmenter.js} +93 -53
- package/dist/main/video/typeGuards.d.ts +2 -0
- package/dist/main/video/typeGuards.js +8 -1
- package/dist/main/video/types.d.ts +36 -16
- package/dist/main/video/utils.d.ts +5 -4
- package/dist/main/video/utils.js +49 -44
- package/dist/main/video/video.d.ts +29 -7
- package/dist/main/video/video.js +323 -28
- package/dist/workers/mediaWorker.js +35 -162
- package/dist/workers/tsconfig.tsbuildinfo +1 -1
- package/dist/worklets/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -12
- package/api-docs/functions/createCanvasTransform.mdx +0 -14
- package/api-docs/functions/createVideoTrackProcessor.mdx +0 -9
- package/api-docs/functions/createVideoTrackProcessorWithFallback.mdx +0 -15
- package/api-docs/interfaces/Detector.mdx +0 -81
- package/api-docs/interfaces/SegmentationParams.mdx +0 -18
- package/api-docs/interfaces/Transform.mdx +0 -62
- package/api-docs/type-aliases/ProcessVideoTrack.mdx +0 -15
- package/api-docs/type-aliases/SegmentationTransform.mdx +0 -3
- 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
- package/dist/main/transformer.d.ts +0 -1
- package/dist/main/transformer.js +0 -4
- package/dist/main/video/canvasTransform.d.ts +0 -17
- package/dist/main/video/canvasTransform.js +0 -253
- package/dist/main/video/segmenters/mediapipe.d.ts +0 -22
- package/dist/main/video/transformer.d.ts +0 -9
- package/dist/main/video/transformer.js +0 -68
- package/dist/main/video/videoStreamTrackProcessor.d.ts +0 -20
- package/dist/main/video/videoStreamTrackProcessor.js +0 -86
|
@@ -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,97 @@ export const createRenderer = (adapter, renderEventHandlers, canvas = new Offscr
|
|
|
88
187
|
if (options) {
|
|
89
188
|
updateProps(options);
|
|
90
189
|
}
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
width: frame.width,
|
|
95
|
-
height: frame.height,
|
|
96
|
-
timestamp: frame.timestamp,
|
|
190
|
+
assert(props.device);
|
|
191
|
+
const encoder = props.device.createCommandEncoder({
|
|
192
|
+
label: 'Renderer Encoder',
|
|
97
193
|
});
|
|
98
|
-
const
|
|
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(mask, frameUploadPass);
|
|
199
|
+
frameUploadPass.end();
|
|
200
|
+
let smoothedMask;
|
|
201
|
+
let compositeInputMask;
|
|
202
|
+
switch (options.downSampleFactor) {
|
|
203
|
+
case 4: {
|
|
204
|
+
const downsamplePass = encoder.beginComputePass({
|
|
205
|
+
label: 'downsample pass',
|
|
206
|
+
});
|
|
207
|
+
const maskLowRes = props.maskDownsampler4.render(downsamplePass, maskTexture);
|
|
208
|
+
const frameLowRes = props.frameDownsampler4.render(downsamplePass, frameTexture);
|
|
209
|
+
downsamplePass.end();
|
|
210
|
+
const filteredMask = props.jointBilateralFilterRenderer4.render(encoder, maskLowRes, frameLowRes, options);
|
|
211
|
+
smoothedMask = props.maskSmoothingRenderer4.render(encoder, filteredMask, props.prevMask4 ?? filteredMask, options);
|
|
212
|
+
const upsamplePass = encoder.beginComputePass({
|
|
213
|
+
label: 'upsample pass',
|
|
214
|
+
});
|
|
215
|
+
const upsampledMask = props.maskUpsampler.render(upsamplePass, smoothedMask);
|
|
216
|
+
upsamplePass.end();
|
|
217
|
+
compositeInputMask = props.strongMaskBlurRenderer.render(encoder, upsampledMask, STRONG_EDGE_BLUR_AMOUNT);
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
default: {
|
|
221
|
+
const downsamplePass = encoder.beginComputePass({
|
|
222
|
+
label: 'downsample pass',
|
|
223
|
+
});
|
|
224
|
+
const maskLowRes = props.maskDownsampler2.render(downsamplePass, maskTexture);
|
|
225
|
+
const frameLowRes = props.frameDownsampler2.render(downsamplePass, frameTexture);
|
|
226
|
+
downsamplePass.end();
|
|
227
|
+
const filteredMask = props.jointBilateralFilterRenderer2.render(encoder, maskLowRes, frameLowRes, options);
|
|
228
|
+
smoothedMask = props.maskSmoothingRenderer2.render(encoder, filteredMask, props.prevMask2 ?? filteredMask, options);
|
|
229
|
+
const upsamplePass = encoder.beginComputePass({
|
|
230
|
+
label: 'upsample pass',
|
|
231
|
+
});
|
|
232
|
+
const upsampledMask = props.maskUpsampler.render(upsamplePass, smoothedMask);
|
|
233
|
+
upsamplePass.end();
|
|
234
|
+
compositeInputMask = props.edgeBlurRenderer.render(encoder, upsampledMask, options);
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
99
238
|
if (options.effects === 'blur') {
|
|
100
|
-
const blurredTexture = props.blurRenderer.render(
|
|
101
|
-
props.blendRenderer.render(
|
|
239
|
+
const blurredTexture = props.blurRenderer.render(encoder, frameTexture, options.backgroundBlurAmount);
|
|
240
|
+
props.blendRenderer.render(encoder, {
|
|
241
|
+
foreground: frameTexture,
|
|
242
|
+
background: blurredTexture,
|
|
243
|
+
mask: compositeInputMask,
|
|
244
|
+
}, options);
|
|
102
245
|
}
|
|
103
246
|
else if (options.effects === 'overlay') {
|
|
104
247
|
if (options.backgroundImage) {
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
width: options.backgroundImage.width,
|
|
108
|
-
height: options.backgroundImage.height,
|
|
109
|
-
timestamp: frame.timestamp,
|
|
248
|
+
const bgImgUploadPass = encoder.beginComputePass({
|
|
249
|
+
label: 'background image upload pass',
|
|
110
250
|
});
|
|
111
|
-
props.
|
|
251
|
+
const bgTexture = props.backgroundImageRenderer.render(options.backgroundImage, bgImgUploadPass);
|
|
252
|
+
bgImgUploadPass.end();
|
|
253
|
+
const blurredBackgroundImageTexture = props.blurRenderer.render(encoder, bgTexture, options.backgroundBlurAmount);
|
|
254
|
+
props.replaceRenderer.render(encoder, {
|
|
255
|
+
foreground: frameTexture,
|
|
256
|
+
background: bgTexture,
|
|
257
|
+
mask: compositeInputMask,
|
|
258
|
+
blurBackground: blurredBackgroundImageTexture,
|
|
259
|
+
timestamp: frame.timestamp,
|
|
260
|
+
}, options);
|
|
112
261
|
}
|
|
113
262
|
}
|
|
114
|
-
|
|
263
|
+
switch (options.downSampleFactor) {
|
|
264
|
+
case 4:
|
|
265
|
+
props.prevMask4 = props.prevMaskRenderer.render(encoder, smoothedMask);
|
|
266
|
+
break;
|
|
267
|
+
default:
|
|
268
|
+
props.prevMask2 = props.prevMaskRenderer.render(encoder, smoothedMask);
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
props.device.queue.submit([encoder.finish()]);
|
|
115
272
|
};
|
|
116
273
|
const release = () => {
|
|
117
274
|
lazyProps.release();
|
|
118
275
|
props.deviceLost = false;
|
|
276
|
+
props.prevMask2 = undefined;
|
|
277
|
+
props.prevMask4 = undefined;
|
|
278
|
+
props.presentationFormat = 'rgba8unorm';
|
|
279
|
+
props.supportR16FloatTextureStorage = false;
|
|
280
|
+
props.maskFormat = 'rgba16float';
|
|
119
281
|
lazyProps = createLazyProps(rendererCreator);
|
|
120
282
|
};
|
|
121
283
|
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
|
};
|