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
Copy file name to clipboardExpand all lines: explainer/index.bs
+142-4Lines changed: 142 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -26,10 +26,152 @@ See [Introduction](https://gpuweb.github.io/gpuweb/#introduction).
26
26
27
27
See [Malicious use considerations](https://gpuweb.github.io/gpuweb/#malicious-use).
28
28
29
+
# Additional Background # {#background}
30
+
31
+
## Sandboxed GPU Processes in Web Browsers ## {#gpu-process}
32
+
33
+
A major design constraint for WebGPU is that it must be implementable and efficient in browsers that use a GPU-process architecture.
34
+
GPU drivers need access to additional kernel syscalls than what's otherwise used for Web content, and many GPU drivers are prone to hangs or crashes.
35
+
To improve stability and sandboxing, browsers use a special process that contains the GPU driver and talks with the rest of the browser through asynchronous IPC.
36
+
GPU processes are (or will be) used in Chromium, Gecko, and WebKit.
37
+
38
+
GPU processes are less sandboxed than content processes, and they are typically shared between multiple origins.
39
+
Therefore, they must validate all messages, for example to prevent a compromised content process from being able to look at the GPU memory used by another content process.
40
+
Most of WebGPU's validation rules are necessary to ensure it is secure to use, so all the validation needs to happen in the GPU process.
41
+
42
+
Likewise, all GPU driver objects only live in the GPU process, including large allocations (like buffers and textures) and complex objects (like pipelines).
43
+
In the content process, WebGPU types (`GPUBuffer`, `GPUTexture`, `GPURenderPipeline`, ...) are mostly just "handles" that identify objects that live in the GPU process.
44
+
This means that the CPU and GPU memory used by WebGPU object isn't necessarily known in the content process.
45
+
A `GPUBuffer` object can use maybe 150 bytes of CPU memory in the content process but hold a 1GB allocation of GPU memory.
46
+
47
+
See also the description of [the content and device timelines in the specification](https://gpuweb.github.io/gpuweb/#programming-model-timelines).
48
+
29
49
# JavaScript API # {#api}
30
50
31
51
## Bitflags ## {#bitflags}
32
52
53
+
## Object Validity and Destroyed-ness ## {#invalid-and-destroyed}
WebGPU is a very chatty API, with some applications making tens of thousands of calls per frame to render complex scenes.
61
+
We have seen that the GPU processes needs to validate the commands to satisfy their security property.
62
+
To avoid the overhead of validating commands twice in both the GPU and content process, WebGPU is designed so Javascript calls can be forwarded directly to the GPU process and validated there.
63
+
See the error section for more details on what's validated where and how errors are reported.
64
+
65
+
At the same time, during a single frame WebGPU objects can be created that depend on one another.
66
+
For example a `GPUCommandBuffer` can be recorded with commands that use temporary `GPUBuffer`s created in the same frame.
67
+
In this example, because of the performance constraint of WebGPU, it is not possible to send the message to create the `GPUBuffer` to the GPU process and synchronously wait for its processing before continuing Javascript execution.
68
+
69
+
Instead, in WebGPU all objects (like `GPUBuffer`) are created immediately on the content timeline and returned to JavaScript.
70
+
The validation is almost all done asynchronously on the "device timeline".
71
+
In the good case, when no errors occur (validation or out-of-memory), everything looks to JS as if it is synchronous.
72
+
However, when an error occurs in a call, it becomes a no-op (aside from error reporting).
73
+
If the call returns an object (like `createBuffer`), the object is tagged as "invalid" on the GPU process side.
74
+
75
+
All WebGPU calls validate that all their arguments are valid objects.
76
+
As a result, if a call takes one WebGPU object and returns a new one, the new object is also invalid (hence the term "contagious").
77
+
78
+
<figure>
79
+
<figcaption>
80
+
Timeline diagram of messages passing between processes, demonstrating how errors are propagated without synchronization.
One way to interpret WebGPU's semantics is that every WebGPU object is actually a `Promise` internally and that all WebGPU methods are `async` and `await` before using each of the WebGPU objects it gets as argument.
133
+
However the execution of the async code is outsourced to the GPU process (where it is actually done synchronously).
134
+
135
+
Another way, closer to actual implementation details, is to imagine that each `GPUFoo` JS object maps to a `gpu::InternalFoo` C++/Rust object on the GPU process that contains a `bool isValid`.
136
+
Then during the validation of each command on the GPU process, the `isValid` are all checked and a new, invalid object is returned if validation fails.
137
+
On the content process side, the `GPUFoo` implementation doesn't know if the object is valid or not.
138
+
139
+
### Early Destruction of WebGPU Objects ### {#early-destroy}
140
+
141
+
Most of the memory usage of WebGPU objects is in the GPU process: it can be GPU memory held by objects like `GPUBuffer` and `GPUTexture`, serialized commands held in CPU memory by `GPURenderBundles`, or complex object graphs for the WGSL AST in `GPUShaderModule`.
142
+
The JavaScript garbage collector (GC) is in the renderer process and doesn't know about the memory usage in the GPU process.
143
+
Browsers have many heuristics to trigger GCs but a common one is that it should be triggered on memory pressure scenarios.
144
+
However a single WebGPU object can hold on to MBs or GBs of memory without the GC knowing and never trigger the memory pressure event.
145
+
146
+
It is important for WebGPU applications to be able to directly free the memory used by some WebGPU objects without waiting for the GC.
147
+
For example applications might create temporary textures and buffers each frame and without the explicit `.destroy()` call they would quickly run out of GPU memory.
148
+
That's why WebGPU has a `.destroy()` method on those object types which can hold on to arbitrary amount of memory.
149
+
It signals that the application doesn't need the content of the object anymore and that it can be freed as soon as possible.
150
+
Of course, it becomes a validation to use the object after the call to `.destroy()`.
151
+
152
+
<div class=example>
153
+
<pre highlight="js">
154
+
const dstBuffer = device.createBuffer({
155
+
size: 4
156
+
usage: GPUBufferUsage.COPY_DST
157
+
});
158
+
159
+
// The buffer is not destroyed (and valid), success!
160
+
device.queue.writeBuffer(dstBuffer, 0, myData);
161
+
162
+
buffer.destroy();
163
+
164
+
// The buffer is now destroyed, commands using that would use its
165
+
// content produce validation errors.
166
+
device.queue.writeBuffer(dstBuffer, 0, myData);
167
+
</pre>
168
+
</div>
169
+
170
+
Note that, while this looks somewhat similar to the behavior of an invalid buffer, it is distinct.
171
+
Unlike invalidity, destroyed-ness can change after creation, is not contagious, and is validated only when work is actually submitted (e.g. `queue.writeBuffer()` or `queue.submit()`), not when creating dependent objects (like command encoders, see above).
172
+
173
+
## Errors ## {#errors}
174
+
33
175
## Adapter Selection and Device Init ## {#initialization}
34
176
35
177
## Adapter and Device Loss ## {#device-loss}
@@ -42,10 +184,6 @@ See [Malicious use considerations](https://gpuweb.github.io/gpuweb/#malicious-us
42
184
43
185
## Pipelines ## {#pipelines}
44
186
45
-
## Object Validity and Destroyed-ness ## {#invalid-and-destroyed}
46
-
47
-
## Errors ## {#errors}
48
-
49
187
## Image, Video, and Canvas input ## {#image-input}
0 commit comments