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..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 @@ -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..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'; @@ -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 85128709d..3f086df30 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/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/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 21696d63c..2808485dd 100644 --- a/apps/typegpu-docs/src/examples/rendering/cubemap-reflection/index.ts +++ b/apps/typegpu-docs/src/examples/rendering/cubemap-reflection/index.ts @@ -300,8 +300,8 @@ function render() { storeOp: 'store', }) .with(cubeVertexLayout, cubeVertexBuffer) - .with(renderLayout, renderBindGroup) - .with(textureLayout, textureBindGroup) + .with(renderBindGroup) + .with(textureBindGroup) .draw(cubeVertices.length); pipeline @@ -312,8 +312,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 e9c81251f..fb21379bd 100644 --- a/apps/typegpu-docs/src/examples/rendering/two-boxes/index.ts +++ b/apps/typegpu-docs/src/examples/rendering/two-boxes/index.ts @@ -289,7 +289,7 @@ function drawObject( depthStoreOp: 'store', }) .with(vertexLayout, buffer) - .with(layout, group) + .with(group) .draw(vertexCount); } 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 eb580f242..9dfdf0d73 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 81db0e442..e9624cb05 100644 --- a/apps/typegpu-docs/src/examples/simulation/stable-fluid/index.ts +++ b/apps/typegpu-docs/src/examples/simulation/stable-fluid/index.ts @@ -320,47 +320,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); @@ -368,7 +367,6 @@ function loop() { advectInkPipeline .with( - c.advectInkLayout, advectInkBindGroups[velBuffer.currentIndex][inkBuffer.currentIndex], ) .dispatchWorkgroups(dispatchX, dispatchY); @@ -406,7 +404,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/core/pipeline/computePipeline.ts b/packages/typegpu/src/core/pipeline/computePipeline.ts index 6322f85ff..7abe63512 100644 --- a/packages/typegpu/src/core/pipeline/computePipeline.ts +++ b/packages/typegpu/src/core/pipeline/computePipeline.ts @@ -6,9 +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, +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'; @@ -45,10 +47,15 @@ export interface TgpuComputePipeline readonly [$internal]: ComputePipelineInternals; readonly resourceType: 'compute-pipeline'; - with( - bindGroupLayout: TgpuBindGroupLayout, - bindGroup: TgpuBindGroup, - ): TgpuComputePipeline; + /** + * @deprecated This overload is outdated. + * Call `pipeline.with(bindGroup)` instead. + */ + with>( + bindGroupLayout: TgpuBindGroupLayout, + bindGroup: TgpuBindGroup, + ): this; + with(bindGroup: TgpuBindGroup): this; dispatchWorkgroups( x: number, @@ -118,17 +125,32 @@ class TgpuComputePipelineImpl implements TgpuComputePipeline { return this._core.unwrap().pipeline; } + with>( + bindGroupLayout: TgpuBindGroupLayout, + bindGroup: TgpuBindGroup, + ): this; + with(bindGroup: TgpuBindGroup): this; with( - bindGroupLayout: TgpuBindGroupLayout, - bindGroup: TgpuBindGroup, - ): TgpuComputePipeline { + 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; } withPerformanceCallback( diff --git a/packages/typegpu/src/core/pipeline/renderPipeline.ts b/packages/typegpu/src/core/pipeline/renderPipeline.ts index 27aebe1ab..77613d581 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, @@ -95,10 +96,15 @@ export interface TgpuRenderPipeline vertexLayout: TgpuVertexLayout, buffer: TgpuBuffer & VertexFlag, ): this; + /** + * @deprecated This overload is outdated. + * Call `pipeline.with(bindGroup)` instead. + */ with>( bindGroupLayout: TgpuBindGroupLayout, bindGroup: TgpuBindGroup, ): this; + with(bindGroup: TgpuBindGroup): this; withColorAttachment( attachment: FragmentOutToColorAttachment, @@ -330,28 +336,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 ?? []), + [layoutOrBindGroup.layout, layoutOrBindGroup], + ]), + }) as this; + } + + if (isBindGroupLayout(layoutOrBindGroup)) { return new TgpuRenderPipelineImpl(internals.core, { ...internals.priors, bindGroupLayoutMap: new Map([ ...(internals.priors.bindGroupLayoutMap ?? []), - [definition, resource as TgpuBindGroup], + [layoutOrBindGroup, resource as TgpuBindGroup], ]), }) as this; } - if (isVertexLayout(definition)) { + 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; } 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 673e381cd..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).(...)]`, ); }); @@ -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] })( @@ -324,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 f2e248884..2fbb77445 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).(...)]`, ); }); @@ -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'] 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( {