You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For code with small, fixed iteration counts, you can use `tgpu.unroll` to unroll loops at compile time. This eliminates branch prediction overhead and can significantly improve performance.
299
+
For code with small, fixed iteration counts, you can use `tgpu.unroll` to unroll loops at compile time.
300
300
301
301
### Usage
302
302
@@ -387,5 +387,215 @@ fn fbm(pos: vec3f) -> f32 {
387
387
388
388
:::note
389
389
- There are no constraints on how large a loop can be for unrolling. We will always try to unroll it, and if we can't, you'll receive an error.
390
-
- You cannot use `continue` or `break` inside loop that you intend to unroll later.
390
+
- You cannot use `continue` or `break` inside a loop that you intend to unroll later.
391
391
:::
392
+
393
+
:::tip
394
+
You can unroll loops conditionally, for example:
395
+
```ts
396
+
// A value determined based on the user's environment
397
+
const shouldUnroll =true;
398
+
399
+
const f = () => {
400
+
'use gpu';
401
+
const arr = [1, 2, 3];
402
+
let r =d.i32(0);
403
+
for (const foo ofshouldUnroll?tgpu.unroll(arr) :arr) {
404
+
r+=foo;
405
+
}
406
+
};
407
+
```
408
+
:::
409
+
410
+
### Types of iterables (more technical section)
411
+
412
+
**Array expression of primitive elements:**
413
+
```ts
414
+
for (const foo oftgpu.unroll([1, 2, 3])) {
415
+
result+=foo;
416
+
}
417
+
```
418
+
419
+
Generates:
420
+
```wgsl
421
+
// unrolled iteration #0
422
+
{
423
+
result += 1u;
424
+
}
425
+
// unrolled iteration #1
426
+
{
427
+
result += 2u;
428
+
}
429
+
// unrolled iteration #2
430
+
{
431
+
result += 3u;
432
+
}
433
+
```
434
+
:::note
435
+
`std.range` falls into the primitive array expression category.
In the example above, if `Boid` creation were inlined, we would throw an error. This means that elements of a complex type must be stored in variables before unrolling.
468
+
:::
469
+
470
+
**Vector**
471
+
```ts
472
+
const v =d.vec3f(1, 2, 3);
473
+
let res =d.f32(0);
474
+
for (const foo oftgpu.unroll(d.vec3f(v))) {
475
+
res+=foo;
476
+
}
477
+
```
478
+
479
+
Generates:
480
+
```wgsl
481
+
// unrolled iteration #0
482
+
{
483
+
res = res + v[0u];
484
+
}
485
+
// unrolled iteration #1
486
+
{
487
+
res = res + v[1u];
488
+
}
489
+
// unrolled iteration #2
490
+
{
491
+
res = res + v[2u];
492
+
}
493
+
```
494
+
495
+
**Array expression of struct field names**
496
+
```ts
497
+
const values = { a: 1, b: 2, c: 3 };
498
+
const keys =Object.keys(values) as (keyoftypeofvalues)[];
499
+
500
+
const f = () => {
501
+
'use gpu';
502
+
let result =d.u32(0);
503
+
for (const key oftgpu.unroll(keys)) {
504
+
result+=values[key];
505
+
}
506
+
returnresult;
507
+
};
508
+
```
509
+
510
+
Generates:
511
+
```wgsl
512
+
// ...
513
+
514
+
// unrolled iteration #0
515
+
{
516
+
result += 1u;
517
+
}
518
+
// unrolled iteration #1
519
+
{
520
+
result += 2u;
521
+
}
522
+
// unrolled iteration #2
523
+
{
524
+
result += 3u;
525
+
}
526
+
527
+
// ...
528
+
```
529
+
530
+
:::note
531
+
As you can see, `tgpu.unroll` will handle external arrays as long as they are known at compile-time.
0 commit comments