Skip to content

Commit 37914d5

Browse files
committed
Merge branch 'main' into feat/ref-value
2 parents 5805cac + b754154 commit 37914d5

File tree

9 files changed

+327
-111
lines changed

9 files changed

+327
-111
lines changed

apps/typegpu-docs/src/content/docs/fundamentals/utils.mdx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,16 @@ The default workgroup sizes are:
118118
The callback is not called if the global invocation id of a thread would exceed the size in any dimension.
119119
:::
120120

121+
:::tip
122+
`TgpuGuardedComputePipeline` provides getters for the underlying pipeline and the size buffer.
123+
Those might be useful for `tgpu.resolve`, since you cannot resolve a guarded pipeline directly.
124+
125+
```ts
126+
const innerPipeline = doubleUpPipeline.with(bindGroup1).pipeline;
127+
tgpu.resolve({ externals: { innerPipeline } });
128+
```
129+
:::
130+
121131
## *console.log*
122132

123133
Yes, you read that correctly, TypeGPU implements logging to the console on the GPU!

packages/tgpu-gen/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"wgsl_reflect": "git://github.com/mhawryluk/wgsl_reflect.git#85994fdc8d8a3abbb4f79baf3891e54eed0c1c63"
1919
},
2020
"peerDependencies": {
21-
"typegpu": "workspace:^0.8.1"
21+
"typegpu": "workspace:^0.8.0"
2222
},
2323
"files": ["README.md", "LICENSE", "package.json", "**/*.mjs"],
2424
"devDependencies": {

packages/typegpu/package.json

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "typegpu",
33
"private": true,
4-
"version": "0.8.1",
4+
"version": "0.8.2",
55
"description": "A thin layer between JS and WebGPU/WGSL that improves development experience and allows for faster iteration.",
66
"license": "MIT",
77
"type": "module",
@@ -21,27 +21,19 @@
2121
"./package.json": "./dist/package.json",
2222
".": {
2323
"types": "./dist/index.d.ts",
24-
"module": "./dist/index.js",
25-
"import": "./dist/index.js",
26-
"default": "./dist/index.cjs"
24+
"default": "./dist/index.js"
2725
},
2826
"./data": {
2927
"types": "./dist/data/index.d.ts",
30-
"module": "./dist/data/index.js",
31-
"import": "./dist/data/index.js",
32-
"default": "./dist/data/index.cjs"
28+
"default": "./dist/data/index.js"
3329
},
3430
"./std": {
3531
"types": "./dist/std/index.d.ts",
36-
"module": "./dist/std/index.js",
37-
"import": "./dist/std/index.js",
38-
"default": "./dist/std/index.cjs"
32+
"default": "./dist/std/index.js"
3933
},
4034
"./common": {
4135
"types": "./dist/common/index.d.ts",
42-
"module": "./dist/common/index.js",
43-
"import": "./dist/common/index.js",
44-
"default": "./dist/common/index.cjs"
36+
"default": "./dist/common/index.js"
4537
}
4638
}
4739
},
@@ -73,7 +65,7 @@
7365
},
7466
"homepage": "https://typegpu.com",
7567
"devDependencies": {
76-
"@ark/attest": "^0.49.0",
68+
"@ark/attest": "^0.53.0",
7769
"@typegpu/tgpu-dev-cli": "workspace:*",
7870
"@webgpu/types": "catalog:types",
7971
"arktype": "catalog:",

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,14 @@ export class TgpuGuardedComputePipelineImpl<TArgs extends number[]>
186186
workgroupCount.z,
187187
);
188188
}
189+
190+
get pipeline() {
191+
return this.#pipeline;
192+
}
193+
194+
get sizeUniform() {
195+
return this.#sizeUniform;
196+
}
189197
}
190198

191199
class WithBindingImpl implements WithBinding {

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
AnyWgslData,
1414
U16,
1515
U32,
16+
Vec3u,
1617
Void,
1718
WgslArray,
1819
} from '../../data/wgslTypes.ts';
@@ -94,6 +95,17 @@ export interface TgpuGuardedComputePipeline<TArgs extends number[] = number[]> {
9495
* "guarded" by a bounds check.
9596
*/
9697
dispatchThreads(...args: TArgs): void;
98+
99+
/**
100+
* The underlying pipeline used during `dispatchThreads`.
101+
*/
102+
pipeline: TgpuComputePipeline;
103+
104+
/**
105+
* The buffer used to automatically pass the thread count to the underlying pipeline during `dispatchThreads`.
106+
* For pipelines with a dimension count lower than 3, the remaining coordinates are expected to be 1.
107+
*/
108+
sizeUniform: TgpuUniform<Vec3u>;
97109
}
98110

99111
export interface WithCompute {

packages/typegpu/src/core/texture/textureUtils.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,36 @@ import type { ExternalImageSource } from './texture.ts';
77
export function getImageSourceDimensions(
88
source: ExternalImageSource,
99
): { width: number; height: number } {
10-
if ('displayWidth' in source && 'displayHeight' in source) {
11-
return { width: source.displayWidth, height: source.displayHeight };
10+
// We used to do it this way but it fails on React Native (ImageBitmap is probably a proxy there)
11+
// if ('displayWidth' in source && 'displayHeight' in source) {
12+
// return { width: source.displayWidth, height: source.displayHeight };
13+
// }
14+
15+
const { videoWidth, videoHeight } = source as HTMLVideoElement;
16+
if (videoWidth && videoHeight) {
17+
return { width: videoWidth, height: videoHeight };
1218
}
13-
return { width: source.width as number, height: source.height as number };
19+
20+
const { naturalWidth, naturalHeight } = source as HTMLImageElement;
21+
if (naturalWidth && naturalHeight) {
22+
return { width: naturalWidth, height: naturalHeight };
23+
}
24+
25+
const { codedWidth, codedHeight } = source as VideoFrame;
26+
if (codedWidth && codedHeight) {
27+
return { width: codedWidth, height: codedHeight };
28+
}
29+
30+
const { width, height } = source as ImageBitmap || HTMLCanvasElement ||
31+
OffscreenCanvas || HTMLImageElement || ImageData;
32+
33+
if (!width || !height) {
34+
throw new Error(
35+
'Cannot determine dimensions of the provided image source.',
36+
);
37+
}
38+
39+
return { width, height };
1440
}
1541

1642
type CachedResources = {
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import { describe, expect } from 'vitest';
2+
import * as d from '../src/data/index.ts';
3+
import tgpu from '../src/index.ts';
4+
import { it } from './utils/extendedIt.ts';
5+
6+
describe('resolve', () => {
7+
const Boid = d.struct({
8+
position: d.vec2f,
9+
color: d.vec4f,
10+
});
11+
12+
const computeFn = tgpu['~unstable'].computeFn({
13+
workgroupSize: [1, 1, 1],
14+
in: { gid: d.builtin.globalInvocationId },
15+
})(() => {
16+
const myBoid = Boid({
17+
position: d.vec2f(0, 0),
18+
color: d.vec4f(1, 0, 0, 1),
19+
});
20+
});
21+
22+
const vertexFn = tgpu['~unstable'].vertexFn({
23+
out: { pos: d.builtin.position, color: d.vec4f },
24+
})(() => {
25+
const myBoid = Boid();
26+
return { pos: d.vec4f(myBoid.position, 0, 1), color: myBoid.color };
27+
});
28+
29+
const fragmentFn = tgpu['~unstable'].fragmentFn({
30+
in: { color: d.vec4f },
31+
out: d.vec4f,
32+
})((input) => {
33+
return input.color;
34+
});
35+
36+
it('can resolve a render pipeline', ({ root }) => {
37+
const pipeline = root
38+
.withVertex(vertexFn, {})
39+
.withFragment(fragmentFn, { format: 'rgba8unorm' })
40+
.createPipeline();
41+
42+
expect(tgpu.resolve({ externals: { pipeline } })).toMatchInlineSnapshot(`
43+
"struct Boid_1 {
44+
position: vec2f,
45+
color: vec4f,
46+
}
47+
48+
struct vertexFn_Output_2 {
49+
@builtin(position) pos: vec4f,
50+
@location(0) color: vec4f,
51+
}
52+
53+
@vertex fn vertexFn_0() -> vertexFn_Output_2 {
54+
var myBoid = Boid_1();
55+
return vertexFn_Output_2(vec4f(myBoid.position, 0f, 1f), myBoid.color);
56+
}
57+
58+
struct fragmentFn_Input_4 {
59+
@location(0) color: vec4f,
60+
}
61+
62+
@fragment fn fragmentFn_3(input: fragmentFn_Input_4) -> @location(0) vec4f {
63+
return input.color;
64+
}"
65+
`);
66+
});
67+
68+
it('can resolve a compute pipeline', ({ root }) => {
69+
const pipeline = root
70+
.withCompute(computeFn)
71+
.createPipeline();
72+
73+
expect(tgpu.resolve({ externals: { pipeline } })).toMatchInlineSnapshot(`
74+
"struct Boid_1 {
75+
position: vec2f,
76+
color: vec4f,
77+
}
78+
79+
struct computeFn_Input_2 {
80+
@builtin(global_invocation_id) gid: vec3u,
81+
}
82+
83+
@compute @workgroup_size(1, 1, 1) fn computeFn_0(_arg_0: computeFn_Input_2) {
84+
var myBoid = Boid_1(vec2f(), vec4f(1, 0, 0, 1));
85+
}"
86+
`);
87+
});
88+
89+
it('can resolve a guarded compute pipeline', ({ root }) => {
90+
const pipelineGuard = root.createGuardedComputePipeline((x, y, z) => {
91+
'use gpu';
92+
const myBoid = Boid({
93+
position: d.vec2f(0, 0),
94+
color: d.vec4f(x, y, z, 1),
95+
});
96+
});
97+
98+
expect(tgpu.resolve({ externals: { pipeline: pipelineGuard.pipeline } }))
99+
.toMatchInlineSnapshot(`
100+
"@group(0) @binding(0) var<uniform> sizeUniform_1: vec3u;
101+
102+
struct Boid_3 {
103+
position: vec2f,
104+
color: vec4f,
105+
}
106+
107+
fn wrappedCallback_2(x: u32, y: u32, z: u32) {
108+
var myBoid = Boid_3(vec2f(), vec4f(f32(x), f32(y), f32(z), 1f));
109+
}
110+
111+
struct mainCompute_Input_4 {
112+
@builtin(global_invocation_id) id: vec3u,
113+
}
114+
115+
@compute @workgroup_size(8, 8, 4) fn mainCompute_0(in: mainCompute_Input_4) {
116+
if (any(in.id >= sizeUniform_1)) {
117+
return;
118+
}
119+
wrappedCallback_2(in.id.x, in.id.y, in.id.z);
120+
}"
121+
`);
122+
});
123+
124+
it('throws when resolving multiple pipelines', ({ root }) => {
125+
const renderPipeline = root
126+
.withVertex(vertexFn, {})
127+
.withFragment(fragmentFn, { format: 'rgba8unorm' })
128+
.createPipeline();
129+
130+
const computePipeline = root
131+
.withCompute(computeFn)
132+
.createPipeline();
133+
134+
expect(() =>
135+
tgpu.resolve({ externals: { renderPipeline, computePipeline } })
136+
).toThrowErrorMatchingInlineSnapshot(
137+
`[Error: Found 2 pipelines but can only resolve one at a time.]`,
138+
);
139+
});
140+
});

packages/typegpu/tsup.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const entry = [
1414
export default defineConfig({
1515
entry,
1616
outDir: 'dist',
17-
format: ['cjs', 'esm'],
17+
format: ['esm'],
1818
target: 'es2024',
1919
splitting: true,
2020
sourcemap: true,

0 commit comments

Comments
 (0)