Skip to content

Commit 3f10ef8

Browse files
authored
feat: Texture std expansion and generator adjustments (#1189)
1 parent 7415eaf commit 3f10ef8

File tree

8 files changed

+157
-5
lines changed

8 files changed

+157
-5
lines changed

packages/typegpu/src/core/root/init.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type { Infer } from '../../shared/repr.ts';
1717
import { $internal } from '../../shared/symbols.ts';
1818
import type { AnyVertexAttribs } from '../../shared/vertexFormat.ts';
1919
import type {
20-
LayoutEntryToInput,
20+
ExtractBindGroupInputFromLayout,
2121
TgpuBindGroup,
2222
TgpuBindGroupLayout,
2323
TgpuLayoutEntry,
@@ -289,9 +289,7 @@ class TgpuRootImpl
289289
>,
290290
>(
291291
layout: TgpuBindGroupLayout<Entries>,
292-
entries: {
293-
[K in keyof Entries]: LayoutEntryToInput<Entries[K]>;
294-
},
292+
entries: ExtractBindGroupInputFromLayout<Entries>,
295293
) {
296294
return new TgpuBindGroupImpl(layout, entries);
297295
}

packages/typegpu/src/data/vectorOps.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,32 @@ export const VectorOps = {
829829
<T extends wgsl.AnyFloatVecInstance | number>(a: T, b: T) => T
830830
>,
831831

832+
sqrt: {
833+
vec2f: unary2f(Math.sqrt),
834+
vec2h: unary2h(Math.sqrt),
835+
836+
vec3f: unary3f(Math.sqrt),
837+
vec3h: unary3h(Math.sqrt),
838+
839+
vec4f: unary4f(Math.sqrt),
840+
vec4h: unary4h(Math.sqrt),
841+
} as Record<VecKind, <T extends vBase>(v: T) => T>,
842+
843+
div: {
844+
vec2f: binaryComponentWise2f((a, b) => a / b),
845+
vec2h: binaryComponentWise2h((a, b) => a / b),
846+
vec2i: binaryComponentWise2i((a, b) => a / b),
847+
vec2u: binaryComponentWise2u((a, b) => a / b),
848+
vec3f: binaryComponentWise3f((a, b) => a / b),
849+
vec3h: binaryComponentWise3h((a, b) => a / b),
850+
vec3i: binaryComponentWise3i((a, b) => a / b),
851+
vec3u: binaryComponentWise3u((a, b) => a / b),
852+
vec4f: binaryComponentWise4f((a, b) => a / b),
853+
vec4h: binaryComponentWise4h((a, b) => a / b),
854+
vec4i: binaryComponentWise4i((a, b) => a / b),
855+
vec4u: binaryComponentWise4u((a, b) => a / b),
856+
} as Record<VecKind, <T extends vBase>(a: T, b: T) => T>,
857+
832858
mix: {
833859
vec2f: (e1: wgsl.v2f, e2: wgsl.v2f, e3: wgsl.v2f | number) => {
834860
if (typeof e3 === 'number') {

packages/typegpu/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ export type {
153153
BindLayoutEntry,
154154
LayoutEntryToInput,
155155
TgpuBindGroup,
156+
ExtractBindGroupInputFromLayout,
156157
} from './tgpuBindGroupLayout.ts';
157158
export type {
158159
TgpuFn,

packages/typegpu/src/std/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export {
2828
pow,
2929
reflect,
3030
neg,
31+
sqrt,
32+
div,
3133
} from './numeric.js';
3234

3335
export {

packages/typegpu/src/std/numeric.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,3 +456,40 @@ export const neg = createDualImpl(
456456
// GPU implementation
457457
(value) => ({ value: `-(${value.value})`, dataType: value.dataType }),
458458
);
459+
460+
export const sqrt = createDualImpl(
461+
// CPU implementation
462+
<T extends AnyFloatVecInstance | number>(value: T): T => {
463+
if (typeof value === 'number') {
464+
return Math.sqrt(value) as T;
465+
}
466+
return VectorOps.sqrt[value.kind](value) as T;
467+
},
468+
// GPU implementation
469+
(value) => ({ value: `sqrt(${value.value})`, dataType: value.dataType }),
470+
);
471+
472+
export const div = createDualImpl(
473+
// CPU implementation
474+
<T extends AnyNumericVecInstance | number>(lhs: T, rhs: T | number): T => {
475+
if (typeof lhs === 'number' && typeof rhs === 'number') {
476+
return (lhs / rhs) as T;
477+
}
478+
if (typeof rhs === 'number') {
479+
return VectorOps.mulSxV[(lhs as AnyNumericVecInstance).kind](
480+
1 / rhs,
481+
lhs as AnyNumericVecInstance,
482+
) as T;
483+
}
484+
// Vector / Vector case
485+
return VectorOps.div[(lhs as AnyNumericVecInstance).kind](
486+
lhs as AnyNumericVecInstance,
487+
rhs as AnyNumericVecInstance,
488+
) as T;
489+
},
490+
// GPU implementation
491+
(lhs, rhs) => ({
492+
value: `(${lhs.value} / ${rhs.value})`,
493+
dataType: lhs.dataType,
494+
}),
495+
);

packages/typegpu/src/tgpuBindGroupLayout.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,12 @@ export type InferLayoutEntry<T extends TgpuLayoutEntry | null> =
341341
? StorageTextureUsageForEntry<T>
342342
: never;
343343

344+
export type ExtractBindGroupInputFromLayout<
345+
T extends Record<string, TgpuLayoutEntry | null>,
346+
> = {
347+
[K in keyof T]: LayoutEntryToInput<T[K]>;
348+
};
349+
344350
export type TgpuBindGroup<
345351
Entries extends Record<string, TgpuLayoutEntry | null> = Record<
346352
string,

packages/typegpu/src/tgsl/generationHelpers.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
UnknownData,
4141
type Wgsl,
4242
hasInternalDataType,
43+
isSelfResolvable,
4344
} from '../types.ts';
4445

4546
const swizzleableTypes = [
@@ -245,7 +246,10 @@ export function getTypeFromWgsl(resource: Wgsl): AnyData | UnknownData {
245246
}
246247
}
247248

248-
return isWgslData(resource) ? resource : UnknownData;
249+
// TODO: do not treat self-resolvable as wgsl data (when we have proper texture schemas)
250+
return isWgslData(resource) || isSelfResolvable(resource)
251+
? (resource as unknown as AnyData)
252+
: UnknownData;
249253
}
250254

251255
export function numericLiteralToSnippet(value: string): Snippet | undefined {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { describe, expect, it } from 'vitest';
2+
import * as d from '../../../src/data/index.ts';
3+
import { div } from '../../../src/std/index.ts';
4+
5+
describe('div', () => {
6+
it('computes quotient of a d.vec2f and a number', () => {
7+
expect(div(d.vec2f(0, 0), 17)).toEqual(d.vec2f(0, 0));
8+
expect(div(d.vec2f(0.24, 0), 0.4).x).toBeCloseTo(0.6);
9+
expect(div(d.vec2f(0, 0), 5)).toEqual(d.vec2f());
10+
});
11+
12+
it('computes quotient of a d.vec2u and a number', () => {
13+
expect(div(d.vec2u(0, 0), 2)).toEqual(d.vec2u(0, 0));
14+
expect(div(d.vec2u(3, 3), 3)).toEqual(d.vec2u(1));
15+
});
16+
17+
it('computes quotient of a d.vec2i and a number', () => {
18+
expect(div(d.vec2i(0, 0), 9)).toEqual(d.vec2i(0, 0));
19+
expect(div(d.vec2i(-3, -3), -3)).toEqual(d.vec2i(1));
20+
expect(div(d.vec2i(0, 0), 5)).toEqual(d.vec2i());
21+
});
22+
23+
it('computes quotient of a d.vec3f and a number', () => {
24+
expect(div(d.vec3f(-3, -4, -6), 2)).toEqual(d.vec3f(-1.5, -2, -3));
25+
expect(div(d.vec3f(-2, -2, -2), -2)).toEqual(d.vec3f(1));
26+
expect(div(d.vec3f(0, 0, 0), 5)).toEqual(d.vec3f());
27+
});
28+
29+
it('computes quotient of a d.vec3u and a number', () => {
30+
expect(div(d.vec3u(2, 2, 2), 2)).toEqual(d.vec3u(1));
31+
expect(div(d.vec3u(0, 0, 0), 5)).toEqual(d.vec3u());
32+
});
33+
34+
it('computes quotient of a d.vec3i and a number', () => {
35+
expect(div(d.vec3i(-1, -2, -3), 1)).toEqual(d.vec3i(-1, -2, -3));
36+
expect(div(d.vec3i(-4, -6, -8), -2)).toEqual(d.vec3i(2, 3, 4));
37+
expect(div(d.vec3i(2, 2, 2), 2)).toEqual(d.vec3i(1));
38+
});
39+
40+
it('computes quotient of a d.vec4f and a number', () => {
41+
expect(div(d.vec4f(1.5, 2, 3, 4), 2)).toEqual(d.vec4f(0.75, 1, 1.5, 2));
42+
expect(div(d.vec4f(4, 7, 8, 10), 2)).toEqual(d.vec4f(2, 3.5, 4, 5));
43+
expect(div(d.vec4f(0.09, 0.09, 0.09, 0.09), 0.3)).toEqual(d.vec4f(0.3));
44+
});
45+
46+
it('computes quotient of a d.vec4u and a number', () => {
47+
expect(div(d.vec4u(2, 2, 2, 2), 2)).toEqual(d.vec4u(1));
48+
expect(div(d.vec4u(16, 16, 16, 16), 8)).toEqual(d.vec4u(2));
49+
});
50+
51+
it('computes quotient of a d.vec4i and a number', () => {
52+
expect(div(d.vec4i(1, 2, 3, 4), -1)).toEqual(d.vec4i(-1, -2, -3, -4));
53+
expect(div(d.vec4i(0, 0, 0, 0), 1)).toEqual(d.vec4i());
54+
expect(div(d.vec4i(16, 16, 16, 16), 8)).toEqual(d.vec4i(2));
55+
});
56+
57+
it('computes quotient of a d.vec4f and a d.vec4f', () => {
58+
expect(div(d.vec4f(1.5, 2, 3, 4), d.vec4f(2, 2, 2, 2))).toEqual(
59+
d.vec4f(0.75, 1, 1.5, 2),
60+
);
61+
expect(div(d.vec4f(0.09, 0.09, 0.09, 0.09), d.vec4f(0.3))).toEqual(
62+
d.vec4f(0.3),
63+
);
64+
});
65+
66+
it('computes quotient of a d.vec4u and a d.vec4u', () => {
67+
expect(div(d.vec4u(2, 2, 2, 2), d.vec4u(2))).toEqual(d.vec4u(1));
68+
expect(div(d.vec4u(16, 16, 16, 16), d.vec4u(8))).toEqual(d.vec4u(2));
69+
});
70+
71+
it('computes quotient of a d.vec4i and a d.vec4i', () => {
72+
expect(div(d.vec4i(1, 2, 3, 4), d.vec4i(-1))).toEqual(
73+
d.vec4i(-1, -2, -3, -4),
74+
);
75+
expect(div(d.vec4i(0, 0, 0, 0), d.vec4i(1))).toEqual(d.vec4i());
76+
expect(div(d.vec4i(16, 16, 16, 16), d.vec4i(8))).toEqual(d.vec4i(2));
77+
});
78+
});

0 commit comments

Comments
 (0)