// This file is part of the 64k demo project. // It implements shared WebGPU initialization for GPU tests. // Provides graceful fallback if GPU unavailable. #include "webgpu_test_fixture.h" #include #include WebGPUTestFixture::WebGPUTestFixture() { } WebGPUTestFixture::~WebGPUTestFixture() { shutdown(); } bool WebGPUTestFixture::init() { // Create instance const WGPUInstanceDescriptor instance_desc = {}; instance_ = wgpuCreateInstance(&instance_desc); if (!instance_) { fprintf(stderr, "WebGPU not available (wgpuCreateInstance failed) - skipping GPU " "test\n"); return false; } // Request adapter (API differs between Win32 and native) WGPUAdapter adapter = nullptr; const WGPURequestAdapterOptions adapter_opts = { .compatibleSurface = nullptr, .powerPreference = WGPUPowerPreference_HighPerformance, }; #if defined(DEMO_CROSS_COMPILE_WIN32) // Win32: Old callback API (function pointer + userdata) auto on_adapter = [](WGPURequestAdapterStatus status, WGPUAdapter a, const char* message, void* userdata) { if (status == WGPURequestAdapterStatus_Success) { *(WGPUAdapter*)userdata = a; } else if (message) { fprintf(stderr, "Adapter request failed: %s\n", message); } }; wgpuInstanceRequestAdapter(instance_, &adapter_opts, on_adapter, &adapter); #else // Native: New callback info API auto on_adapter = [](WGPURequestAdapterStatus status, WGPUAdapter a, WGPUStringView message, void* userdata, void* user2) { (void)user2; (void)message; if (status == WGPURequestAdapterStatus_Success) { *(WGPUAdapter*)userdata = a; } }; WGPURequestAdapterCallbackInfo adapter_cb = {}; adapter_cb.mode = WGPUCallbackMode_WaitAnyOnly; adapter_cb.callback = on_adapter; adapter_cb.userdata1 = &adapter; wgpuInstanceRequestAdapter(instance_, &adapter_opts, adapter_cb); #endif // Wait for adapter callback for (int i = 0; i < 100 && !adapter; ++i) { wgpuInstanceProcessEvents(instance_); } if (!adapter) { fprintf(stderr, "No WebGPU adapter available - skipping GPU test\n"); shutdown(); return false; } adapter_ = adapter; // Request device (API differs between Win32 and native) WGPUDevice device = nullptr; const WGPUDeviceDescriptor device_desc = {}; #if defined(DEMO_CROSS_COMPILE_WIN32) // Win32: Old callback API auto on_device = [](WGPURequestDeviceStatus status, WGPUDevice d, const char* message, void* userdata) { if (status == WGPURequestDeviceStatus_Success) { *(WGPUDevice*)userdata = d; } else if (message) { fprintf(stderr, "Device request failed: %s\n", message); } }; wgpuAdapterRequestDevice(adapter_, &device_desc, on_device, &device); #else // Native: New callback info API auto on_device = [](WGPURequestDeviceStatus status, WGPUDevice d, WGPUStringView message, void* userdata, void* user2) { (void)user2; (void)message; if (status == WGPURequestDeviceStatus_Success) { *(WGPUDevice*)userdata = d; } }; WGPURequestDeviceCallbackInfo device_cb = {}; device_cb.mode = WGPUCallbackMode_WaitAnyOnly; device_cb.callback = on_device; device_cb.userdata1 = &device; wgpuAdapterRequestDevice(adapter_, &device_desc, device_cb); #endif // Wait for device callback for (int i = 0; i < 100 && !device; ++i) { wgpuInstanceProcessEvents(instance_); } if (!device) { fprintf(stderr, "Failed to create WebGPU device - skipping GPU test\n"); shutdown(); return false; } device_ = device; queue_ = wgpuDeviceGetQueue(device_); return true; } void WebGPUTestFixture::shutdown() { if (queue_) { wgpuQueueRelease(queue_); queue_ = nullptr; } if (device_) { wgpuDeviceRelease(device_); device_ = nullptr; } if (adapter_) { wgpuAdapterRelease(adapter_); adapter_ = nullptr; } if (instance_) { wgpuInstanceRelease(instance_); instance_ = nullptr; } }