Skip to content

Commit bbbdbb3

Browse files
committed
Address PR feedback
1 parent 5a5c6b8 commit bbbdbb3

File tree

1 file changed

+21
-31
lines changed
  • apps/typegpu-docs/src/examples/image-processing/camera-fft

1 file changed

+21
-31
lines changed

apps/typegpu-docs/src/examples/image-processing/camera-fft/index.ts

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { oklabGamutClip, oklabToLinearRgb } from '@typegpu/color';
2+
import type { Fft2d } from '@typegpu/sort';
23
import {
34
createFft2d,
45
createStockhamRadix2LineStrategy,
56
createStockhamRadix4LineStrategy,
6-
type Fft2d,
77
} from '@typegpu/sort';
8+
import type { TgpuBindGroup } from 'typegpu';
89
import tgpu, { common, d, std } from 'typegpu';
910
import { defineControls } from '../../common/defineControls.ts';
1011

@@ -73,7 +74,7 @@ function decodedFrameSize(
7374
return { width: w, height: h };
7475
}
7576

76-
const fillParamsType = d.struct({
77+
const FillParams = d.struct({
7778
videoW: d.u32,
7879
videoH: d.u32,
7980
padW: d.u32,
@@ -88,7 +89,7 @@ const fillParamsType = d.struct({
8889

8990
const fillLayout = tgpu.bindGroupLayout({
9091
video: { texture: d.texture2d() },
91-
params: { uniform: fillParamsType },
92+
params: { uniform: FillParams },
9293
out: { storage: d.arrayOf(d.vec2f), access: 'mutable' },
9394
});
9495

@@ -164,6 +165,7 @@ const filterKernel = tgpu.computeFn({
164165
numWorkgroups: d.builtin.numWorkgroups,
165166
},
166167
})((input) => {
168+
'use gpu';
167169
const wg = d.u32(WORKGROUP);
168170
const spanX = input.numWorkgroups.x * wg;
169171
const spanY = input.numWorkgroups.y * spanX;
@@ -203,8 +205,7 @@ const filterKernel = tgpu.computeFn({
203205
const highMaskInner = std.select(d.f32(0), d.f32(1), r > highC);
204206
const highMask = std.select(highMaskInner, d.f32(1), highPassOff);
205207
const mask = lowMask * highMask;
206-
const c = filterLayout.$.spectrum[tid];
207-
filterLayout.$.spectrum[tid] = d.vec2f(c.x * mask, c.y * mask);
208+
filterLayout.$.spectrum[tid] *= mask;
208209
});
209210

210211
const magParamsType = d.struct({
@@ -257,10 +258,10 @@ const magKernel = tgpu.computeFn({
257258
magLayout.$.params.swapSpectrumAxes !== d.u32(0),
258259
);
259260
const cShift = magLayout.$.spectrum[srcTid];
260-
const lenRaw = std.sqrt(cShift.x * cShift.x + cShift.y * cShift.y);
261+
const lenRaw = std.length(cShift);
261262
/** Log stretch tuned on these magnitudes (`log(1+|·|) * 0.2`). */
262263
const logv = std.log(1.0 + lenRaw) * 0.2 * std.exp2(magLayout.$.params.exposure);
263-
const cv = std.clamp(logv, 0.0, 1.0);
264+
const cv = std.saturate(logv);
264265
/** `cv` from log-magnitude; L ∈ [0.04, 1]; chroma → 0 at max `cv` so peaks go neutral white. */
265266
const L = 0.04 + cv * (1.0 - 0.04);
266267
const chroma = cv * (1.0 - cv) * 0.32;
@@ -295,6 +296,7 @@ const spatialKernel = tgpu.computeFn({
295296
numWorkgroups: d.builtin.numWorkgroups,
296297
},
297298
})((input) => {
299+
'use gpu';
298300
const wg = d.u32(WORKGROUP);
299301
const spanX = input.numWorkgroups.x * wg;
300302
const spanY = input.numWorkgroups.y * spanX;
@@ -308,7 +310,7 @@ const spatialKernel = tgpu.computeFn({
308310

309311
const c = spatialLayout.$.spectrum[tid];
310312
const inv = spatialLayout.$.params.invSize;
311-
const g = std.clamp(c.x * inv * std.exp2(spatialLayout.$.params.exposure), 0.0, 1.0);
313+
const g = std.saturate(c.x * inv * std.exp2(spatialLayout.$.params.exposure));
312314
const padWLog2 = spatialLayout.$.params.padWLog2;
313315
const padWMask = spatialLayout.$.params.padWMask;
314316
const x = tid & padWMask;
@@ -377,15 +379,10 @@ const spectrumFrag = tgpu.fragmentFn({
377379
return d.vec4f(col.rgb, 1);
378380
});
379381

380-
const videoBlitTargetDimsType = d.struct({
381-
w: d.f32,
382-
h: d.f32,
383-
});
384-
385382
const videoBlitLayout = tgpu.bindGroupLayout({
386383
inputTexture: { externalTexture: d.textureExternal() },
387384
/** Render-target size (pixels); `fullScreenTriangle` uv is not linear in pixel space for offscreen passes. */
388-
targetPx: { uniform: videoBlitTargetDimsType },
385+
targetPx: { uniform: d.vec2f },
389386
});
390387

391388
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
@@ -419,15 +416,14 @@ const sampler = root['~unstable'].createSampler({
419416
minFilter: 'linear',
420417
});
421418

422-
const videoBlitTargetPx = root.createBuffer(videoBlitTargetDimsType).$usage('uniform');
419+
const videoBlitTargetPx = root.createBuffer(d.vec2f).$usage('uniform');
423420

424421
const videoBlitFrag = tgpu.fragmentFn({
425422
in: { position: d.builtin.position },
426423
out: d.vec4f,
427424
})((input) => {
428-
const w = d.f32(videoBlitLayout.$.targetPx.w);
429-
const rtH = d.f32(videoBlitLayout.$.targetPx.h);
430-
const st = d.vec2f(input.position.x / w, input.position.y / rtH);
425+
'use gpu';
426+
const st = input.position.xy / videoBlitLayout.$.targetPx;
431427
return std.textureSampleBaseClampToEdge(videoBlitLayout.$.inputTexture, sampler.$, st);
432428
});
433429

@@ -470,7 +466,7 @@ let displayTexture: ReturnType<typeof createPaddedDisplayTexture> | undefined;
470466
let displaySampleView: ReturnType<typeof displaySampleViewOf> | undefined;
471467
let displayStorageView: ReturnType<typeof displayStorageViewOf> | undefined;
472468

473-
const fillParams = root.createBuffer(fillParamsType).$usage('uniform');
469+
const fillParams = root.createBuffer(FillParams).$usage('uniform');
474470
const filterParams = root.createBuffer(filterParamsType).$usage('uniform');
475471
const magParams = root.createBuffer(magParamsType).$usage('uniform');
476472
const spatialParams = root.createBuffer(spatialParamsType).$usage('uniform');
@@ -516,18 +512,12 @@ function effectiveFrameSize(frameW: number, frameH: number): { effW: number; eff
516512
return { effW, effH };
517513
}
518514

519-
let fillBindGroup: ReturnType<typeof root.createBindGroup> | undefined;
515+
let fillBindGroup: TgpuBindGroup | undefined;
520516
/** One bind group per ping-pong buffer; use `fft.outputIndex()` after each transform to pick the right one. */
521-
let magBindSlots:
522-
| [ReturnType<typeof root.createBindGroup>, ReturnType<typeof root.createBindGroup>]
523-
| undefined;
524-
let filterBindSlots:
525-
| [ReturnType<typeof root.createBindGroup>, ReturnType<typeof root.createBindGroup>]
526-
| undefined;
527-
let spatialBindSlots:
528-
| [ReturnType<typeof root.createBindGroup>, ReturnType<typeof root.createBindGroup>]
529-
| undefined;
530-
let renderBindGroup: ReturnType<typeof root.createBindGroup> | undefined;
517+
let magBindSlots: [TgpuBindGroup, TgpuBindGroup] | undefined;
518+
let filterBindSlots: [TgpuBindGroup, TgpuBindGroup] | undefined;
519+
let spatialBindSlots: [TgpuBindGroup, TgpuBindGroup] | undefined;
520+
let renderBindGroup: TgpuBindGroup | undefined;
531521

532522
function invalidateBindGroups(all: boolean) {
533523
fillBindGroup = undefined;
@@ -708,7 +698,7 @@ function processVideoFrame(_: number, metadata: VideoFrameCallbackMetadata) {
708698
const videoBlitKey = `${effW}x${effH}`;
709699
if (videoBlitKey !== lastVideoBlitKey) {
710700
lastVideoBlitKey = videoBlitKey;
711-
videoBlitTargetPx.write({ w: effW, h: effH });
701+
videoBlitTargetPx.write(d.vec2f(effW, effH));
712702
}
713703
const videoBlitBindGroup = root.createBindGroup(videoBlitLayout, {
714704
inputTexture: device.importExternalTexture({ source: video }),

0 commit comments

Comments
 (0)