Skip to content

Commit

Permalink
Add a note about error callback in refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
eliemichel committed Aug 30, 2023
1 parent 0273f84 commit 0f7f139
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
42 changes: 42 additions & 0 deletions basic-3d-rendering/some-interaction/refactoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ However, it is also the occasion to **organize a bit our code base**, which we h
An application structure
------------------------

### Main class

I am going to **avoid over-engineering** things since each use case is different, so you will customize the details for your needs. Nevertheless it always starts with a class (or struct) that holds all the global state of the application.

We implement this in two new files `Application.h` and `Application.cpp`, where the behavior of the application is distributed across **event handlers**. To make this logic clear, handles start with "on", like `onFrame`.
Expand Down Expand Up @@ -153,6 +155,9 @@ public:
};
```
Other notes
-----------
### Library implementation
As we start including our libraries in multiple files, we must remember that the `#define FOO_IMPLEMENTATION` that some of them require **must appear in only one** C++ file, and the include must be placed before any other one that may recursively include it.
Expand All @@ -171,6 +176,43 @@ To avoid some unexpected complication, I recommend to create a file `implementat
#include "stb_image.h"
```

### Callback handles

```{important}
This section is **specific to the WebGPU C++ wrapper** I provide. When using the raw C API, the callback cannot be a lambda function and must rather be defined in the global scope.
```

In order to prevent the uncaptured error callback from behing freed too early, we need to store the handle returned by `device.setUncapturedErrorCallback`. So far this was just done by defining a variable `h` that lives for the whole main function:

```C++
// Until now, we just stored the handle in a variable local to the main function
auto h = device.setUncapturedErrorCallback([](ErrorType type, char const* message) {
std::cout << "Device error: type " << type;
if (message) std::cout << " (message: " << message << ")";
std::cout << std::endl;
});
```

Since we no longer define this in the main function directly but rather in the `Application`'s init, we must store the `h` handle as a class member:

```C++
// In Application.h
class Application {
private:
// Keep the error callback alive
std::unique_ptr<wgpu::ErrorCallback> errorCallbackHandle;
}

// In Application.cpp, in onInit()
errorCallbackHandle = device.setUncapturedErrorCallback([](ErrorType type, char const* message) {
std::cout << "Device error: type " << type;
if (message) std::cout << " (message: " << message << ")";
std::cout << std::endl;
});
```
This way, the callback is released only when the Application object is destroyed.
Conclusion
----------
Expand Down
7 changes: 6 additions & 1 deletion basic-3d-rendering/some-interaction/simple-gui.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,12 @@ ImGui::End();
### Capabilities
Using ImGUI requires `maxBindGroups` to be at least 1.
Using ImGUI requires `maxBindGroups` to be at least 2.
```C++
requiredLimits.limits.maxBindGroups = 2;
// ^ This was a 1
```

Misc
----
Expand Down

0 comments on commit 0f7f139

Please sign in to comment.