From 0268f9786eaba395a6f33b0de97ea5bc07cbb68f Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Tue, 30 Sep 2025 16:53:22 +0200 Subject: [PATCH 1/6] Add tests for bind group type checks --- .../typegpu/tests/computePipeline.test.ts | 24 +++++++++++++++ packages/typegpu/tests/renderPipeline.test.ts | 30 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/packages/typegpu/tests/computePipeline.test.ts b/packages/typegpu/tests/computePipeline.test.ts index 673e381cd..58c267e84 100644 --- a/packages/typegpu/tests/computePipeline.test.ts +++ b/packages/typegpu/tests/computePipeline.test.ts @@ -69,6 +69,30 @@ describe('TgpuComputePipeline', () => { `); }); + it('type checks passed bind groups', ({ root }) => { + const main = tgpu['~unstable'] + .computeFn({ workgroupSize: [32] })(() => { + // do something + }); + const computePipeline = root + .withCompute(main) + .createPipeline(); + + const layout1 = tgpu.bindGroupLayout({ buf: { uniform: d.u32 } }); + const bindGroup1 = root.createBindGroup(layout1, { + buf: root.createBuffer(d.u32).$usage('uniform'), + }); + const layout2 = tgpu.bindGroupLayout({ buf: { uniform: d.f32 } }); + const bindGroup2 = root.createBindGroup(layout2, { + buf: root.createBuffer(d.f32).$usage('uniform'), + }); + + computePipeline.with(layout1, bindGroup1); + computePipeline.with(layout2, bindGroup2); + //@ts-expect-error + (() => computePipeline.with(layout1, bindGroup2)); + }); + describe('Performance Callbacks', () => { it('should add performance callback with automatic query set', ({ root }) => { const entryFn = tgpu['~unstable'].computeFn({ workgroupSize: [1] })( diff --git a/packages/typegpu/tests/renderPipeline.test.ts b/packages/typegpu/tests/renderPipeline.test.ts index 54cecc521..11ed9808d 100644 --- a/packages/typegpu/tests/renderPipeline.test.ts +++ b/packages/typegpu/tests/renderPipeline.test.ts @@ -140,6 +140,36 @@ describe('TgpuRenderPipeline', () => { ).toEqualTypeOf>(); }); + it('type checks passed bind groups', ({ root }) => { + const vertexMain = tgpu['~unstable'].vertexFn({ + out: { bar: d.location(0, d.vec3f) }, + })(() => ({ + bar: d.vec3f(), + })); + const fragmentMain = tgpu['~unstable'].fragmentFn({ + in: { bar: d.location(0, d.vec3f) }, + out: d.vec4f, + })(() => d.vec4f()); + const renderPipeline = root + .withVertex(vertexMain, {}) + .withFragment(fragmentMain, { format: 'r8unorm' }) + .createPipeline(); + + const layout1 = tgpu.bindGroupLayout({ buf: { uniform: d.u32 } }); + const bindGroup1 = root.createBindGroup(layout1, { + buf: root.createBuffer(d.u32).$usage('uniform'), + }); + const layout2 = tgpu.bindGroupLayout({ buf: { uniform: d.f32 } }); + const bindGroup2 = root.createBindGroup(layout2, { + buf: root.createBuffer(d.f32).$usage('uniform'), + }); + + renderPipeline.with(layout1, bindGroup1); + renderPipeline.with(layout2, bindGroup2); + //@ts-expect-error + (() => renderPipeline.with(layout1, bindGroup2)); + }); + describe('resolve', () => { it('allows resolving the entire shader code', ({ root }) => { const pipeline = root['~unstable'] From 0ea83244b7dfe2ae0004d335226eaf34fac761ae Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Tue, 30 Sep 2025 16:56:52 +0200 Subject: [PATCH 2/6] Fix computePipeline types --- .../src/core/pipeline/computePipeline.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/typegpu/src/core/pipeline/computePipeline.ts b/packages/typegpu/src/core/pipeline/computePipeline.ts index 6322f85ff..6803a86ca 100644 --- a/packages/typegpu/src/core/pipeline/computePipeline.ts +++ b/packages/typegpu/src/core/pipeline/computePipeline.ts @@ -9,6 +9,7 @@ import { $getNameForward, $internal, $resolve } from '../../shared/symbols.ts'; import type { TgpuBindGroup, TgpuBindGroupLayout, + TgpuLayoutEntry, } from '../../tgpuBindGroupLayout.ts'; import { logDataFromGPU } from '../../tgsl/consoleLog/deserializers.ts'; import type { LogResources } from '../../tgsl/consoleLog/types.ts'; @@ -45,10 +46,10 @@ export interface TgpuComputePipeline readonly [$internal]: ComputePipelineInternals; readonly resourceType: 'compute-pipeline'; - with( - bindGroupLayout: TgpuBindGroupLayout, - bindGroup: TgpuBindGroup, - ): TgpuComputePipeline; + with>( + bindGroupLayout: TgpuBindGroupLayout, + bindGroup: TgpuBindGroup, + ): this; dispatchWorkgroups( x: number, @@ -118,17 +119,17 @@ class TgpuComputePipelineImpl implements TgpuComputePipeline { return this._core.unwrap().pipeline; } - with( - bindGroupLayout: TgpuBindGroupLayout, - bindGroup: TgpuBindGroup, - ): TgpuComputePipeline { + with>( + bindGroupLayout: TgpuBindGroupLayout, + bindGroup: TgpuBindGroup, + ): this { return new TgpuComputePipelineImpl(this._core, { ...this._priors, bindGroupLayoutMap: new Map([ ...(this._priors.bindGroupLayoutMap ?? []), [bindGroupLayout, bindGroup], ]), - }); + }) as this; } withPerformanceCallback( From 927b1e6320f265c55a8f55e399e47fa4f442fc6c Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Tue, 30 Sep 2025 17:36:11 +0200 Subject: [PATCH 3/6] Add one argument `with` implementations --- .../src/examples/rendering/3d-fish/index.ts | 6 ++-- .../src/core/pipeline/computePipeline.ts | 27 +++++++++++++--- .../src/core/pipeline/renderPipeline.ts | 31 +++++++++++++++---- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/apps/typegpu-docs/src/examples/rendering/3d-fish/index.ts b/apps/typegpu-docs/src/examples/rendering/3d-fish/index.ts index 8d92328a5..0e3c7861e 100644 --- a/apps/typegpu-docs/src/examples/rendering/3d-fish/index.ts +++ b/apps/typegpu-docs/src/examples/rendering/3d-fish/index.ts @@ -257,7 +257,7 @@ function frame(timestamp: DOMHighResTimeStamp) { cameraBuffer.write(camera); computePipeline - .with(computeBindGroupLayout, computeBindGroups[odd ? 1 : 0]) + .with(computeBindGroups[odd ? 1 : 0]) .dispatchWorkgroups(p.fishAmount / p.workGroupSize); renderPipeline @@ -280,7 +280,7 @@ function frame(timestamp: DOMHighResTimeStamp) { }) .with(modelVertexLayout, oceanFloorModel.vertexBuffer) .with(renderInstanceLayout, oceanFloorDataBuffer) - .with(renderBindGroupLayout, renderOceanFloorBindGroup) + .with(renderOceanFloorBindGroup) .draw(oceanFloorModel.polygonCount, 1); renderPipeline @@ -303,7 +303,7 @@ function frame(timestamp: DOMHighResTimeStamp) { }) .with(modelVertexLayout, fishModel.vertexBuffer) .with(renderInstanceLayout, fishDataBuffers[odd ? 1 : 0]) - .with(renderBindGroupLayout, renderFishBindGroups[odd ? 1 : 0]) + .with(renderFishBindGroups[odd ? 1 : 0]) .draw(fishModel.polygonCount, p.fishAmount); root['~unstable'].flush(); diff --git a/packages/typegpu/src/core/pipeline/computePipeline.ts b/packages/typegpu/src/core/pipeline/computePipeline.ts index 6803a86ca..67d60c04f 100644 --- a/packages/typegpu/src/core/pipeline/computePipeline.ts +++ b/packages/typegpu/src/core/pipeline/computePipeline.ts @@ -6,10 +6,11 @@ import { type ResolutionResult, resolve } from '../../resolutionCtx.ts'; import type { TgpuNamable } from '../../shared/meta.ts'; import { getName, PERF, setName } from '../../shared/meta.ts'; import { $getNameForward, $internal, $resolve } from '../../shared/symbols.ts'; -import type { - TgpuBindGroup, - TgpuBindGroupLayout, - TgpuLayoutEntry, +import { + isBindGroup, + type TgpuBindGroup, + type TgpuBindGroupLayout, + type TgpuLayoutEntry, } from '../../tgpuBindGroupLayout.ts'; import { logDataFromGPU } from '../../tgsl/consoleLog/deserializers.ts'; import type { LogResources } from '../../tgsl/consoleLog/types.ts'; @@ -50,6 +51,7 @@ export interface TgpuComputePipeline bindGroupLayout: TgpuBindGroupLayout, bindGroup: TgpuBindGroup, ): this; + with(bindGroup: TgpuBindGroup): this; dispatchWorkgroups( x: number, @@ -122,12 +124,27 @@ class TgpuComputePipelineImpl implements TgpuComputePipeline { with>( bindGroupLayout: TgpuBindGroupLayout, bindGroup: TgpuBindGroup, + ): this; + with(bindGroup: TgpuBindGroup): this; + with( + layoutOrBindGroup: TgpuBindGroupLayout | TgpuBindGroup, + bindGroup?: TgpuBindGroup, ): this { + if (isBindGroup(layoutOrBindGroup)) { + return new TgpuComputePipelineImpl(this._core, { + ...this._priors, + bindGroupLayoutMap: new Map([ + ...(this._priors.bindGroupLayoutMap ?? []), + [layoutOrBindGroup.layout, layoutOrBindGroup], + ]), + }) as this; + } + return new TgpuComputePipelineImpl(this._core, { ...this._priors, bindGroupLayoutMap: new Map([ ...(this._priors.bindGroupLayoutMap ?? []), - [bindGroupLayout, bindGroup], + [layoutOrBindGroup as TgpuBindGroupLayout, bindGroup as TgpuBindGroup], ]), }) as this; } diff --git a/packages/typegpu/src/core/pipeline/renderPipeline.ts b/packages/typegpu/src/core/pipeline/renderPipeline.ts index c471c3019..b0d499143 100644 --- a/packages/typegpu/src/core/pipeline/renderPipeline.ts +++ b/packages/typegpu/src/core/pipeline/renderPipeline.ts @@ -26,6 +26,7 @@ import { getName, PERF, setName } from '../../shared/meta.ts'; import { $getNameForward, $internal, $resolve } from '../../shared/symbols.ts'; import type { AnyVertexAttribs } from '../../shared/vertexFormat.ts'; import { + isBindGroup, isBindGroupLayout, type TgpuBindGroup, type TgpuBindGroupLayout, @@ -99,6 +100,7 @@ export interface TgpuRenderPipeline bindGroupLayout: TgpuBindGroupLayout, bindGroup: TgpuBindGroup, ): this; + with(bindGroup: TgpuBindGroup): this; withColorAttachment( attachment: FragmentOutToColorAttachment, @@ -330,28 +332,45 @@ class TgpuRenderPipelineImpl implements TgpuRenderPipeline { bindGroupLayout: TgpuBindGroupLayout, bindGroup: TgpuBindGroup, ): this; + with(bindGroup: TgpuBindGroup): this; with( - definition: TgpuVertexLayout | TgpuBindGroupLayout, - resource: (TgpuBuffer & VertexFlag) | TgpuBindGroup, + layoutOrBindGroup: + | TgpuVertexLayout + | TgpuBindGroupLayout + | TgpuBindGroup, + resource?: (TgpuBuffer & VertexFlag) | TgpuBindGroup, ): this { const internals = this[$internal]; - if (isBindGroupLayout(definition)) { + if (isBindGroup(layoutOrBindGroup)) { return new TgpuRenderPipelineImpl(internals.core, { ...internals.priors, bindGroupLayoutMap: new Map([ ...(internals.priors.bindGroupLayoutMap ?? []), - [definition, resource as TgpuBindGroup], + [layoutOrBindGroup.layout, layoutOrBindGroup], ]), }) as this; } - if (isVertexLayout(definition)) { + if (isBindGroupLayout(layoutOrBindGroup)) { + return new TgpuRenderPipelineImpl(internals.core, { + ...internals.priors, + bindGroupLayoutMap: new Map([ + ...(internals.priors.bindGroupLayoutMap ?? []), + [layoutOrBindGroup, resource as TgpuBindGroup], + ]), + }) as this; + } + + if (isVertexLayout(layoutOrBindGroup)) { return new TgpuRenderPipelineImpl(internals.core, { ...internals.priors, vertexLayoutMap: new Map([ ...(internals.priors.vertexLayoutMap ?? []), - [definition, resource as TgpuBuffer & VertexFlag], + [ + layoutOrBindGroup, + resource as TgpuBuffer & VertexFlag, + ], ]), }) as this; } From a04179bcc89444f4dbda0d994a7ab0c7e0816c43 Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Tue, 30 Sep 2025 17:54:18 +0200 Subject: [PATCH 4/6] Mark old overloads as outdated --- packages/typegpu/src/core/pipeline/computePipeline.ts | 4 ++++ packages/typegpu/src/core/pipeline/renderPipeline.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/packages/typegpu/src/core/pipeline/computePipeline.ts b/packages/typegpu/src/core/pipeline/computePipeline.ts index 67d60c04f..7abe63512 100644 --- a/packages/typegpu/src/core/pipeline/computePipeline.ts +++ b/packages/typegpu/src/core/pipeline/computePipeline.ts @@ -47,6 +47,10 @@ export interface TgpuComputePipeline readonly [$internal]: ComputePipelineInternals; readonly resourceType: 'compute-pipeline'; + /** + * @deprecated This overload is outdated. + * Call `pipeline.with(bindGroup)` instead. + */ with>( bindGroupLayout: TgpuBindGroupLayout, bindGroup: TgpuBindGroup, diff --git a/packages/typegpu/src/core/pipeline/renderPipeline.ts b/packages/typegpu/src/core/pipeline/renderPipeline.ts index b0d499143..5a27e0a5b 100644 --- a/packages/typegpu/src/core/pipeline/renderPipeline.ts +++ b/packages/typegpu/src/core/pipeline/renderPipeline.ts @@ -96,6 +96,10 @@ export interface TgpuRenderPipeline vertexLayout: TgpuVertexLayout, buffer: TgpuBuffer & VertexFlag, ): this; + /** + * @deprecated This overload is outdated. + * Call `pipeline.with(bindGroup)` instead. + */ with>( bindGroupLayout: TgpuBindGroupLayout, bindGroup: TgpuBindGroup, From 4321a452c058a5a7e5e7837ae55902532a9649f3 Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Wed, 1 Oct 2025 12:35:57 +0200 Subject: [PATCH 5/6] Update examples, update prepareDispatch --- .../content/docs/ecosystem/typegpu-noise.mdx | 2 +- .../content/docs/fundamentals/pipelines.mdx | 4 ++-- .../src/content/docs/fundamentals/utils.mdx | 4 ++-- .../examples/algorithms/matrix-next/index.ts | 2 +- .../algorithms/mnist-inference/index.ts | 4 ++-- .../algorithms/probability/executor.ts | 2 +- .../image-processing/ascii-filter/index.ts | 2 +- .../rendering/cubemap-reflection/icosphere.ts | 2 +- .../rendering/cubemap-reflection/index.ts | 8 ++++---- .../examples/rendering/perlin-noise/index.ts | 2 +- .../src/examples/rendering/two-boxes/index.ts | 2 +- .../examples/simple/liquid-glass/mipmaps.ts | 1 - .../src/examples/simple/oklab/index.ts | 2 +- .../examples/simulation/boids-next/index.ts | 2 +- .../src/examples/simulation/gravity/index.ts | 6 +++--- .../examples/simulation/stable-fluid/index.ts | 18 ++++++++---------- .../src/examples/tests/dispatch/index.ts | 4 ++-- .../src/perlin-2d/dynamic-cache.ts | 4 ++-- .../src/perlin-3d/dynamic-cache.ts | 4 ++-- packages/typegpu/src/errors.ts | 2 +- packages/typegpu/src/prepareDispatch.ts | 14 ++++---------- packages/typegpu/tests/computePipeline.test.ts | 6 +++--- packages/typegpu/tests/renderPipeline.test.ts | 2 +- packages/typegpu/tests/root.test.ts | 2 +- 24 files changed, 46 insertions(+), 55 deletions(-) diff --git a/apps/typegpu-docs/src/content/docs/ecosystem/typegpu-noise.mdx b/apps/typegpu-docs/src/content/docs/ecosystem/typegpu-noise.mdx index 729f1025e..eb8b3705a 100644 --- a/apps/typegpu-docs/src/content/docs/ecosystem/typegpu-noise.mdx +++ b/apps/typegpu-docs/src/content/docs/ecosystem/typegpu-noise.mdx @@ -260,7 +260,7 @@ let bindGroup = initBindGroup(d.vec3u(10, 10, 1)); // Dispatching the pipeline pipeline - .with(dynamicLayout, bindGroup) + .with(bindGroup) .dispatchWorkgroups(1); // Can be called again to reinitialize the cache with diff --git a/apps/typegpu-docs/src/content/docs/fundamentals/pipelines.mdx b/apps/typegpu-docs/src/content/docs/fundamentals/pipelines.mdx index 59bdc7c7e..d9713472d 100644 --- a/apps/typegpu-docs/src/content/docs/fundamentals/pipelines.mdx +++ b/apps/typegpu-docs/src/content/docs/fundamentals/pipelines.mdx @@ -305,11 +305,11 @@ const bindGroup = root.createBindGroup(bindGroupLayout, { // binding and execution renderPipeline .with(vertexLayout, vertexBuffer) - .with(bindGroupLayout, bindGroup) + .with(bindGroup) .draw(8); computePipeline - .with(bindGroupLayout, bindGroup) + .with(bindGroup) .dispatchWorkgroups(1); ``` diff --git a/apps/typegpu-docs/src/content/docs/fundamentals/utils.mdx b/apps/typegpu-docs/src/content/docs/fundamentals/utils.mdx index 1d81c48da..2d81e7a95 100644 --- a/apps/typegpu-docs/src/content/docs/fundamentals/utils.mdx +++ b/apps/typegpu-docs/src/content/docs/fundamentals/utils.mdx @@ -89,8 +89,8 @@ const test = prepareDispatch(root, (x) => { layout.$.buffer[x] *= 2; }); -test.with(layout, bindGroup1).dispatch(3); -test.with(layout, bindGroup2).dispatch(4); +test.with(bindGroup1).dispatch(3); +test.with(bindGroup2).dispatch(4); console.log(await buffer1.read()); // [2, 4, 6]; console.log(await buffer2.read()); // [4, 8, 16, 32]; diff --git a/apps/typegpu-docs/src/examples/algorithms/matrix-next/index.ts b/apps/typegpu-docs/src/examples/algorithms/matrix-next/index.ts index d1649efdb..c1018e134 100644 --- a/apps/typegpu-docs/src/examples/algorithms/matrix-next/index.ts +++ b/apps/typegpu-docs/src/examples/algorithms/matrix-next/index.ts @@ -176,7 +176,7 @@ async function compute() { }; pipelines[state.strategy] - .with(computeLayout, bindGroup) + .with(bindGroup) .dispatchWorkgroups(workgroupCount.x, workgroupCount.y); await root.device.queue.onSubmittedWorkDone(); diff --git a/apps/typegpu-docs/src/examples/algorithms/mnist-inference/index.ts b/apps/typegpu-docs/src/examples/algorithms/mnist-inference/index.ts index bd17b234c..af429dc6b 100644 --- a/apps/typegpu-docs/src/examples/algorithms/mnist-inference/index.ts +++ b/apps/typegpu-docs/src/examples/algorithms/mnist-inference/index.ts @@ -165,8 +165,8 @@ function createNetwork(layers: [LayerData, LayerData][]): Network { const isLastLayer = i === buffers.length - 1; let boundPipeline = pipeline - .with(ioLayout, ioBindGroups[i]) - .with(weightsBiasesLayout, weightsBindGroups[i]); + .with(ioBindGroups[i]) + .with(weightsBindGroups[i]); if (querySet && (isFirstLayer || isLastLayer)) { const descriptor = { diff --git a/apps/typegpu-docs/src/examples/algorithms/probability/executor.ts b/apps/typegpu-docs/src/examples/algorithms/probability/executor.ts index 8429acc1c..75d588e41 100644 --- a/apps/typegpu-docs/src/examples/algorithms/probability/executor.ts +++ b/apps/typegpu-docs/src/examples/algorithms/probability/executor.ts @@ -123,7 +123,7 @@ export class Executor { } pipeline - .with(this.#bindGroupLayout, this.#bindGroup) + .with(this.#bindGroup) .dispatchWorkgroups(Math.ceil(this.#count / 64)); return await this.#samplesBuffer.read(); diff --git a/apps/typegpu-docs/src/examples/image-processing/ascii-filter/index.ts b/apps/typegpu-docs/src/examples/image-processing/ascii-filter/index.ts index e9b36816b..bf86b4c61 100644 --- a/apps/typegpu-docs/src/examples/image-processing/ascii-filter/index.ts +++ b/apps/typegpu-docs/src/examples/image-processing/ascii-filter/index.ts @@ -234,7 +234,7 @@ function processVideoFrame( } pipeline - .with(layout, bindGroup) + .with(bindGroup) .withColorAttachment({ loadOp: 'clear', storeOp: 'store', diff --git a/apps/typegpu-docs/src/examples/rendering/cubemap-reflection/icosphere.ts b/apps/typegpu-docs/src/examples/rendering/cubemap-reflection/icosphere.ts index 35b093f54..e313ffd86 100644 --- a/apps/typegpu-docs/src/examples/rendering/cubemap-reflection/icosphere.ts +++ b/apps/typegpu-docs/src/examples/rendering/cubemap-reflection/icosphere.ts @@ -307,7 +307,7 @@ export class IcosphereGenerator { ); this.pipeline - .with(generatorLayout, bindGroup) + .with(bindGroup) .dispatchWorkgroups(xGroups, yGroups, 1); this.root['~unstable'].flush(); diff --git a/apps/typegpu-docs/src/examples/rendering/cubemap-reflection/index.ts b/apps/typegpu-docs/src/examples/rendering/cubemap-reflection/index.ts index a063a4a25..139a7a88d 100644 --- a/apps/typegpu-docs/src/examples/rendering/cubemap-reflection/index.ts +++ b/apps/typegpu-docs/src/examples/rendering/cubemap-reflection/index.ts @@ -291,8 +291,8 @@ function render() { storeOp: 'store', }) .with(cubeVertexLayout, cubeVertexBuffer) - .with(renderLayout, renderBindGroup) - .with(textureLayout, textureBindGroup) + .with(renderBindGroup) + .with(textureBindGroup) .draw(cubeVertices.length); pipeline @@ -303,8 +303,8 @@ function render() { storeOp: 'store', }) .with(vertexLayout, vertexBuffer) - .with(renderLayout, renderBindGroup) - .with(textureLayout, textureBindGroup) + .with(renderBindGroup) + .with(textureBindGroup) .draw(vertexBuffer.dataType.elementCount); root['~unstable'].flush(); diff --git a/apps/typegpu-docs/src/examples/rendering/perlin-noise/index.ts b/apps/typegpu-docs/src/examples/rendering/perlin-noise/index.ts index 1a78f5579..7025d91a2 100644 --- a/apps/typegpu-docs/src/examples/rendering/perlin-noise/index.ts +++ b/apps/typegpu-docs/src/examples/rendering/perlin-noise/index.ts @@ -114,7 +114,7 @@ function draw(timestamp: number) { time.write(timestamp * 0.0002 % DEPTH); renderPipelines[activeSharpenFn] - .with(dynamicLayout, bindGroup) + .with(bindGroup) .withColorAttachment({ view: context.getCurrentTexture().createView(), loadOp: 'clear', diff --git a/apps/typegpu-docs/src/examples/rendering/two-boxes/index.ts b/apps/typegpu-docs/src/examples/rendering/two-boxes/index.ts index d184f9a20..771749feb 100644 --- a/apps/typegpu-docs/src/examples/rendering/two-boxes/index.ts +++ b/apps/typegpu-docs/src/examples/rendering/two-boxes/index.ts @@ -281,7 +281,7 @@ function drawObject( depthStoreOp: 'store', }) .with(vertexLayout, buffer) - .with(layout, group) + .with(group) .draw(vertexCount); } diff --git a/apps/typegpu-docs/src/examples/simple/liquid-glass/mipmaps.ts b/apps/typegpu-docs/src/examples/simple/liquid-glass/mipmaps.ts index 9de1a916e..45a56b153 100644 --- a/apps/typegpu-docs/src/examples/simple/liquid-glass/mipmaps.ts +++ b/apps/typegpu-docs/src/examples/simple/liquid-glass/mipmaps.ts @@ -78,7 +78,6 @@ export async function loadExternalImageWithMipmaps( loadOp: 'clear', storeOp: 'store', }).with( - downsampleLayout, root.createBindGroup(downsampleLayout, { source: sourceView, }), diff --git a/apps/typegpu-docs/src/examples/simple/oklab/index.ts b/apps/typegpu-docs/src/examples/simple/oklab/index.ts index 1dcec6361..739eca8ea 100644 --- a/apps/typegpu-docs/src/examples/simple/oklab/index.ts +++ b/apps/typegpu-docs/src/examples/simple/oklab/index.ts @@ -173,7 +173,7 @@ function draw() { `; pipeline - .with(layout, bindGroup) + .with(bindGroup) .withColorAttachment({ view: context.getCurrentTexture().createView(), clearValue: [0, 0, 0, 0], diff --git a/apps/typegpu-docs/src/examples/simulation/boids-next/index.ts b/apps/typegpu-docs/src/examples/simulation/boids-next/index.ts index 6af3580f7..d67e0e38f 100644 --- a/apps/typegpu-docs/src/examples/simulation/boids-next/index.ts +++ b/apps/typegpu-docs/src/examples/simulation/boids-next/index.ts @@ -274,7 +274,7 @@ function frame() { even = !even; computePipeline - .with(computeBindGroupLayout, computeBindGroups[even ? 0 : 1]) + .with(computeBindGroups[even ? 0 : 1]) .dispatchWorkgroups(triangleAmount); renderPipeline diff --git a/apps/typegpu-docs/src/examples/simulation/gravity/index.ts b/apps/typegpu-docs/src/examples/simulation/gravity/index.ts index ddac38cd5..4c233e802 100644 --- a/apps/typegpu-docs/src/examples/simulation/gravity/index.ts +++ b/apps/typegpu-docs/src/examples/simulation/gravity/index.ts @@ -153,11 +153,11 @@ let depthTexture = root.device.createTexture({ function render() { computeCollisionsPipeline - .with(computeLayout, dynamicResourcesBox.data.computeCollisionsBindGroup) + .with(dynamicResourcesBox.data.computeCollisionsBindGroup) .dispatchWorkgroups(celestialBodiesCount); computeGravityPipeline - .with(computeLayout, dynamicResourcesBox.data.computeGravityBindGroup) + .with(dynamicResourcesBox.data.computeGravityBindGroup) .dispatchWorkgroups(celestialBodiesCount); skyBoxPipeline @@ -184,7 +184,7 @@ function render() { depthStoreOp: 'store', }) .with(renderVertexLayout, sphereVertexBuffer) - .with(renderBindGroupLayout, dynamicResourcesBox.data.renderBindGroup) + .with(dynamicResourcesBox.data.renderBindGroup) .draw(sphereVertexCount, celestialBodiesCount); } diff --git a/apps/typegpu-docs/src/examples/simulation/stable-fluid/index.ts b/apps/typegpu-docs/src/examples/simulation/stable-fluid/index.ts index e20ef71b5..ca513591d 100644 --- a/apps/typegpu-docs/src/examples/simulation/stable-fluid/index.ts +++ b/apps/typegpu-docs/src/examples/simulation/stable-fluid/index.ts @@ -302,47 +302,46 @@ function loop() { }); brushPipeline - .with(c.brushLayout, brushBindGroup) + .with(brushBindGroup) .dispatchWorkgroups(dispatchX, dispatchY); addInkPipeline - .with(c.addInkLayout, addInkBindGroups[inkBuffer.currentIndex]) + .with(addInkBindGroups[inkBuffer.currentIndex]) .dispatchWorkgroups(dispatchX, dispatchY); inkBuffer.swap(); addForcePipeline - .with(c.addForcesLayout, addForceBindGroups[velBuffer.currentIndex]) + .with(addForceBindGroups[velBuffer.currentIndex]) .dispatchWorkgroups(dispatchX, dispatchY); } else { velBuffer.setCurrent(0); } advectPipeline - .with(c.advectLayout, advectBindGroups[velBuffer.currentIndex]) + .with(advectBindGroups[velBuffer.currentIndex]) .dispatchWorkgroups(dispatchX, dispatchY); for (let i = 0; i < p.params.jacobiIter; i++) { diffusionPipeline - .with(c.diffusionLayout, diffusionBindGroups[velBuffer.currentIndex]) + .with(diffusionBindGroups[velBuffer.currentIndex]) .dispatchWorkgroups(dispatchX, dispatchY); velBuffer.swap(); } divergencePipeline - .with(c.divergenceLayout, divergenceBindGroups[velBuffer.currentIndex]) + .with(divergenceBindGroups[velBuffer.currentIndex]) .dispatchWorkgroups(dispatchX, dispatchY); pressureBuffer.setCurrent(0); for (let i = 0; i < p.params.jacobiIter; i++) { pressurePipeline - .with(c.pressureLayout, pressureBindGroups[pressureBuffer.currentIndex]) + .with(pressureBindGroups[pressureBuffer.currentIndex]) .dispatchWorkgroups(dispatchX, dispatchY); pressureBuffer.swap(); } projectPipeline .with( - c.projectLayout, projectBindGroups[velBuffer.currentIndex][pressureBuffer.currentIndex], ) .dispatchWorkgroups(dispatchX, dispatchY); @@ -350,7 +349,6 @@ function loop() { advectInkPipeline .with( - c.advectInkLayout, advectInkBindGroups[velBuffer.currentIndex][inkBuffer.currentIndex], ) .dispatchWorkgroups(dispatchX, dispatchY); @@ -388,7 +386,7 @@ function loop() { loadOp: 'clear', storeOp: 'store', }) - .with(renderLayout, renderBG) + .with(renderBG) .draw(3); requestAnimationFrame(loop); diff --git a/apps/typegpu-docs/src/examples/tests/dispatch/index.ts b/apps/typegpu-docs/src/examples/tests/dispatch/index.ts index 08d576710..43a96cb35 100644 --- a/apps/typegpu-docs/src/examples/tests/dispatch/index.ts +++ b/apps/typegpu-docs/src/examples/tests/dispatch/index.ts @@ -114,8 +114,8 @@ async function testDifferentBindGroups(): Promise { } }); - test.with(layout, bindGroup1).dispatch(); - test.with(layout, bindGroup2).dispatch(); + test.with(bindGroup1).dispatch(); + test.with(bindGroup2).dispatch(); const filled1 = await buffer1.read(); const filled2 = await buffer2.read(); diff --git a/packages/typegpu-noise/src/perlin-2d/dynamic-cache.ts b/packages/typegpu-noise/src/perlin-2d/dynamic-cache.ts index 7068f7492..fd270e19b 100644 --- a/packages/typegpu-noise/src/perlin-2d/dynamic-cache.ts +++ b/packages/typegpu-noise/src/perlin-2d/dynamic-cache.ts @@ -97,7 +97,7 @@ const DefaultPerlin2DLayoutPrefix = 'perlin2dCache__' as const; * const group = root.createBindGroup(dynamicLayout, { ...cache.bindings }); * * pipeline - * .with(dynamicLayout, group) + * .with(group) * // ... * .draw(3); * }; @@ -198,7 +198,7 @@ export function dynamicCacheConfig( }); computePipeline - .with(computeLayout, computeBindGroup) + .with(computeBindGroup) .dispatchWorkgroups(size.x, size.y); return memory; diff --git a/packages/typegpu-noise/src/perlin-3d/dynamic-cache.ts b/packages/typegpu-noise/src/perlin-3d/dynamic-cache.ts index 10e867598..7c501561e 100644 --- a/packages/typegpu-noise/src/perlin-3d/dynamic-cache.ts +++ b/packages/typegpu-noise/src/perlin-3d/dynamic-cache.ts @@ -97,7 +97,7 @@ const DefaultPerlin3DLayoutPrefix = 'perlin3dCache__' as const; * const group = root.createBindGroup(dynamicLayout, { ...perlinCache.bindings }); * * pipeline - * .with(dynamicLayout, group) + * .with(group) * // ... * .draw(3); * }; @@ -202,7 +202,7 @@ export function dynamicCacheConfig( }); computePipeline - .with(computeLayout, computeBindGroup) + .with(computeBindGroup) .dispatchWorkgroups(size.x, size.y, size.z); return memory; diff --git a/packages/typegpu/src/errors.ts b/packages/typegpu/src/errors.ts index 10c258f75..5b3399cb2 100644 --- a/packages/typegpu/src/errors.ts +++ b/packages/typegpu/src/errors.ts @@ -161,7 +161,7 @@ export class MissingBindGroupsError extends Error { super( `Missing bind groups for layouts: '${ [...layouts].map((layout) => getName(layout) ?? '').join(', ') - }'. Please provide it using pipeline.with(layout, bindGroup).(...)`, + }'. Please provide it using pipeline.with(bindGroup).(...)`, ); // Set the prototype explicitly. diff --git a/packages/typegpu/src/prepareDispatch.ts b/packages/typegpu/src/prepareDispatch.ts index b7d3e2253..76989090a 100644 --- a/packages/typegpu/src/prepareDispatch.ts +++ b/packages/typegpu/src/prepareDispatch.ts @@ -7,10 +7,7 @@ import { u32 } from './data/numeric.ts'; import { vec3f, vec3u } from './data/vector.ts'; import type { v3u } from './data/wgslTypes.ts'; import { ceil } from './std/numeric.ts'; -import type { - TgpuBindGroup, - TgpuBindGroupLayout, -} from './tgpuBindGroupLayout.ts'; +import type { TgpuBindGroup } from './tgpuBindGroupLayout.ts'; /** * Changes the given array to a vec of 3 numbers, filling missing values with 1. @@ -43,15 +40,12 @@ class PreparedDispatch { /** * Returns a new PreparedDispatch with the specified bind group bound. - * Analogous to `TgpuComputePipeline.with()`. + * Analogous to `TgpuComputePipeline.with(bindGroup)`. */ - with( - bindGroupLayout: TgpuBindGroupLayout, - bindGroup: TgpuBindGroup, - ): PreparedDispatch { + with(bindGroup: TgpuBindGroup): PreparedDispatch { return new PreparedDispatch( this.#createDispatch, - this.#pipeline.with(bindGroupLayout, bindGroup), + this.#pipeline.with(bindGroup), ); } diff --git a/packages/typegpu/tests/computePipeline.test.ts b/packages/typegpu/tests/computePipeline.test.ts index 58c267e84..29234f77d 100644 --- a/packages/typegpu/tests/computePipeline.test.ts +++ b/packages/typegpu/tests/computePipeline.test.ts @@ -48,7 +48,7 @@ describe('TgpuComputePipeline', () => { expect(() => pipeline.dispatchWorkgroups(1)) .toThrowErrorMatchingInlineSnapshot( - `[Error: Missing bind groups for layouts: 'layout'. Please provide it using pipeline.with(layout, bindGroup).(...)]`, + `[Error: Missing bind groups for layouts: 'layout'. Please provide it using pipeline.with(bindGroup).(...)]`, ); }); @@ -348,12 +348,12 @@ describe('TgpuComputePipeline', () => { beginningOfPassWriteIndex: 0, endOfPassWriteIndex: 1, }) - .with(layout, bindGroup); + .with(bindGroup); const pipeline2 = root .withCompute(entryFn) .createPipeline() - .with(layout, bindGroup) + .with(bindGroup) .withTimestampWrites({ querySet, beginningOfPassWriteIndex: 2, diff --git a/packages/typegpu/tests/renderPipeline.test.ts b/packages/typegpu/tests/renderPipeline.test.ts index 11ed9808d..72489a9e0 100644 --- a/packages/typegpu/tests/renderPipeline.test.ts +++ b/packages/typegpu/tests/renderPipeline.test.ts @@ -114,7 +114,7 @@ describe('TgpuRenderPipeline', () => { ); expect(() => pipeline.draw(6)).toThrowErrorMatchingInlineSnapshot( - `[Error: Missing bind groups for layouts: 'layout'. Please provide it using pipeline.with(layout, bindGroup).(...)]`, + `[Error: Missing bind groups for layouts: 'layout'. Please provide it using pipeline.with(bindGroup).(...)]`, ); }); diff --git a/packages/typegpu/tests/root.test.ts b/packages/typegpu/tests/root.test.ts index 1cbc6db8a..d13953ad3 100644 --- a/packages/typegpu/tests/root.test.ts +++ b/packages/typegpu/tests/root.test.ts @@ -273,7 +273,7 @@ describe('TgpuRoot', () => { .withVertex(mainVertexUsing, {}) .withFragment(mainFragment, {}) .createPipeline() - .with(layout, group); + .with(group); root.beginRenderPass( { From cc2ee1ca99f7ad55426d8fcd5dae613c74f5baea Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Wed, 1 Oct 2025 15:56:17 +0200 Subject: [PATCH 6/6] Update docs --- apps/typegpu-docs/src/content/docs/fundamentals/pipelines.mdx | 2 +- apps/typegpu-docs/src/content/docs/fundamentals/utils.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/typegpu-docs/src/content/docs/fundamentals/pipelines.mdx b/apps/typegpu-docs/src/content/docs/fundamentals/pipelines.mdx index d9713472d..1f29da63b 100644 --- a/apps/typegpu-docs/src/content/docs/fundamentals/pipelines.mdx +++ b/apps/typegpu-docs/src/content/docs/fundamentals/pipelines.mdx @@ -277,7 +277,7 @@ renderPipeline ### Resource bindings -Before executing pipelines, it is necessary to bind all of the utilized resources, like bind groups, vertex buffers and slots. It is done using the `with` method. It accepts a pair of arguments: [a bind group layout and a bind group](/TypeGPU/fundamentals/bind-groups) (render and compute pipelines) or [a vertex layout and a vertex buffer](/TypeGPU/fundamentals/vertex-layouts) (render pipelines only). +Before executing pipelines, it is necessary to bind all of the utilized resources, like bind groups, vertex buffers and slots. It is done using the `with` method. It accepts either [a bind group](/TypeGPU/fundamentals/bind-groups) (render and compute pipelines) or [a vertex layout and a vertex buffer](/TypeGPU/fundamentals/vertex-layouts) (render pipelines only). ```ts // vertex layout diff --git a/apps/typegpu-docs/src/content/docs/fundamentals/utils.mdx b/apps/typegpu-docs/src/content/docs/fundamentals/utils.mdx index 2d81e7a95..1dead965a 100644 --- a/apps/typegpu-docs/src/content/docs/fundamentals/utils.mdx +++ b/apps/typegpu-docs/src/content/docs/fundamentals/utils.mdx @@ -62,7 +62,7 @@ prepareDispatch(root, (x, y) => { console.log(await waterLevelMutable.read()); ``` -Analogously to `TgpuComputePipeline`, the result of `prepareDispatch` can have bind groups bound using the `with` method. +The result of `prepareDispatch` can have bind groups bound using the `with` method. ```ts twoslash import tgpu, { prepareDispatch } from 'typegpu';