Skip to content

Commit f5cfbe2

Browse files
authored
Fix invalid bound type for samplers (#771)
1 parent d44bc55 commit f5cfbe2

File tree

4 files changed

+118
-24
lines changed

4 files changed

+118
-24
lines changed

packages/typegpu/src/experimental/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ export type {
151151
TgpuBindGroupLayout,
152152
TgpuLayoutEntry,
153153
TgpuLayoutSampler,
154+
TgpuLayoutComparisonSampler,
154155
TgpuLayoutTexture,
155156
TgpuLayoutStorage,
156157
TgpuLayoutStorageTexture,

packages/typegpu/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export type {
6666
TgpuBindGroupLayout,
6767
TgpuLayoutEntry,
6868
TgpuLayoutSampler,
69+
TgpuLayoutComparisonSampler,
6970
TgpuLayoutTexture,
7071
TgpuLayoutStorage,
7172
TgpuLayoutStorageTexture,

packages/typegpu/src/tgpuBindGroupLayout.ts

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
TgpuLaidOutBufferImpl,
1212
} from './core/buffer/bufferUsage';
1313
import {
14+
type TgpuComparisonSampler,
1415
TgpuLaidOutComparisonSamplerImpl,
1516
TgpuLaidOutSamplerImpl,
1617
type TgpuSampler,
@@ -87,8 +88,13 @@ export type TgpuLayoutStorage = TgpuLayoutEntryBase & {
8788
};
8889

8990
export type TgpuLayoutSampler = TgpuLayoutEntryBase & {
90-
sampler: GPUSamplerBindingType;
91+
sampler: 'filtering' | 'non-filtering';
9192
};
93+
94+
export type TgpuLayoutComparisonSampler = TgpuLayoutEntryBase & {
95+
sampler: 'comparison';
96+
};
97+
9298
export type TgpuLayoutTexture<
9399
TSampleType extends GPUTextureSampleType = GPUTextureSampleType,
94100
> = TgpuLayoutEntryBase & {
@@ -126,6 +132,7 @@ export type TgpuLayoutEntry =
126132
| TgpuLayoutUniform
127133
| TgpuLayoutStorage
128134
| TgpuLayoutSampler
135+
| TgpuLayoutComparisonSampler
129136
| TgpuLayoutTexture
130137
| TgpuLayoutStorageTexture
131138
| TgpuLayoutExternalTexture;
@@ -265,24 +272,26 @@ export type LayoutEntryToInput<T extends TgpuLayoutEntry | null> =
265272
| (TgpuBuffer<UnwrapRuntimeConstructor<T['storage']>> & Storage)
266273
| GPUBuffer
267274
: T extends TgpuLayoutSampler
268-
? GPUSampler
269-
: T extends TgpuLayoutTexture
270-
?
271-
| GPUTextureView
272-
| (Sampled &
273-
TgpuTexture<
274-
Prettify<TextureProps & GetTextureRestriction<T>>
275-
>)
276-
: T extends TgpuLayoutStorageTexture
275+
? TgpuSampler | GPUSampler
276+
: T extends TgpuLayoutComparisonSampler
277+
? TgpuComparisonSampler | GPUSampler
278+
: T extends TgpuLayoutTexture
277279
?
278280
| GPUTextureView
279-
| (Storage &
281+
| (Sampled &
280282
TgpuTexture<
281-
Prettify<TextureProps & GetStorageTextureRestriction<T>>
283+
Prettify<TextureProps & GetTextureRestriction<T>>
282284
>)
283-
: T extends TgpuLayoutExternalTexture
284-
? GPUExternalTexture
285-
: never;
285+
: T extends TgpuLayoutStorageTexture
286+
?
287+
| GPUTextureView
288+
| (Storage &
289+
TgpuTexture<
290+
Prettify<TextureProps & GetStorageTextureRestriction<T>>
291+
>)
292+
: T extends TgpuLayoutExternalTexture
293+
? GPUExternalTexture
294+
: never;
286295

287296
export type BindLayoutEntry<T extends TgpuLayoutEntry | null> =
288297
T extends TgpuLayoutUniform
@@ -291,14 +300,16 @@ export type BindLayoutEntry<T extends TgpuLayoutEntry | null> =
291300
? StorageUsageForEntry<T>
292301
: T extends TgpuLayoutSampler
293302
? TgpuSampler
294-
: T extends TgpuLayoutTexture
295-
? TgpuSampledTexture<
296-
Default<GetDimension<T['viewDimension']>, '2d'>,
297-
ChannelFormatToSchema[T['texture']]
298-
>
299-
: T extends TgpuLayoutStorageTexture
300-
? StorageTextureUsageForEntry<T>
301-
: never;
303+
: T extends TgpuLayoutComparisonSampler
304+
? TgpuComparisonSampler
305+
: T extends TgpuLayoutTexture
306+
? TgpuSampledTexture<
307+
Default<GetDimension<T['viewDimension']>, '2d'>,
308+
ChannelFormatToSchema[T['texture']]
309+
>
310+
: T extends TgpuLayoutStorageTexture
311+
? StorageTextureUsageForEntry<T>
312+
: never;
302313

303314
export type TgpuBindGroup<
304315
Entries extends Record<string, TgpuLayoutEntry | null> = Record<

packages/typegpu/tests/bindGroupLayout.test.ts

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,12 @@ import tgpu, {
2323
} from '../src/experimental';
2424
import './utils/webgpuGlobals';
2525
import { parse } from 'tgpu-wgsl-parser';
26+
import { comparisonSampler, sampler } from '../src/core/sampler/sampler';
2627
import {
2728
MissingBindingError,
2829
type TgpuBindGroup,
30+
type TgpuLayoutComparisonSampler,
31+
type TgpuLayoutSampler,
2932
type UnwrapRuntimeConstructor,
3033
bindGroupLayout,
3134
} from '../src/tgpuBindGroupLayout';
@@ -283,7 +286,7 @@ describe('TgpuBindGroup', () => {
283286
});
284287

285288
describe('filtering sampler layout', () => {
286-
let layout: TgpuBindGroupLayout<{ foo: { sampler: 'filtering' } }>;
289+
let layout: TgpuBindGroupLayout<{ foo: TgpuLayoutSampler }>;
287290

288291
beforeEach(() => {
289292
layout = tgpu
@@ -315,6 +318,84 @@ describe('TgpuBindGroup', () => {
315318
],
316319
});
317320
});
321+
322+
it('accepts filtering/non-filtering sampler when creating bind group, but not comparison', ({
323+
root,
324+
}) => {
325+
root.createBindGroup(layout, {
326+
foo: sampler({ minFilter: 'linear' }),
327+
});
328+
329+
root.createBindGroup(layout, {
330+
foo: sampler({ minFilter: 'nearest' }),
331+
});
332+
333+
root.createBindGroup(layout, {
334+
foo: root.device.createSampler(),
335+
});
336+
337+
root.createBindGroup(layout, {
338+
// @ts-expect-error
339+
foo: comparisonSampler({ compare: 'less' }),
340+
});
341+
});
342+
});
343+
344+
describe('comparison sampler layout', () => {
345+
let layout: TgpuBindGroupLayout<{ foo: TgpuLayoutComparisonSampler }>;
346+
347+
beforeEach(() => {
348+
layout = tgpu
349+
.bindGroupLayout({
350+
foo: { sampler: 'comparison' },
351+
})
352+
.$name('example');
353+
});
354+
355+
it('populates a simple layout with a raw sampler', ({ root }) => {
356+
const sampler = root.device.createSampler();
357+
358+
const bindGroup = root.createBindGroup(layout, {
359+
foo: sampler,
360+
});
361+
362+
expect(root.device.createBindGroupLayout).not.toBeCalled();
363+
root.unwrap(bindGroup);
364+
expect(root.device.createBindGroupLayout).toBeCalled();
365+
366+
expect(root.device.createBindGroup).toBeCalledWith({
367+
label: 'example',
368+
layout: root.unwrap(layout),
369+
entries: [
370+
{
371+
binding: 0,
372+
resource: sampler,
373+
},
374+
],
375+
});
376+
});
377+
378+
it('accepts comparison sampler when creating bind group, but not filtering/non-filtering', ({
379+
root,
380+
}) => {
381+
root.createBindGroup(layout, {
382+
foo: comparisonSampler({ compare: 'equal' }),
383+
});
384+
385+
root.createBindGroup(layout, {
386+
foo: root.device.createSampler(),
387+
});
388+
389+
root.createBindGroup(layout, {
390+
// @ts-expect-error
391+
foo: sampler({ minFilter: 'linear' }),
392+
});
393+
394+
root.createBindGroup(layout, {
395+
// @ts-expect-error
396+
foo: sampler({ minFilter: 'nearest' }),
397+
});
398+
});
318399
});
319400

320401
describe('texture layout', () => {

0 commit comments

Comments
 (0)