134 {
135 if (gpu_initialized)
136 return;
137
138 wgpu::InstanceDescriptor instanceDesc = {};
139 instance = wgpu::CreateInstance(&instanceDesc);
140
141 if (!instance) {
142 IMG2NUM_LOG_INFO("Fatal: WebGPU instance creation failed.");
143 return;
144 }
145
146
147
148
149 IMG2NUM_LOG_INFO("Requesting Adapter...");
150 adapter_ready = false;
151
152 instance.RequestAdapter(
153 nullptr,
154 wgpu::CallbackMode::AllowProcessEvents,
155 [this](wgpu::RequestAdapterStatus status, wgpu::Adapter a, wgpu::StringView msg) {
156 if (status == wgpu::RequestAdapterStatus::Success) {
157 adapter = std::move(a);
158 IMG2NUM_LOG_INFO("Adapter Acquired");
159 } else {
160 IMG2NUM_LOG_INFO(
161 "Adapter Failed: {}", std::string_view(msg.data ? msg.data : "", msg.length)
162 );
163 }
164 adapter_ready = true;
165 }
166 );
167
168
169 while (!adapter_ready) {
170 instance.ProcessEvents();
171#if defined(__EMSCRIPTEN__)
172 emscripten_sleep(10);
173#endif
174 }
175
176 if (!adapter) {
177 IMG2NUM_LOG_INFO("Fatal: Could not get WebGPU Adapter.");
178 return;
179 }
180
181
182
183
184 IMG2NUM_LOG_INFO("Requesting Device...");
185 device_ready = false;
186
187 wgpu::DeviceDescriptor deviceDesc = {};
188 deviceDesc.SetUncapturedErrorCallback([](const wgpu::Device&, wgpu::ErrorType type,
189 wgpu::StringView msg) {
190
191 std::string err_str = (msg.data && msg.length > 0) ? std::string(msg.data, msg.length)
192 : "Unknown Error (Null message)";
193
194
195 IMG2NUM_LOG_INFO(
196 "\n[WEBGPU FATAL ERROR] Type: {} | Msg: {}\n", static_cast<uint32_t>(type), err_str
197 );
198 });
199 deviceDesc.SetDeviceLostCallback(
200 wgpu::CallbackMode::AllowProcessEvents,
201 [](const wgpu::Device&, wgpu::DeviceLostReason reason, wgpu::StringView msg) {
202 std::string err_msg = (msg.data && msg.length > 0)
203 ? std::string(msg.data, msg.length)
204 : "Unknown device lost reason";
205
206 if (reason == wgpu::DeviceLostReason::CallbackCancelled) {
207 return;
208 }
209 IMG2NUM_LOG_INFO(
210 "[DEVICE LOST] Reason: {} Msg: {}", static_cast<int>(reason), err_msg
211 );
212 }
213 );
214
215
216 wgpu::Limits supportedLimits;
217 wgpu::Limits requiredLimits;
218 if (adapter.GetLimits(&supportedLimits)) {
219
220
221
222 requiredLimits = supportedLimits;
223
224 IMG2NUM_LOG_INFO("maxBufferSize: {}", requiredLimits.maxBufferSize);
225 IMG2NUM_LOG_INFO(
226 "maxStorageBufferBindingSize: {}", requiredLimits.maxStorageBufferBindingSize
227 );
228
229 deviceDesc.requiredLimits = &requiredLimits;
230 }
231
232 adapter.RequestDevice(
233 &deviceDesc,
234 wgpu::CallbackMode::AllowProcessEvents,
235 [this](wgpu::RequestDeviceStatus status, wgpu::Device d, wgpu::StringView msg) {
236 if (status == wgpu::RequestDeviceStatus::Success) {
237 device = std::move(d);
238 IMG2NUM_LOG_INFO("Device Acquired");
239 } else {
240 IMG2NUM_LOG_INFO(
241 "Device Failed: {}", msg.data && msg.length > 0
242 ? std::string(msg.data, msg.length)
243 : "Unknown error"
244 );
245 }
246 device_ready = true;
247 }
248 );
249
250
251 while (!device_ready) {
252 instance.ProcessEvents();
253#if defined(__EMSCRIPTEN__)
254 emscripten_sleep(10);
255#endif
256 }
257
258 if (!device) {
259 IMG2NUM_LOG_INFO("Fatal: Could not get WebGPU Device.");
260 return;
261 }
262
263 if (!validate_device()) {
264 IMG2NUM_LOG_INFO("Fatal: Could not get WebGPU Device.");
265 return;
266 }
267
268 queue = device.GetQueue();
269 gpu_initialized = true;
270 IMG2NUM_LOG_INFO("GPU Fully Initialized.");
271 };