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
Before feeding vertex data to the render pipeline, we need to get familiar with the notion of **buffer**. A buffer is "just" a **chunk of memory** allocated in the **VRAM** (the GPU's memory). Think of it as some kind of `new` or `malloc` for the GPU.
23
+
Before feeding vertex data to the render pipeline, we need to get familiar with the notion of a **buffer**. A buffer is "just" a **chunk of memory** allocated in the **VRAM** (the GPU's memory). Think of it as some kind of `new` or `malloc` for the GPU.
24
24
25
-
In this chapter, we see how to **create** (i.e., allocate), **write** from CPU, **copy** from GPU to GPU and **read back** to CPU.
25
+
In this chapter, we will see how to **create** (i.e., allocate), **write** from CPU, **copy** from GPU to GPU and **read back** to CPU.
26
26
27
27
```{note}
28
-
Note that textures are a special kind of memory (because of the way we usually sample them) that they live in a different kind of object.
28
+
Note that textures are a special kind of memory (because of the way we usually sample them) so they live in a different kind of object.
29
29
```
30
30
31
31
Since this is just an experiment, I suggest we temporarily write the whole code of this chapter at the end of the `Initialize()` function. The overall outline of our code is as follows:
32
32
33
33
```{lit} C++, Playing with buffers (insert in {{Initialize}} after "InitializePipeline()", also for tangle root "Vanilla")
34
-
// Experimentation for the "Playing with buffer" chapter
34
+
// Experimentation for the "Playing with buffers" chapter
35
35
{{Create a first buffer}}
36
36
{{Create a second buffer}}
37
37
@@ -177,7 +177,7 @@ And don't forget that commands sent through the **command encoder** are only sub
177
177
Copying a buffer
178
178
----------------
179
179
180
-
We can now submit a **buffer-buffer copy** operation to the command queue. This is not directly available from the queue object but rather requires to **create a command encoder**. We may use the same one as the render pass for our test and simply add the following:
180
+
We can now submit a **buffer-buffer copy** operation to the command queue. This is not directly available from the queue object but rather requires us to **create a command encoder**. Once we have an encoder we may simply add the following:
181
181
182
182
````{tab} With webgpu.hpp
183
183
```{lit} C++, Copy buffer to buffer
@@ -228,7 +228,7 @@ Reading from a buffer
228
228
229
229
The **command queue**, that we used to send data (`writeBuffer`) and instructions (`copyBufferToBuffer`), **only goes in one way**: from CPU host to GPU device. It is thus a "fire and forget" queue: functions do not return a value since they **run on a different timeline**.
230
230
231
-
So, how do we read data back then? We use an **asynchronous operation**, like we did when using `wgpuQueueOnSubmittedWorkDone` in the [Command Queue](../../getting-started/the-command-queue.md) chapter. Instead of directly get a value back, we set up a **callback** that gets invoked whenever the requested data is ready. We then **poll the device** to check for incoming events.
231
+
So, how do we read data back then? We use an **asynchronous operation**, like we did when using `wgpuQueueOnSubmittedWorkDone` in the [Command Queue](../../getting-started/the-command-queue.md) chapter. Instead of directly getting a value back, we set up a **callback** that gets invoked whenever the requested data is ready. We then **poll the device** to check for incoming events.
232
232
233
233
**To read data from a buffer**, we use `buffer.mapAsync` (or `wgpuBufferMapAsync`). This operation **maps** the GPU buffer into CPU memory, and then whenever it is ready it executes the callback function it was provided. Once we are done, we can **unmap** the buffer.
234
234
@@ -353,7 +353,7 @@ while (!ready) {
353
353
}
354
354
```
355
355
356
-
You could now see `Buffer 2 mapped with status 1` (1 being the value of `BufferMapAsyncStatus::Success`) when running your program. **However**, we never change the `ready` variable to `true`! So the program then **hangs forever**... not great. That is why the next section shows how to pass some context to the callback.
356
+
You could now see `Buffer 2 mapped with status 1` (1 being the value of `BufferMapAsyncStatus::Success` when using Dawn, it is 0 for WGPU) when running your program. **However**, we never change the `ready` variable to `true`! So the program then **hangs forever**... not great. That is why the next section shows how to pass some context to the callback.
357
357
358
358
### Mapping context
359
359
@@ -363,7 +363,7 @@ So, we need the callback to **access and mutate** the `ready` variable. But how
363
363
When defining `onBuffer2Mapped` as a regular function, it is clear that `ready` is not accessible. When using a lambda expression like we did above, one could be tempted to add `ready` in the **capture list** (the brackets before function arguments). But this **does not work** because a capturing lambda has a **different type**, that cannot be used as a regular callback. We see below that the C++ wrapper fixes this limitation.
364
364
```
365
365
366
-
The **user pointer** is an argument that is provided to `wgpuBufferMapAsync`, when setting up the callback, and that is then fed **as is** to the callback `onBuffer2Mapped` when the map operation is ready. The buffer only forwards this pointer but never uses it: **only you** (the user of the API) interprets it.
366
+
The **user pointer** is an argument that is provided to `wgpuBufferMapAsync`, when setting up the callback, and that is then fed **as is** to the callback `onBuffer2Mapped` when the map operation is ready. The buffer only forwards this pointer but never uses it: **only you** (the user of the API) interpret it.
0 commit comments