wieslawsoltes/SparseStrips: Vello Sparse Strips .NET Bindings

nuget
nuget
nuget

Status: Ready for production

High-performance .NET 8.0 bindings for the Velo Sparse Strips CPU renderer 100% API coverage,

SparseStrips/
├── extern/vello/              # Git submodule - Vello upstream
│   └── sparse_strips/
│       ├── vello_cpu/         # Core CPU renderer
│       └── vello_common/      # Common utilities
│
├── vello_cpu_ffi/             # Rust C-ABI FFI wrapper
│   ├── Cargo.toml
│   ├── build.rs
│   └── src/
│       └── lib.rs             # FFI exports
│
├── dotnet/                    # .NET bindings
│   ├── src/                   # Shipping packages
│   │   ├── Vello.Native/      # P/Invoke layer (internal)
│   │   ├── Vello/             # High-level C# API (public)
│   │   └── Vello.Avalonia/    # Avalonia control + helpers (NuGet package)
│   ├── samples/               # Demo applications
│   │   ├── Vello.Samples/     # 15 example applications
│   │   ├── Vello.Examples/    # CLI samples
│   │   └── MTTest/            # Multithreading investigation harness
│   └── tests/                 # Automated + perf suites
│       ├── Vello.Tests/       # 85 unit tests (95.3% passing)
│       ├── Vello.DiagnosticTests/   # Deep diagnostics harness
│       ├── Vello.Benchmarks/  # BenchmarkDotNet harness
│       └── Vello.IntegrationTest/   # Package validation app
│
├── docs/                      # Documentation
│   ├── API_COVERAGE.md        # Complete API coverage matrix
│   ├── FFI_DESIGN.md          # FFI architecture and design
│   ├── IMPLEMENTATION_PLAN.md # Development phases
│   └── STATUS.md              # Project status
│
└── README.md                  # This file
  • 100% API coverage – All 34 RenderContext methods implemented
  • complete feature set – Images, gradients, blending, clipping, masking, glyphs
  • zero-allocation rendering , Span/stackalloc For text, gradients, PNG I/O (steps 1 and 2 completed)
  • high performance – Through zero-copy pixel access ReadOnlySpan
  • Modern .NET 8.0 , LibraryImportblowable structures, Span honey bee
  • SIMD support – SSE2, AVX, AVX2, AVX512, NEON
  • multi threading – Configurable worker threads
  • cross-platform – Windows, Linux, macOS (x64, ARM64)
  • secure api , IDisposable pattern, automatic cleaning
  • comprehensive testing – 113 tests (100% passed, including 32 performance tests)
  • 15 examples – Extensive example applications
  • War 1.86+ (for vello_cpu_ffi)
  • .NET 8.0 SDK (for C# bindings)
  • Platform-specific tools,
    • Windows: MSVC or MinGW
    • Linux: GCC/Clang
    • macOS: Xcode Command Line Tools

For convenience, scripts/ The directory highlights one-liners per target platform. Each script builds Velo CPU FFI native libraries for both Debug And Release Profile:

# Windows (PowerShell)
.\scripts\build-windows.ps1
# Linux
./scripts/build-linux.sh

# macOS
./scripts/build-macos.sh

# WebAssembly (requires wasm-tools workload, Emscripten, and Rust nightly)
./scripts/build-wasm.sh

These helpers focus entirely on native Rust artifacts (which include wasm32-unknown-emscripten static collection). Create separate .NET project via dotnet build Or dotnet publish,

Detailed setup notes (toolchain requirements, manual steps, and artifact locations) for each platform are available in docs/native-build.md.

using Vello;
using Vello.Geometry;

// Create 800x600 render context
using var context = new RenderContext(800, 600);

// Set magenta paint
context.SetPaint(Color.Magenta);

// Draw filled rectangle
context.FillRect(Rect.FromXYWH(100, 100, 200, 150));

// Render to pixmap
using var pixmap = new Pixmap(800, 600);
context.RenderToPixmap(pixmap);

// Zero-copy pixel access
ReadOnlySpan<PremulRgba8> pixels = pixmap.GetPixels();
Console.WriteLine($"First pixel: R={pixels[0].R}, G={pixels[0].G}, B={pixels[0].B}");

Install Avalonia Host Control from NuGet:

dotnet add package Vello.Avalonia

drop reusable VelloSurface Insert and bind in XAML IVelloRenderer The implementation that drives your view logic:

<UserControl xmlns="https://github.com/avaloniaui"
             xmlns:vello="clr-namespace:Vello.Avalonia.Controls;assembly=Vello.Avalonia">
  <vello:VelloSurface Renderer="{Binding Renderer}"
                      UseMultithreadedRendering="{Binding UseMultithreadedRendering}" />
UserControl>
using Vello;
using Vello.Avalonia.Rendering;

public sealed class MotionMarkRenderer : IVelloRenderer
{
    private readonly MotionMarkScene _scene = new();

    public void Render(RenderContext context, int pixelWidth, int pixelHeight)
    {
        _scene.Render(context, pixelWidth, pixelHeight);
    }
}

The control handles render-loop scheduling, context pooling, and stride-aware blitting. WriteableBitmapS. agree FrameStatsUpdated For average FPS/frame-time telemetry when profiling high-performance scenes.

Look dotnet/samples/Vello.Samples/ For 15 complete examples:

  1. simple rectangle – basic solid color rendering
  2. linear gradient – gradient fills with extended mode
  3. radial gradient – circular gradient
  4. bezier path – drawing complex paths with curves
  5. changes – affine transformation
  6. zero-copy access – Direct pixel manipulation with spans
  7. PNG I/O – Save and load PNG images
  8. blending mode – 28 blend mode combinations
  9. stroke styles – Line joins, caps, and dashing
  10. sweep gradient – angular gradient
  11. blurred rounded rectangles – blur effect
  12. scrap – Path-based clipping
  13. text rendering – Font loading and glyph rendering
  14. masking – Alpha and Luminance Mask
  15. raster images – Image rendering with quality settings

The complete document is available in docs/ folder:

  1. Rust FFI Layer ,vello_cpu_ffi) – C-ABI wrapper around Velo_CPU
  2. p/invoke layer ,Vello.Native) – low-level .NET interop (internal)
  3. safe cover ,Vello) – high level C# API (public)
  • opaque handle For rust types (prevents abuse)
  • blowable structures for geometry (zero marshalling cost)
  • libraryimport For source-generated P/Invocation
  • Duration For zero-copy pixel access
  • idisposable for deterministic cleaning

Zero-allocation rendering (steps 1 and 2) ✅

All important rendering paths now supported zero allocation render using Span And stackalloc,

Step 1: Text and gradient rendering

  • text rendering (≤256 characters): 0 allocation (was 5 per call)
  • slope (≤32 stops): 0 allocation (was 1 per call)
  • glyph rendering (≤256 glyphs): 0 allocation (was 1 per call)
// Zero-allocation text rendering
context.FillText(font, 48.0f, "Hello, World!", 10, 50);  // 0 allocations

// Zero-allocation gradient rendering
Span<ColorStop> stops = stackalloc ColorStop[3];
stops[0] = new ColorStop(0.0f, Color.Red);
stops[1] = new ColorStop(0.5f, Color.Green);
stops[2] = new ColorStop(1.0f, Color.Blue);
context.SetPaintLinearGradient(0, 0, 400, 300, stops);  // 0 allocations

// Zero-allocation glyph conversion
Span<Glyph> glyphs = stackalloc Glyph[text.Length];
int count = font.TextToGlyphs(text, glyphs);  // 0 allocations
context.FillGlyphs(font, 48.0f, glyphs.Slice(0, count));  // 0 allocations

Step 2: PNG I/O and pixelmap operations

  • Loading PNG:zero copy from ReadOnlySpan sources say
  • png export:try-pattern with pre-allocated buffers
  • pixel byte access:zero-copy direct memory access
// Zero-copy PNG loading from memory
ReadOnlySpan<byte> pngData = File.ReadAllBytes("image.png");
using var pixmap = Pixmap.FromPng(pngData);  // Zero-copy

// Zero-allocation PNG export with pre-allocated buffer
int size = pixmap.GetPngSize();
Span<byte> buffer = stackalloc byte[size];
if (pixmap.TryToPng(buffer, out int bytesWritten))
{
    File.WriteAllBytes("output.png", buffer.Slice(0, bytesWritten).ToArray());
}

// Zero-copy byte access to pixel data
ReadOnlySpan<byte> bytes = pixmap.GetBytes();  // Direct memory access, no copy
// Or copy to existing buffer:
Span<byte> destination = new byte[pixmap.Width * pixmap.Height * 4];
pixmap.CopyBytesTo(destination);

// Zero-copy font loading from memory
ReadOnlySpan<byte> fontData = File.ReadAllBytes("font.ttf");
using var font = new FontData(fontData);  // Zero-copy

Main performance characteristics

  • zero-copy pixel access – through direct memory access Duration
  • Blittable types – No marshalling overhead
  • SIMD optimizations – Automatic hardware detection (SSE2, AVX, AVX2, AVX512, NEON)
  • Multithreading – Configurable worker threads
  • Stackalloc – Automatic stack allocation for typical sizes, heap for large data

Example configuration:

var settings = new RenderSettings(
    level: SimdLevel.Avx2,      // Force AVX2
    numThreads: 8,               // 8 worker threads
    mode: RenderMode.OptimizeSpeed
);

using var context = new RenderContext(1920, 1080, settings);

platform 64 arm64 Situation
windows planned to
linux planned to
Mac OS planned to

Completed – ready for production

All stages of implementation have been completed:

  • ✅ Step 1: Planning and Design
  • ✅ Step 2: Rust FFI Layer (3,300+ lines)
  • ✅ Step 3: .NET Binding Layer (4,500+ lines)
  • ✅ Step 4: Core rendering methods
  • ✅ Step 5: Advanced Features (Gradient, Image, Text, Masking)
  • ✅ Step 6: Testing and Verification (85 tested, 81 active, 100% passed)
  • ✅ Step 7: Documentation

100% API coverage:All 34 RenderContext methods implemented

See docs/STATUS.md for detailed completion status.

All vello_cpu RenderContext features are fully implemented:

  • raster images – Image rendering with quality and detail modes
  • slope – Linear, Radial and Sweep gradients
  • blurred rounded rectangles – Blur effect with standard deviation
  • mixing and matching – 16 Mix Modes × 14 Compose Modes = 28 Combinations
  • scrap – Path-based clipping layers
  • masking – Alpha and Luminance Mask
  • glyph – All glyph types (CFF, Bitmap, COLRv0, COLRv1)
  • paint transforms – Affine transformation for paint
  • fill rules – Nonzero and evenodd winding rules
  • strokes – width, joint, cap, miter border, dashing

See docs/API_COVERAGE.md for a complete method-by-method comparison.

Contributions welcome! The implementation is complete, but improvements are always appreciated.

This project is licensed under Apache-2.0 or MIT, which matches the Velo project.

Built by the Linebender community on top of Velo Spars strips.



Leave a Comment