Skip to content

Commit 53ee7c9

Browse files
Use WebGPUEnvironmentError for probe results
1 parent 636bc6d commit 53ee7c9

File tree

11 files changed

+200
-87
lines changed

11 files changed

+200
-87
lines changed

samples/DrawingBackendBenchmark/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Depending on what the machine can initialize, the sample can show:
1515
- `SkiaSharp (GPU)`: Skia using a GPU-backed `GRContext` when the hidden GL host is available
1616
- `WebGPU`: the offscreen `ImageSharp.Drawing.WebGPU` backend
1717

18-
The sample always starts with the CPU and Skia CPU paths. The WebGPU backend is added only when `WebGPUEnvironment.TryProbeComputePipelineSupport(...)` succeeds. The Skia GPU backend is added once the hidden `SKGLControl` has produced a usable `GRContext`.
18+
The sample always starts with the CPU and Skia CPU paths. The WebGPU backend is added only when `WebGPUEnvironment.ProbeComputePipelineSupport()` returns `WebGPUEnvironmentError.Success`. The Skia GPU backend is added once the hidden `SKGLControl` has produced a usable `GRContext`.
1919

2020
## What the UI shows
2121

@@ -77,7 +77,7 @@ This keeps the benchmark focused on scene rendering rather than repeated target
7777

7878
The WebGPU backend is intentionally small:
7979

80-
- it probes support up front with `WebGPUEnvironment.TryProbeComputePipelineSupport(...)`
80+
- it probes support up front with `WebGPUEnvironment.ProbeComputePipelineSupport()`
8181
- it renders into an owned offscreen `WebGPURenderTarget<Bgra32>`
8282
- it draws through `CreateCanvas(...)`, not a hybrid CPU plus GPU canvas
8383
- it reads back the final frame only when the UI requests the last-iteration preview

samples/DrawingBackendBenchmark/WebGpuBenchmarkBackend.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ private WebGpuBenchmarkBackend()
2323

2424
public static bool TryCreate([NotNullWhen(true)] out WebGpuBenchmarkBackend? result, [NotNullWhen(false)] out string? error)
2525
{
26-
if (!WebGPUEnvironment.TryProbeComputePipelineSupport(out error))
26+
WebGPUEnvironmentError probeError = WebGPUEnvironment.ProbeComputePipelineSupport();
27+
if (probeError != WebGPUEnvironmentError.Success)
2728
{
2829
result = null;
30+
error = $"WebGPU unavailable: {probeError}.";
2931
return false;
3032
}
3133

src/ImageSharp.Drawing.WebGPU/RemoteExecutor/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ private static int Main(string[] args)
2525

2626
return methodName switch
2727
{
28-
nameof(WebGPURuntime.ProbeComputePipelineSupport) => WebGPURuntime.ProbeComputePipelineSupport(),
28+
nameof(WebGPURuntime.RunComputePipelineSupportProbe) => WebGPURuntime.RunComputePipelineSupportProbe(),
2929
_ => -1
3030
};
3131
}

src/ImageSharp.Drawing.WebGPU/WEBGPU_BACKEND.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ Those types all exist to get a `DrawingCanvas<TPixel>` over a native WebGPU targ
2828

2929
The support probes also live outside the backend:
3030

31-
- `WebGPUEnvironment.TryProbeAvailability(...)` checks whether the library-managed WebGPU device and queue can be acquired
32-
- `WebGPUEnvironment.TryProbeComputePipelineSupport(...)` runs the crash-isolated trivial compute-pipeline probe
31+
- `WebGPUEnvironment.ProbeAvailability()` checks whether the library-managed WebGPU device and queue can be acquired
32+
- `WebGPUEnvironment.ProbeComputePipelineSupport()` runs the crash-isolated trivial compute-pipeline probe
3333

3434
That split keeps support probing separate from flush execution. `WebGPUDrawingBackend` is the flush executor, not the public support API. The WebGPU constructors create their objects directly; callers use `WebGPUEnvironment` when they want explicit preflight checks.
3535

src/ImageSharp.Drawing.WebGPU/WebGPUDeviceContext{TPixel}.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ public WebGPUDeviceContext(Configuration configuration)
3636

3737
try
3838
{
39-
if (!WebGPURuntime.TryGetOrCreateDevice(out WebGPUDeviceHandle? deviceHandle, out WebGPUQueueHandle? queueHandle, out string? error)
39+
if (!WebGPURuntime.TryGetOrCreateDevice(out WebGPUDeviceHandle? deviceHandle, out WebGPUQueueHandle? queueHandle, out WebGPUEnvironmentError errorCode)
4040
|| deviceHandle is null
4141
|| queueHandle is null)
4242
{
43-
throw new InvalidOperationException(error);
43+
throw new InvalidOperationException(WebGPURuntime.CreateEnvironmentExceptionMessage(errorCode));
4444
}
4545

4646
this.DeviceHandle = deviceHandle;
Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

4-
using System.Diagnostics.CodeAnalysis;
5-
64
namespace SixLabors.ImageSharp.Drawing.Processing.Backends;
75

86
/// <summary>
@@ -12,18 +10,22 @@ namespace SixLabors.ImageSharp.Drawing.Processing.Backends;
1210
public static class WebGPUEnvironment
1311
{
1412
/// <summary>
15-
/// Tries to acquire the library-managed WebGPU device and queue.
13+
/// Probes whether the library-managed WebGPU device and queue are available.
1614
/// </summary>
17-
/// <param name="error">Receives the failure reason when the probe fails.</param>
18-
/// <returns><see langword="true"/> when the library-managed WebGPU device and queue are available; otherwise, <see langword="false"/>.</returns>
19-
public static bool TryProbeAvailability([NotNullWhen(false)] out string? error)
20-
=> WebGPURuntime.TryProbeAvailability(out error);
15+
/// <returns>
16+
/// <see cref="WebGPUEnvironmentError.Success"/> when the library-managed WebGPU device and queue are available;
17+
/// otherwise, the stable failure code describing why the probe failed.
18+
/// </returns>
19+
public static WebGPUEnvironmentError ProbeAvailability()
20+
=> WebGPURuntime.ProbeAvailability();
2121

2222
/// <summary>
23-
/// Tries to create a trivial compute pipeline using the library-managed WebGPU device.
23+
/// Probes whether the library-managed WebGPU device can create a trivial compute pipeline.
2424
/// </summary>
25-
/// <param name="error">Receives the failure reason when the probe fails.</param>
26-
/// <returns><see langword="true"/> when compute pipeline creation succeeds; otherwise, <see langword="false"/>.</returns>
27-
public static bool TryProbeComputePipelineSupport([NotNullWhen(false)] out string? error)
28-
=> WebGPURuntime.TryProbeComputePipelineSupport(out error);
25+
/// <returns>
26+
/// <see cref="WebGPUEnvironmentError.Success"/> when compute pipeline creation succeeds;
27+
/// otherwise, the stable failure code describing why the probe failed.
28+
/// </returns>
29+
public static WebGPUEnvironmentError ProbeComputePipelineSupport()
30+
=> WebGPURuntime.ProbeComputePipelineSupport();
2931
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
namespace SixLabors.ImageSharp.Drawing.Processing.Backends;
5+
6+
/// <summary>
7+
/// Error codes returned by <see cref="WebGPUEnvironment"/> probe methods.
8+
/// </summary>
9+
/// <remarks>
10+
/// <see cref="Success"/> is the only successful result. All other values describe one stable
11+
/// failure case that callers can branch on without parsing diagnostic strings.
12+
/// </remarks>
13+
public enum WebGPUEnvironmentError
14+
{
15+
/// <summary>
16+
/// The probe succeeded.
17+
/// </summary>
18+
Success = 0,
19+
20+
/// <summary>
21+
/// The shared WebGPU API loader or required extension could not be initialized.
22+
/// </summary>
23+
ApiInitializationFailed,
24+
25+
/// <summary>
26+
/// The runtime could not create a WebGPU instance.
27+
/// </summary>
28+
InstanceCreationFailed,
29+
30+
/// <summary>
31+
/// The adapter request callback did not complete before the timeout expired.
32+
/// </summary>
33+
AdapterRequestTimedOut,
34+
35+
/// <summary>
36+
/// The runtime failed to acquire a WebGPU adapter.
37+
/// </summary>
38+
AdapterRequestFailed,
39+
40+
/// <summary>
41+
/// The device request callback did not complete before the timeout expired.
42+
/// </summary>
43+
DeviceRequestTimedOut,
44+
45+
/// <summary>
46+
/// The runtime failed to acquire a WebGPU device.
47+
/// </summary>
48+
DeviceRequestFailed,
49+
50+
/// <summary>
51+
/// The runtime acquired a device but could not retrieve its default queue.
52+
/// </summary>
53+
QueueAcquisitionFailed,
54+
55+
/// <summary>
56+
/// The runtime could not provision the shared device/queue pair for an unspecified reason.
57+
/// </summary>
58+
DeviceAcquisitionFailed,
59+
60+
/// <summary>
61+
/// The isolated compute-pipeline probe ran to completion and reported that compute pipeline creation failed.
62+
/// </summary>
63+
ComputePipelineCreationFailed,
64+
65+
/// <summary>
66+
/// The isolated compute-pipeline probe process terminated before it could report a normal result.
67+
/// </summary>
68+
ComputePipelineProbeProcessFailed,
69+
}

0 commit comments

Comments
 (0)