载入中...
搜索中...
未找到
InitFlow.cpp
浏览该文件的文档.
2
3#include "common/Exception.h"
4
5#include <atomic>
6#include <cstdio>
7#include <cstring>
8
9#if defined(__EMSCRIPTEN__)
10#include <emscripten/emscripten.h>
11#endif
12
13namespace eve::graphics::webgpu {
14
16 wgpu::Instance instance;
17#if defined(__EMSCRIPTEN__)
18 instance = wgpu::CreateInstance();
19#else
20 // Native (Dawn) requires the TimedWaitAny instance feature so the
21 // ProcessEvents busy-wait below can drive the request callbacks.
22 const WGPUInstanceFeatureName requiredFeatures[] = {WGPUInstanceFeatureName_TimedWaitAny};
23 WGPUInstanceDescriptor instanceDesc{};
24 instanceDesc.requiredFeatureCount = 1;
25 instanceDesc.requiredFeatures = requiredFeatures;
26 instance = wgpu::CreateInstance(reinterpret_cast<const wgpu::InstanceDescriptor*>(&instanceDesc));
27#endif
28 if (!instance) throw Exception("WebGPU: wgpuCreateInstance failed");
29 return InstanceDone{std::move(instance)};
30}
31
32AdapterDone InitFlow::requestAdapter(InstanceDone&& prev, const wgpu::Surface& compatibleSurface) {
33 wgpu::Instance& instance = prev.instance;
34
35 struct Result {
36 wgpu::Adapter adapter;
37 std::string error;
38 std::atomic<bool> received{false};
39 } result;
40
41 WGPURequestAdapterOptions opts{};
42 opts.compatibleSurface = compatibleSurface.Get();
43 opts.powerPreference = WGPUPowerPreference_HighPerformance;
44
45 WGPURequestAdapterCallbackInfo cbInfo{};
46 cbInfo.nextInChain = nullptr;
47 cbInfo.mode = WGPUCallbackMode_AllowProcessEvents;
48 cbInfo.callback = [](WGPURequestAdapterStatus status, WGPUAdapter a, WGPUStringView msg, void* userdata1,
49 void* /*userdata2*/) {
50 auto* r = static_cast<Result*>(userdata1);
51 if (status == WGPURequestAdapterStatus_Success && a) {
52 r->adapter = wgpu::Adapter(a);
53 } else {
54 r->error = msg.data ? std::string(msg.data, msg.length) : "unknown adapter error";
55 }
56 r->received.store(true);
57 };
58 cbInfo.userdata1 = &result;
59 cbInfo.userdata2 = nullptr;
60
61 wgpuInstanceRequestAdapter(instance.Get(), &opts, cbInfo);
62 while (!result.received.load()) {
63#if defined(__EMSCRIPTEN__)
64 // Yield to the browser event loop so the JS requestAdapter promise can
65 // resolve and fire the callback, then flush it with ProcessEvents.
66 emscripten_sleep(0);
67#endif
68 wgpuInstanceProcessEvents(instance.Get());
69 }
70 if (!result.adapter) {
71 throw Exception("WebGPU: no adapter found (%s)", result.error.c_str());
72 }
73 return AdapterDone{std::move(instance), std::move(result.adapter)};
74}
75
77 wgpu::Instance& instance = prev.instance;
78 wgpu::Adapter& adapter = prev.adapter;
79
80 struct Result {
81 wgpu::Device device;
82 std::string error;
83 std::atomic<bool> received{false};
84 } result;
85
86 WGPUDeviceDescriptor devDesc{};
87 devDesc.label = sv("eve_device");
88 // Mesh3D bind group samples albedo/normal/env/shadow/height/depth/AO/extras.
89 constexpr std::uint32_t requiredSampledTextures = 17;
90 // Phase B GBuffer is five RGBA8Unorm color targets (5×8 = 40 bytes/sample).
91 // WebGPU's default maxColorAttachmentBytesPerSample is 32; Dawn/macOS
92 // adapters advertise 128 but only grant it when requested here.
93 constexpr std::uint32_t requiredColorAttachmentBytes = 40;
94 wgpu::Limits adapterLimits{};
95 if (adapter.GetLimits(&adapterLimits) != wgpu::Status::Success ||
96 adapterLimits.maxSampledTexturesPerShaderStage < requiredSampledTextures)
97 throw Exception("WebGPU: adapter exposes fewer than %u sampled textures per shader stage",
98 requiredSampledTextures);
99 if (adapterLimits.maxColorAttachmentBytesPerSample < requiredColorAttachmentBytes)
100 throw Exception(
101 "WebGPU: adapter maxColorAttachmentBytesPerSample (%u) is below the "
102 "GBuffer requirement (%u)",
103 adapterLimits.maxColorAttachmentBytesPerSample, requiredColorAttachmentBytes);
104 WGPULimits requiredLimits = WGPU_LIMITS_INIT;
105 requiredLimits.maxSampledTexturesPerShaderStage = requiredSampledTextures;
106 requiredLimits.maxColorAttachmentBytesPerSample = requiredColorAttachmentBytes;
107 // Leave maxColorAttachments at the WGPU default (8); only raise bytes/sample.
108 devDesc.requiredLimits = &requiredLimits;
109 devDesc.uncapturedErrorCallbackInfo.callback = [](WGPUDevice const*, WGPUErrorType type, WGPUStringView message,
110 void*, void*) {
111 std::fprintf(stderr, "[webgpu] uncaptured error type=%d: %.*s\n", int(type), int(message.length),
112 message.data ? message.data : "");
113 };
114
115 WGPURequestDeviceCallbackInfo cbInfo{};
116 cbInfo.nextInChain = nullptr;
117 cbInfo.mode = WGPUCallbackMode_AllowProcessEvents;
118 cbInfo.callback = [](WGPURequestDeviceStatus status, WGPUDevice d, WGPUStringView msg, void* userdata1,
119 void* /*userdata2*/) {
120 auto* r = static_cast<Result*>(userdata1);
121 if (status == WGPURequestDeviceStatus_Success && d) {
122 r->device = wgpu::Device(d);
123 } else {
124 r->error = msg.data ? std::string(msg.data, msg.length) : "unknown device error";
125 }
126 r->received.store(true);
127 };
128 cbInfo.userdata1 = &result;
129 cbInfo.userdata2 = nullptr;
130
131 wgpuAdapterRequestDevice(adapter.Get(), &devDesc, cbInfo);
132 while (!result.received.load()) {
133#if defined(__EMSCRIPTEN__)
134 emscripten_sleep(0);
135#endif
136 wgpuInstanceProcessEvents(instance.Get());
137 }
138 if (!result.device) {
139 throw Exception("WebGPU: device request failed (%s)", result.error.c_str());
140 }
141
142 wgpu::Queue queue = result.device.GetQueue();
144 caps.capture(adapter, result.device);
145 return DeviceDone{std::move(instance), std::move(adapter), std::move(result.device), std::move(queue),
146 std::move(caps)};
147}
148
149} // namespace eve::graphics::webgpu
std::string message
vkb::Device & device
wgpu::PopErrorScopeStatus status
double r
MeleePoint3 a
Definition MeleeHit.cpp:40
std::string error
Definition Package.cpp:60
float d
std::string_view adapter
int caps
Definition TreeMesh.cpp:162
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
Move-only operation result carrying either a value or Status.
Definition Result.h:155
Read-only snapshot of WebGPU adapter/device limits and surface capabilities, queried once after devic...
static DeviceDone requestDevice(AdapterDone &&prev)
Blocking device request (plus queue + capability capture). Throws eve::graphics::Exception on failure...
Definition InitFlow.cpp:76
static InstanceDone createInstance()
Create a wgpu Instance (native requests the TimedWaitAny feature).
Definition InitFlow.cpp:15
static AdapterDone requestAdapter(InstanceDone &&prev, const wgpu::Surface &compatibleSurface)
Blocking adapter request. Drives ProcessEvents until the callback fires; throws eve::graphics::Except...
Definition InitFlow.cpp:32
WGPUStringView sv(const char *s)
Build a WGPUStringView from a C string (null-safe, length auto-computed).
Definition wgpu_types.h:20
Instance + adapter resolved.
Definition InitFlow.h:23
Instance + adapter + device + queue + capability snapshot.
Definition InitFlow.h:29
Instance created, no adapter yet.
Definition InitFlow.h:18