Skip to content

Commit 4c9708a

Browse files
committed
feat!: switch to raise-based error model (v0.7.0)
1 parent 70b35f5 commit 4c9708a

23 files changed

+546
-576
lines changed

.beads/issues.jsonl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
{"id":"wgpu_mbt-1mk.2","title":"Declare/bindings: render pipeline pos2 with explicit pipeline layout","description":"Add C stub + raw extern for render pipeline (pos2) that takes PipelineLayout* so we can bind uniform buffer.","status":"closed","priority":2,"issue_type":"task","owner":"842376130@qq.com","created_at":"2026-01-26T15:20:27.963986+08:00","created_by":"Milky2018","updated_at":"2026-01-26T15:23:43.754006+08:00","closed_at":"2026-01-26T15:23:43.754006+08:00","close_reason":"Closed","dependencies":[{"issue_id":"wgpu_mbt-1mk.2","depends_on_id":"wgpu_mbt-1mk","type":"parent-child","created_at":"2026-01-26T15:20:27.964737+08:00","created_by":"Milky2018"}]}
2020
{"id":"wgpu_mbt-1mk.3","title":"Test: offscreen render with uniform color (beads)","description":"Render 1x1 using pos2 vertex buffer + uniform vec4 color bound at group(0)/binding(0), assert pixel from readback.","status":"closed","priority":2,"issue_type":"task","owner":"842376130@qq.com","created_at":"2026-01-26T15:20:28.048084+08:00","created_by":"Milky2018","updated_at":"2026-01-26T15:23:43.755198+08:00","closed_at":"2026-01-26T15:23:43.755198+08:00","close_reason":"Closed","dependencies":[{"issue_id":"wgpu_mbt-1mk.3","depends_on_id":"wgpu_mbt-1mk","type":"parent-child","created_at":"2026-01-26T15:20:28.048735+08:00","created_by":"Milky2018"}]}
2121
{"id":"wgpu_mbt-1sn","title":"wgpu: indirect dispatch + draw","description":"Expose ComputePass dispatch_workgroups_indirect and RenderPass draw_indirect/draw_indexed_indirect, plus BufferUsage_Indirect constant. Add root tests that render a pixel via draw_indirect and run compute via dispatch_indirect.","status":"closed","priority":2,"issue_type":"task","owner":"842376130@qq.com","created_at":"2026-01-27T10:24:07.231141+08:00","created_by":"Milky2018","updated_at":"2026-01-27T10:33:44.119593+08:00","closed_at":"2026-01-27T10:33:44.119595+08:00","dependencies":[{"issue_id":"wgpu_mbt-1sn","depends_on_id":"wgpu_mbt-avd","type":"blocks","created_at":"2026-01-27T10:24:07.231847+08:00","created_by":"Milky2018"}],"comments":[{"id":11,"issue_id":"wgpu_mbt-1sn","author":"Milky2018","text":"Implemented indirect dispatch/draw APIs (ComputePass.dispatch_workgroups_indirect, RenderPass.draw_indirect/draw_indexed_indirect) and added root tests for draw_indirect + dispatch_indirect. Added buffer usage constants for INDIRECT and QUERY_RESOLVE.","created_at":"2026-01-27T02:33:44Z"}]}
22+
{"id":"wgpu_mbt-2de","title":"Breaking: switch error model to raise/try-catch (no Result)","description":"Replace public Result-returning APIs with raise-based error model (try/catch). Update docs/tests. Bump 0.x major.","status":"closed","priority":0,"issue_type":"epic","owner":"842376130@qq.com","created_at":"2026-02-02T20:35:32.23106+08:00","created_by":"Milky2018","updated_at":"2026-02-02T20:59:34.47554+08:00","closed_at":"2026-02-02T20:59:34.47554+08:00","close_reason":"Epic complete: error model is raise/try-catch end-to-end (no Result APIs)."}
23+
{"id":"wgpu_mbt-2de.1","title":"API: replace Result with raise","description":"Convert require_native/require_native_symbol, Instance::create/adapter/device acquisition, and RenderPipelineDescBuilder APIs to raise-based errors; remove Result from public signatures.","status":"closed","priority":0,"issue_type":"task","assignee":"Milky2018","owner":"842376130@qq.com","created_at":"2026-02-02T20:35:46.605218+08:00","created_by":"Milky2018","updated_at":"2026-02-02T20:59:34.178045+08:00","closed_at":"2026-02-02T20:59:34.178045+08:00","close_reason":"Switched public APIs from Result to raise-based errors (WgpuError/RenderPipelineDescError); updated C helpers for status/null checks.","dependencies":[{"issue_id":"wgpu_mbt-2de.1","depends_on_id":"wgpu_mbt-2de","type":"parent-child","created_at":"2026-02-02T20:35:46.606015+08:00","created_by":"Milky2018"}]}
24+
{"id":"wgpu_mbt-2de.2","title":"Update tests + examples for try/catch","description":"Adjust all tests and cmd examples to compile with raise-based API (no .unwrap()).","status":"closed","priority":0,"issue_type":"task","owner":"842376130@qq.com","created_at":"2026-02-02T20:35:46.713862+08:00","created_by":"Milky2018","updated_at":"2026-02-02T20:59:34.279389+08:00","closed_at":"2026-02-02T20:59:34.279389+08:00","close_reason":"Updated cmd tools and tests to use try/catch and new raising pipeline builder API.","dependencies":[{"issue_id":"wgpu_mbt-2de.2","depends_on_id":"wgpu_mbt-2de","type":"parent-child","created_at":"2026-02-02T20:35:46.714655+08:00","created_by":"Milky2018"}]}
25+
{"id":"wgpu_mbt-2de.3","title":"Docs + version bump + publish","description":"Update README to document try/catch usage. Bump version to 0.7.0, publish, verify CI and release assets.","status":"closed","priority":1,"issue_type":"task","owner":"842376130@qq.com","created_at":"2026-02-02T20:35:46.912121+08:00","created_by":"Milky2018","updated_at":"2026-02-02T20:59:34.377105+08:00","closed_at":"2026-02-02T20:59:34.377105+08:00","close_reason":"Updated README, bumped version to 0.7.0, ran moon info/fmt/check/test; ready to publish.","dependencies":[{"issue_id":"wgpu_mbt-2de.3","depends_on_id":"wgpu_mbt-2de","type":"parent-child","created_at":"2026-02-02T20:35:46.912936+08:00","created_by":"Milky2018"}]}
2226
{"id":"wgpu_mbt-2gy","title":"refactor: move wgpu -\u003e src and tests into src/tests","description":"Rename package directory wgpu/ to src/, add moon.mod.json source=src, move root tests to src/tests, and keep cmd runnable.","notes":"Applying directory rename + source root changes","status":"closed","priority":2,"issue_type":"task","owner":"842376130@qq.com","created_at":"2026-01-27T14:40:59.624223+08:00","created_by":"Milky2018","updated_at":"2026-01-27T14:43:53.915336+08:00","closed_at":"2026-01-27T14:43:53.915336+08:00","close_reason":"renamed wgpu/ -\u003e src/, set source=src, moved tests to src/tests, kept cmd runnable via symlink"}
2327
{"id":"wgpu_mbt-5px","title":"Hardening: safe init + auto-enable robustness","description":"Improve error model around native loading and make auto-enable markers robust to lib changes.","status":"closed","priority":1,"issue_type":"epic","owner":"842376130@qq.com","created_at":"2026-02-02T19:41:54.933202+08:00","created_by":"Milky2018","updated_at":"2026-02-02T20:05:38.571122+08:00","closed_at":"2026-02-02T20:05:38.571122+08:00","close_reason":"All child tasks completed and released (v0.6.5–v0.6.7): safe native init API, marker path binding, troubleshooting docs."}
2428
{"id":"wgpu_mbt-5px.1","title":"Error model: non-aborting Instance::try_create + require_native","description":"Add Result-returning APIs to avoid abort when libwgpu_native is missing: require_native(), Instance::try_create(), Instance::try_create_ptr(). Update cmd/main example and README.","status":"closed","priority":0,"issue_type":"task","assignee":"Milky2018","owner":"842376130@qq.com","created_at":"2026-02-02T19:42:02.940458+08:00","created_by":"Milky2018","updated_at":"2026-02-02T19:44:37.080202+08:00","closed_at":"2026-02-02T19:44:37.080202+08:00","close_reason":"Added NativeLoadError + require_native() + Instance::try_create/try_create_ptr to avoid aborts when libwgpu_native is missing; updated README and cmd/main.","dependencies":[{"issue_id":"wgpu_mbt-5px.1","depends_on_id":"wgpu_mbt-5px","type":"parent-child","created_at":"2026-02-02T19:42:02.941321+08:00","created_by":"Milky2018"}]}

README.mbt.md

Lines changed: 44 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -179,20 +179,22 @@ This module does **not** try to locate the library via CWD.
179179
If neither location works, the process will abort when the first WebGPU symbol is used
180180
(because we `dlopen` the library lazily).
181181

182-
To avoid aborts and surface a diagnostic string instead, use:
183-
- `@wgpu.require_native()` (returns `Result[Unit, NativeLoadError]`)
184-
- `Instance::try_create()` / `Instance::try_create_ptr(...)` (returns `Result[Instance, NativeLoadError]`)
182+
To avoid aborts and surface a diagnostic string instead, use `try/catch` around:
183+
- `@wgpu.require_native()` / `@wgpu.require_native_symbol("wgpu...")` (raises `WgpuError`)
184+
- `Instance::create()` / `Instance::create_ptr(...)` (raises `WgpuError`)
185+
- `Instance::request_adapter_sync()` / `Instance::request_adapter_sync_ptr(...)` (raises `WgpuError`)
186+
- `Adapter::request_device_sync()` / `Adapter::request_device_sync_ptr(...)` (raises `WgpuError`)
185187

186188
## Troubleshooting
187189

188190
If you see crashes/aborts early in the program, it is usually because `libwgpu_native` cannot be located/loaded.
189191

190192
- Inspect loader diagnostics:
191193
- `@wgpu.native_diagnostic()`
192-
- Avoid aborts while checking availability:
193-
- `@wgpu.native_check()` / `@wgpu.require_native_symbol("wgpu...")`
194-
- `Instance::try_create()` / `Instance::try_create_ptr(...)`
195-
- `Instance::try_request_adapter_sync()` / `Adapter::try_request_device_sync(...)`
194+
- Avoid aborts while checking availability (use `try/catch`):
195+
- `@wgpu.require_native()` / `@wgpu.require_native_symbol("wgpu...")`
196+
- `Instance::create()` / `Instance::create_ptr(...)`
197+
- `Instance::request_adapter_sync()` / `Adapter::request_device_sync(...)`
196198
- Fix typical causes:
197199
- Install the native library to the default per-user path (recommended) by running `python3 scripts/postadd.py`
198200
- Or set `MBT_WGPU_NATIVE_LIB` to an absolute path to your `.dylib` / `.so` / `.dll`
@@ -222,59 +224,44 @@ Minimal example (same as `src/cmd/main/main.mbt`):
222224

223225
```moonbit
224226
fn main {
225-
let instance = match @wgpu.Instance::try_create() {
226-
Ok(i) => i
227-
Err(e) => {
227+
try {
228+
let instance = @wgpu.Instance::create()
229+
let adapter = instance.request_adapter_sync()
230+
let device = adapter.request_device_sync(instance)
231+
let queue = device.queue()
232+
let buf = device.create_buffer(
233+
size=4UL,
234+
usage=@wgpu.BufferUsage::from_u64(@wgpu.BUFFER_USAGE_COPY_DST),
235+
)
236+
ignore(buf.size())
237+
let wgsl : String =
238+
#|@compute @workgroup_size(1)
239+
#|fn main() {}
240+
#|
241+
let sm = device.create_shader_module_wgsl(wgsl)
242+
let pipeline = device.create_compute_pipeline(sm)
243+
let encoder = device.create_command_encoder()
244+
let pass = encoder.begin_compute_pass()
245+
pass.set_pipeline(pipeline)
246+
pass.dispatch_workgroups(1U, 1U, 1U)
247+
pass.end()
248+
pass.release()
249+
let cmd = encoder.finish()
250+
queue.submit_one(cmd)
251+
buf.release()
252+
cmd.release()
253+
encoder.release()
254+
pipeline.release()
255+
sm.release()
256+
queue.release()
257+
device.release()
258+
adapter.release()
259+
instance.release()
260+
} catch {
261+
e => {
228262
println(e.message())
229-
return
230263
}
231264
}
232-
let adapter = match instance.try_request_adapter_sync() {
233-
Ok(a) => a
234-
Err(e) => {
235-
println(e.message())
236-
instance.release()
237-
return
238-
}
239-
}
240-
let device = match adapter.try_request_device_sync(instance) {
241-
Ok(d) => d
242-
Err(e) => {
243-
println(e.message())
244-
adapter.release()
245-
instance.release()
246-
return
247-
}
248-
}
249-
let queue = device.queue()
250-
let buf = device.create_buffer(
251-
size=4UL,
252-
usage=@wgpu.BufferUsage::from_u64(@wgpu.BUFFER_USAGE_COPY_DST),
253-
)
254-
ignore(buf.size())
255-
let wgsl : String =
256-
#|@compute @workgroup_size(1)
257-
#|fn main() {}
258-
#|
259-
let sm = device.create_shader_module_wgsl(wgsl)
260-
let pipeline = device.create_compute_pipeline(sm)
261-
let encoder = device.create_command_encoder()
262-
let pass = encoder.begin_compute_pass()
263-
pass.set_pipeline(pipeline)
264-
pass.dispatch_workgroups(1U, 1U, 1U)
265-
pass.end()
266-
pass.release()
267-
let cmd = encoder.finish()
268-
queue.submit_one(cmd)
269-
buf.release()
270-
cmd.release()
271-
encoder.release()
272-
pipeline.release()
273-
sm.release()
274-
queue.release()
275-
device.release()
276-
adapter.release()
277-
instance.release()
278265
}
279266
```
280267

moon.mod.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "Milky2018/wgpu_mbt",
3-
"version": "0.6.8",
3+
"version": "0.7.0",
44
"readme": "README.mbt.md",
55
"repository": "https://github.com/moonbit-community/wgpu-mbt.git",
66
"license": "Apache-2.0",

src/c/pkg.generated.mbti

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ pub fn adapter_info_vendor_utf8(WGPUAdapter, Bytes, UInt64) -> Bool
3838

3939
pub fn adapter_info_vendor_utf8_len(WGPUAdapter) -> UInt64
4040

41+
pub fn adapter_is_null(WGPUAdapter) -> Bool
42+
4143
pub fn adapter_limits_max_bind_groups_u32(WGPUAdapter) -> UInt
4244

4345
pub fn adapter_limits_max_buffer_size_u64(WGPUAdapter) -> UInt64
@@ -50,6 +52,8 @@ pub fn adapter_release(WGPUAdapter) -> Unit
5052

5153
pub fn adapter_request_device_sync(WGPUInstance, WGPUAdapter) -> WGPUDevice
5254

55+
pub fn adapter_request_device_sync_last_status_u32() -> UInt
56+
5357
pub fn adapter_request_device_sync_pipeline_statistics_query(WGPUInstance, WGPUAdapter) -> WGPUDevice
5458

5559
pub fn adapter_request_device_sync_ptr(WGPUInstance, WGPUAdapter, WGPUDeviceDescriptorPtr) -> WGPUDevice
@@ -418,6 +422,8 @@ pub fn device_destroy_record_lost(WGPUDevice) -> Unit
418422

419423
pub fn device_get_queue(WGPUDevice) -> WGPUQueue
420424

425+
pub fn device_is_null(WGPUDevice) -> Bool
426+
421427
pub fn device_limits_max_bind_groups_u32(WGPUDevice) -> UInt
422428

423429
pub fn device_limits_max_buffer_size_u64(WGPUDevice) -> UInt64
@@ -496,6 +502,8 @@ pub fn instance_release(WGPUInstance) -> Unit
496502

497503
pub fn instance_request_adapter_sync(WGPUInstance) -> WGPUAdapter
498504

505+
pub fn instance_request_adapter_sync_last_status_u32() -> UInt
506+
499507
pub fn instance_request_adapter_sync_options_u32(WGPUInstance, UInt, UInt, Bool, UInt, WGPUSurface) -> WGPUAdapter
500508

501509
pub fn instance_request_adapter_sync_ptr(WGPUInstance, WGPURequestAdapterOptionsPtr) -> WGPUAdapter

src/c/raw_adapter_device.mbt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ pub extern "C" fn adapter_request_device_sync_ptr(
198198
descriptor : WGPUDeviceDescriptorPtr,
199199
) -> Device = "mbt_wgpu_adapter_request_device_sync_ptr"
200200

201+
///|
202+
pub extern "C" fn adapter_request_device_sync_last_status_u32() -> UInt = "mbt_wgpu_adapter_request_device_sync_last_status_u32"
203+
201204
///|
202205
pub extern "C" fn adapter_request_device_sync_timestamp_query(
203206
instance : Instance,

src/c/raw_core.mbt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ pub extern "C" fn null_submission_index_ptr() -> WGPUSubmissionIndexPtr = "mbt_w
7171
///|
7272
pub extern "C" fn shader_module_is_null(shader_module : ShaderModule) -> Bool = "mbt_wgpu_shader_module_is_null"
7373

74+
///|
75+
pub extern "C" fn adapter_is_null(adapter : Adapter) -> Bool = "mbt_wgpu_adapter_is_null"
76+
77+
///|
78+
pub extern "C" fn device_is_null(device : Device) -> Bool = "mbt_wgpu_device_is_null"
79+
7480
///|
7581
pub extern "C" fn null_render_pipeline_descriptor_ptr() -> WGPURenderPipelineDescriptorPtr = "mbt_wgpu_null_ptr"
7682

src/c/raw_instance.mbt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ pub extern "C" fn instance_request_adapter_sync_ptr(
5454
options : WGPURequestAdapterOptionsPtr,
5555
) -> Adapter = "mbt_wgpu_instance_request_adapter_sync_ptr"
5656

57+
///|
58+
pub extern "C" fn instance_request_adapter_sync_last_status_u32() -> UInt = "mbt_wgpu_instance_request_adapter_sync_last_status_u32"
59+
5760
///|
5861
pub fn instance_request_adapter_sync_options_u32(
5962
instance : Instance,

src/c/wgpu_stub_core.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ bool mbt_wgpu_render_pipeline_descriptor_ptr_is_null(WGPURenderPipelineDescripto
2727
return p == NULL;
2828
}
2929

30+
bool mbt_wgpu_adapter_is_null(WGPUAdapter adapter) { return adapter == NULL; }
31+
bool mbt_wgpu_device_is_null(WGPUDevice device) { return device == NULL; }
32+
3033
bool mbt_wgpu_platform_is_macos(void) {
3134
#if defined(__APPLE__)
3235
return true;

0 commit comments

Comments
 (0)