|
22 | 22 |
|
23 | 23 | </div>
|
24 | 24 |
|
| 25 | +<br> |
| 26 | +<br> |
| 27 | + |
| 28 | +**Table of contents:** |
| 29 | +- [⚙️ TypeGPU as a foundation](#⚙️-typegpu-as-a-foundation) |
| 30 | +- [🧩 TypeGPU as a piece of the puzzle](#🧩-typegpu-as-a-piece-of-the-puzzle) |
| 31 | +- [📚 TypeGPU for libraries](#📚-typegpu-for-libraries) |
| 32 | +- [Documentation](#documentation) |
| 33 | +- [What's next?](#whats-next) |
| 34 | +- [Projects using TypeGPU](#projects-using-typegpu) |
| 35 | +- [Repository structure](#repository-structure) |
| 36 | + |
| 37 | +## ⚙️ TypeGPU as a foundation |
| 38 | + |
| 39 | +We provide an abstraction that solves the most common WebGPU hurdles, yet does not restrict you in capability. |
| 40 | +You can granularly eject into vanilla WebGPU at any point. This means that, when building your app with TypeGPU, |
| 41 | +lock-in is not a concern! |
| 42 | + |
| 43 | +The low-level nature of TypeGPU and it's mirroring of WGSL (WebGPU Shading Language) syntax in TypeScript means |
| 44 | +that learning TypeGPU helps to learn WebGPU itself, with fewer frustrations. |
| 45 | + |
| 46 | +[The Getting Started and Fundamentals guides are a great starting point for new projects!](https://docs.swmansion.com/TypeGPU/getting-started/) |
| 47 | + |
| 48 | +## 🧩 TypeGPU as a piece of the puzzle |
| 49 | + |
| 50 | +Our type-safe APIs can be used together, or in isolation. This makes partial application into existing apps just a few lines of code away, no matter the complexity of your app! |
| 51 | + |
| 52 | +[We wrote a comprehensive resource on ways TypeGPU can improve your existing codebase.](https://docs.swmansion.com/TypeGPU/integration/webgpu-interoperability/) |
| 53 | + |
| 54 | +Pick and choose which parts of TypeGPU you'd like to incorporate into your existing app! |
| 55 | + |
| 56 | +## 📚 TypeGPU for libraries |
| 57 | + |
| 58 | +When creating a type-safe WebGPU library, one can expect to encounter at least one of the following problems: |
| 59 | +- Serializing/deserializing data. |
| 60 | +- Dynamically generating parts of the WGSL shader. |
| 61 | +- Complex type inference. |
| 62 | + |
| 63 | +If implemented from scratch, interoperability with other libraries (ones that have a different focus, solve different problems) can be near impossible without going down to *untyped WebGPU land*, or copying data back to JS. Moreover, to keep up with demand from users, they can be tempted to go out of scope of their initial use-case, even though another library already solves that problem. |
| 64 | + |
| 65 | +> TypeGPU can be used as an interoperability layer between use-case specific libraries! |
| 66 | +
|
| 67 | +Let's imagine `@xyz/gen` is a library for procedural generation using WebGPU compute shaders, and `@abc/plot` is a library for plots and visualization using WebGPU. |
| 68 | + |
| 69 | +```ts |
| 70 | +import tgpu from 'typegpu'; |
| 71 | +import gen from '@xyz/gen'; |
| 72 | +import plot from '@abc/plot'; |
| 73 | + |
| 74 | +// common root for allocating resources |
| 75 | +const root = await tgpu.init(); |
| 76 | + |
| 77 | +const terrainBuffer = await gen.generateHeightMap(root, { ... }); |
| 78 | +// ^? TgpuBuffer<WgslArray<WgslArray<F32>>> & StorageFlag |
| 79 | + |
| 80 | +// ERROR: Argument of type 'TgpuBuffer<WgslArray<WgslArray<F32>>>' is |
| 81 | +// not assignable to parameter of type 'TgpuBuffer<WgslArray<F32>>>' |
| 82 | +plot.array1d(root, terrainBuffer); |
| 83 | + |
| 84 | +// SUCCESS! |
| 85 | +plot.array2d(root, terrainBuffer); |
| 86 | +``` |
| 87 | + |
| 88 | +We can pass typed values around without the need to copy anything back to CPU-accessible memory! Let's see an example of how we can construct a type-safe API: |
| 89 | + |
| 90 | +```ts |
| 91 | +import type { TgpuBuffer, TgpuRoot, StorageFlag } from 'typegpu'; |
| 92 | +import * as d from 'typegpu/data'; |
| 93 | + |
| 94 | +// We can define schemas, or functions that return schemas... |
| 95 | +const HeightMap = (width: number, height: number) => |
| 96 | + d.arrayOf(d.arrayOf(d.f32, height), width); |
| 97 | + |
| 98 | +// ...then infer types from them |
| 99 | +type HeightMap = ReturnType<typeof HeightMap>; |
| 100 | + |
| 101 | +export async function generateHeightMap( |
| 102 | + root: TgpuRoot, |
| 103 | + opts: { width: number, height: number }, |
| 104 | +): Promise<TgpuBuffer<HeightMap> & StorageFlag> { |
| 105 | + |
| 106 | + const buffer = root |
| 107 | + .createBuffer(HeightMap(opts.width, opts.height)) |
| 108 | + .$usage('storage'); |
| 109 | + |
| 110 | + const rawBuffer = root.unwrap(buffer); // => GPUBuffer |
| 111 | + |
| 112 | + // Here we can do anything we would usually do with a |
| 113 | + // WebGPU buffer, like populating it in a compute shader. |
| 114 | + // `rawBuffer` is the WebGPU resource that is backing the |
| 115 | + // typed `buffer` object, meaning any changes to it will |
| 116 | + // be visible in both. |
| 117 | + |
| 118 | + return buffer; |
| 119 | +} |
| 120 | +``` |
| 121 | + |
| 122 | +[Planning to create a WebGPU library? Reach out to us!](https://discord.gg/8jpfgDqPcM) We'd love to work with you to enrich the ecosystem with type-safe WebGPU utilities! |
| 123 | + |
25 | 124 | ## Documentation
|
26 | 125 |
|
27 | 126 | We created a set of guides and tutorials to get you up and running fast. Check out our [Official Docs](https://docs.swmansion.com/TypeGPU/getting-started)!
|
|
0 commit comments