Skip to content

Commit 7b2cbaa

Browse files
authored
feat(🫵): Add ptr<function, ...> schema (#806)
1 parent e5c4db8 commit 7b2cbaa

File tree

6 files changed

+64
-0
lines changed

6 files changed

+64
-0
lines changed

packages/typegpu/src/core/resolve/resolveData.ts

+4
Original file line numberDiff line numberDiff line change
@@ -165,5 +165,9 @@ export function resolveData(ctx: ResolutionCtx, data: AnyWgslData): string {
165165
return ctx.resolve(data.inner as AnyWgslData);
166166
}
167167

168+
if (data.type === 'ptrFn') {
169+
return `ptr<function, ${ctx.resolve(data.inner)}>`;
170+
}
171+
168172
assertExhaustive(data, 'resolveData');
169173
}

packages/typegpu/src/data/dataIO.ts

+8
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ const dataWriters = {
186186
output.seekTo(beginning + sizeOf(schema));
187187
},
188188

189+
ptrFn() {
190+
throw new Error('Pointers are not host-shareable');
191+
},
192+
189193
atomic(output, schema: wgsl.Atomic, value: number) {
190194
dataWriters[schema.inner.type]?.(output, schema, value);
191195
},
@@ -615,6 +619,10 @@ const dataReaders = {
615619
return elements as never[];
616620
},
617621

622+
ptrFn() {
623+
throw new Error('Pointers are not host-shareable');
624+
},
625+
618626
atomic(input, schema: wgsl.Atomic): number {
619627
return readData(input, schema.inner);
620628
},

packages/typegpu/src/data/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export {
77
isWgslData,
88
isWgslArray,
99
isWgslStruct,
10+
isPtrFn,
1011
isAtomic,
1112
isDecorated,
1213
isAlignAttrib,
@@ -39,6 +40,7 @@ export type {
3940
Mat4x4f,
4041
WgslStruct,
4142
WgslArray,
43+
PtrFn,
4244
Atomic,
4345
Decorated,
4446
Size,
@@ -68,6 +70,7 @@ export {
6870
TgpuArray,
6971
arrayOf,
7072
} from './array';
73+
export { ptrFn } from './ptr';
7174
export type {
7275
Disarray,
7376
Unstruct,

packages/typegpu/src/data/ptr.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { AnyData } from './dataTypes';
2+
import type { Exotic } from './exotic';
3+
import type { PtrFn } from './wgslTypes';
4+
5+
export function ptrFn<T extends AnyData>(inner: T): PtrFn<Exotic<T>> {
6+
return {
7+
type: 'ptrFn',
8+
inner: inner as Exotic<T>,
9+
} as PtrFn<Exotic<T>>;
10+
}

packages/typegpu/src/data/wgslTypes.ts

+20
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,13 @@ export interface WgslArray<TElement = BaseWgslData> {
694694
readonly '~repr': Infer<TElement>[];
695695
}
696696

697+
export interface PtrFn<TInner = BaseWgslData> {
698+
readonly type: 'ptrFn';
699+
readonly inner: TInner;
700+
/** Type-token, not available at runtime */
701+
readonly '~repr': Infer<TInner>;
702+
}
703+
697704
/**
698705
* Schema representing the `atomic<...>` WGSL data type.
699706
*/
@@ -770,6 +777,7 @@ export const wgslTypeLiterals = [
770777
'mat4x4f',
771778
'struct',
772779
'array',
780+
'ptrFn',
773781
'atomic',
774782
'decorated',
775783
] as const;
@@ -820,6 +828,7 @@ export type AnyWgslData =
820828
| Mat4x4f
821829
| AnyWgslStruct
822830
| WgslArray
831+
| PtrFn
823832
| Atomic
824833
| Decorated;
825834

@@ -865,6 +874,17 @@ export function isWgslStruct<T extends WgslStruct>(
865874
return (schema as T)?.type === 'struct';
866875
}
867876

877+
/**
878+
* Checks whether passed in value is a pointer ('function' scope) schema.
879+
*
880+
* @example
881+
* isPtrFn(d.ptrFn(d.f32)) // true
882+
* isPtrFn(d.f32) // false
883+
*/
884+
export function isPtrFn<T extends PtrFn>(schema: T | unknown): schema is T {
885+
return (schema as T)?.type === 'ptrFn';
886+
}
887+
868888
/**
869889
* Checks whether the passed in value is an atomic schema.
870890
*
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { describe, expect, expectTypeOf, it } from 'vitest';
2+
import tgpu from '../../src';
3+
import * as d from '../../src/data';
4+
5+
describe('d.ptrFn', () => {
6+
it('wraps a schema and infers type properly', () => {
7+
const ptrToU32 = d.ptrFn(d.u32);
8+
9+
expectTypeOf(ptrToU32).toEqualTypeOf<d.PtrFn<d.U32>>();
10+
});
11+
12+
it('resolves to matching WGSL', () => {
13+
const ptrToU32 = d.ptrFn(d.u32);
14+
15+
expect(
16+
tgpu.resolve({ externals: { ptrToU32 }, template: 'ptrToU32' }),
17+
).toMatchInlineSnapshot(`"ptr<function, u32>"`);
18+
});
19+
});

0 commit comments

Comments
 (0)