* @brief Factory function to create a GPU context, which aggregates WebGPU API * handles to interact with the GPU including the instance, adapter, device, and * queue. * * The function takes optional descriptor parameters for the instance * descriptor, adapter request options, and device descriptor, which are passed * through to the WebGPU API calls to create the instance, adapter, and devic
| 772 | * @endcode |
| 773 | */ |
| 774 | inline Context createContext(const WGPUInstanceDescriptor &desc = {}, |
| 775 | const WGPURequestAdapterOptions &adapterOpts = {}, |
| 776 | const WGPUDeviceDescriptor &devDescriptor = {}) { |
| 777 | Context context; |
| 778 | { |
| 779 | #ifdef __EMSCRIPTEN__ |
| 780 | // Emscripten does not support the instance descriptor |
| 781 | // and throws an assertion error if it is not nullptr. |
| 782 | context.instance = wgpuCreateInstance(nullptr); |
| 783 | #else |
| 784 | context.instance = wgpuCreateInstance(&desc); |
| 785 | #endif |
| 786 | check(context.instance, "Initialize WebGPU", __FILE__, __LINE__); |
| 787 | } |
| 788 | |
| 789 | LOG(kDefLog, kInfo, "Requesting adapter"); |
| 790 | { |
| 791 | struct AdapterData { |
| 792 | WGPUAdapter adapter = nullptr; |
| 793 | bool requestEnded = false; |
| 794 | }; |
| 795 | AdapterData adapterData; |
| 796 | auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, |
| 797 | WGPUAdapter adapter, char const *message, |
| 798 | void *pUserData) { |
| 799 | AdapterData &adapterData = *reinterpret_cast<AdapterData *>(pUserData); |
| 800 | #ifdef __EMSCRIPTEN__ |
| 801 | if (status != WGPURequestAdapterStatus_Success) { |
| 802 | LOG(kDefLog, kError, "Could not get WebGPU adapter: %s", message); |
| 803 | LOG(kDefLog, kError, |
| 804 | "\n\nA common reason is that the browser does not have WebGPU " |
| 805 | "enabled, particularly on Linux.\n" |
| 806 | "- Open `chrome://flags/` in the browser and make sure " |
| 807 | "\"WebGPU Support\" is enabled.\n" |
| 808 | "- Chrome is launched with vulkan enabled. From the command line " |
| 809 | "launch chrome as `google-chrome --enable-features=Vulkan`\n"); |
| 810 | } |
| 811 | #endif |
| 812 | check(status == WGPURequestAdapterStatus_Success, |
| 813 | "Request WebGPU adapter", __FILE__, __LINE__); |
| 814 | adapterData.adapter = adapter; |
| 815 | adapterData.requestEnded = true; |
| 816 | }; |
| 817 | |
| 818 | wgpuInstanceRequestAdapter(context.instance, &adapterOpts, |
| 819 | onAdapterRequestEnded, (void *)&adapterData); |
| 820 | |
| 821 | while (!adapterData.requestEnded) { |
| 822 | processEvents(context.instance); |
| 823 | } |
| 824 | assert(adapterData.requestEnded); |
| 825 | context.adapter = adapterData.adapter; |
| 826 | } |
| 827 | |
| 828 | LOG(kDefLog, kInfo, "Requesting device"); |
| 829 | { |
| 830 | struct DeviceData { |
| 831 | WGPUDevice device = nullptr; |