|
1 | 1 | # Drawing Backend Benchmark |
2 | 2 |
|
3 | | -A Windows sample based on the original `ImageSharpBenchmark` workload from the `Csharp-Data-Visualization` repo. |
| 3 | +`DrawingBackendBenchmark` is a small Windows sample that renders the same randomized line scene through several drawing backends and shows the last rendered frame alongside timing statistics. |
| 4 | + |
| 5 | +It is based on the original ImageSharp benchmark workload from the `Csharp-Data-Visualization` repo: |
4 | 6 |
|
5 | 7 | https://swharden.com/csdv/platforms/compare/ |
6 | 8 |
|
7 | | -It renders a randomized line scene repeatedly and lets you compare: |
| 9 | +## What it compares |
| 10 | + |
| 11 | +Depending on what the machine can initialize, the sample can show: |
| 12 | + |
| 13 | +- `CPU`: the default `ImageSharp.Drawing` CPU backend |
| 14 | +- `SkiaSharp (CPU)`: Skia rasterized in CPU mode |
| 15 | +- `SkiaSharp (GPU)`: Skia using a GPU-backed `GRContext` when the hidden GL host is available |
| 16 | +- `WebGPU`: the offscreen `ImageSharp.Drawing.WebGPU` backend |
8 | 17 |
|
9 | | -- `CPU` via the default `ImageSharp.Drawing` backend |
10 | | -- `WebGPU` via the offscreen `ImageSharp.Drawing.WebGPU` backend |
| 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`. |
11 | 19 |
|
12 | | -The sample shows: |
| 20 | +## What the UI shows |
13 | 21 |
|
14 | | -- a preview of the last rendered frame |
15 | | -- the most recent render time |
16 | | -- running mean |
17 | | -- standard deviation |
| 22 | +The benchmark window contains: |
| 23 | + |
| 24 | +- a backend selector |
| 25 | +- an iteration count selector |
| 26 | +- preset buttons for `10`, `1k`, `10k`, and `100k` lines |
| 27 | +- a preview of the final rendered frame |
| 28 | +- current render time, running mean, and standard deviation |
| 29 | + |
| 30 | +The fixed benchmark surface is `600x400` pixels. |
18 | 31 |
|
19 | 32 | ## Running |
20 | 33 |
|
21 | 34 | ```powershell |
22 | 35 | dotnet run --project samples/DrawingBackendBenchmark -c Release |
23 | 36 | ``` |
24 | 37 |
|
25 | | -The WebGPU path renders to an offscreen native texture and reads the final frame back for preview. The reported benchmark time measures scene rendering and flush time only, not the preview readback. |
| 38 | +## How one benchmark run works |
| 39 | + |
| 40 | +For each iteration the form: |
| 41 | + |
| 42 | +1. generates a deterministic random line set for the requested line count |
| 43 | +2. renders that scene through the selected backend |
| 44 | +3. records the elapsed render time |
| 45 | +4. updates the running mean and standard deviation |
| 46 | +5. captures a preview image only on the last iteration |
| 47 | + |
| 48 | +That last point matters: preview capture is intentionally outside the measured timing path. The reported time measures scene submission and backend flush work only. Any readback, clone, or bitmap conversion needed for the UI happens afterward. |
| 49 | + |
| 50 | +## Timing model |
| 51 | + |
| 52 | +All backends follow the same basic timing rule: |
| 53 | + |
| 54 | +- start the stopwatch immediately before drawing the scene |
| 55 | +- stop it immediately after the backend flush or submission boundary |
| 56 | +- capture preview pixels only after the stopwatch stops |
| 57 | + |
| 58 | +In practice that means: |
| 59 | + |
| 60 | +- `CPU` measures drawing into the cached `Image<Bgra32>` through `DrawingCanvas.Flush()` |
| 61 | +- `SkiaSharp` measures drawing through `SKCanvas.Flush()` and optional GPU context flush |
| 62 | +- `WebGPU` measures drawing through `DrawingCanvas.Flush()` into the offscreen `WebGPURenderTarget<Bgra32>` |
| 63 | + |
| 64 | +So the numbers are comparable as "render and submit" timings, not "render plus preview extraction" timings. |
| 65 | + |
| 66 | +## Backend resource reuse |
| 67 | + |
| 68 | +The sample uses a fixed benchmark size, so the backends keep their render targets alive across iterations instead of reallocating them every run: |
| 69 | + |
| 70 | +- `CpuBenchmarkBackend` caches one `Image<Bgra32>` |
| 71 | +- `SkiaSharpBenchmarkBackend` caches one `SKSurface` |
| 72 | +- `WebGpuBenchmarkBackend` caches one `WebGPURenderTarget<Bgra32>` |
| 73 | + |
| 74 | +This keeps the benchmark focused on scene rendering rather than repeated target allocation noise. |
| 75 | + |
| 76 | +## WebGPU path |
| 77 | + |
| 78 | +The WebGPU backend is intentionally small: |
| 79 | + |
| 80 | +- it probes support up front with `WebGPUEnvironment.TryProbeComputePipelineSupport(...)` |
| 81 | +- it renders into an owned offscreen `WebGPURenderTarget<Bgra32>` |
| 82 | +- it draws through `CreateCanvas(...)`, not a hybrid CPU plus GPU canvas |
| 83 | +- it reads back the final frame only when the UI requests the last-iteration preview |
| 84 | + |
| 85 | +The status line also reports whether the last WebGPU flush completed on the staged GPU path or had to fall back to CPU execution. |
| 86 | + |
| 87 | +## File guide |
26 | 88 |
|
27 | | -Internally the sample now uses an owned `WebGPURenderTarget<TPixel>` so the offscreen WebGPU setup stays small while still supporting the benchmark's hybrid CPU+GPU frame flow. |
| 89 | +- [BenchmarkForm.cs](d:/GitHub/SixLabors/ImageSharp.Drawing/samples/DrawingBackendBenchmark/BenchmarkForm.cs): WinForms UI, backend selection, iteration loop, and preview display |
| 90 | +- [CpuBenchmarkBackend.cs](d:/GitHub/SixLabors/ImageSharp.Drawing/samples/DrawingBackendBenchmark/CpuBenchmarkBackend.cs): ImageSharp CPU baseline backend |
| 91 | +- [SkiaSharpBenchmarkBackend.cs](d:/GitHub/SixLabors/ImageSharp.Drawing/samples/DrawingBackendBenchmark/SkiaSharpBenchmarkBackend.cs): Skia CPU and GPU benchmark backend |
| 92 | +- [WebGpuBenchmarkBackend.cs](d:/GitHub/SixLabors/ImageSharp.Drawing/samples/DrawingBackendBenchmark/WebGpuBenchmarkBackend.cs): offscreen WebGPU benchmark backend |
| 93 | +- [VisualLine.cs](d:/GitHub/SixLabors/ImageSharp.Drawing/samples/DrawingBackendBenchmark/VisualLine.cs): shared randomized line scene description and canvas render helper |
0 commit comments