Open mattleibow opened 6 years ago
I've been looking at passing Span
s to Skia in my project, where I use a lot of pooled SKPoint buffers.
I've got a class that looks like this
internal static class SkiaApiEx
{
// ...snip...
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_path_add_poly(sk_path_t cpath, IntPtr pPoints, int count, [MarshalAs(UnmanagedType.I1)] bool close);
public static void AddPoly(this SKPath path, ReadOnlySpan<SKPoint> points, bool close)
{
unsafe
{
fixed (SKPoint* p = points)
{
sk_path_add_poly(path.Handle, (IntPtr)p, points.Length, close);
}
}
}
}
Not sure if it is the right pattern idiomatically, but works wonderfully for me in my project.
This is something that we will be looking at in the future.
I suppose someone should look at that faster, as it's easy enough. I've just profiled my app and SKPoint allocations are 20% of all allocations. This would reduce allocations by 50%. Also instead of using ReadOnlySpan
I need to access the pixels of a SKBitmap. To do this I wrote these extension methods:
public static unsafe Span<byte> GetPixelSpan(this SKBitmap bitmap)
{
var ptr = SkiaApi.sk_bitmap_get_pixels(bitmap.Handle, out var length);
return new Span<byte>(ptr.ToPointer(), length.ToInt32());
}
public static unsafe Span<uint> GetPixelSpanUInt(this SKBitmap bitmap)
{
var ptr = SkiaApi.sk_bitmap_get_pixels(bitmap.Handle, out var length);
return new Span<uint>(ptr.ToPointer(), length.ToInt32());
}
// this allows something like GetPixelSpan<Foobar>()
public static unsafe Span<T> GetPixelSpan<T>(this SKBitmap bitmap)
{
var ptr = SkiaApi.sk_bitmap_get_pixels(bitmap.Handle, out var length);
return new Span<T>(ptr.ToPointer(), length.ToInt32());
}
With these methods I get a Span
of the pixels and can work with it in a safe way.
SKBitmap.Bytes
copies the whole bitmap to a new byte[]
, so this is very slow and needs more memory.
SKBitmap.GetPixels
returns an IntPtr
and needs unsafe
code to work with it.
GetPixelSpan
has none of those drawbacks.
Of course you don't need all three of those methods. The last is enough, but it enables somebody to write GetPixelSpan<Foobar>()
which does not make sense. Your choice which methods you'll use.
Description
With .NET 4.8 and .NET Core 2.1 and the like, there have been new types introduced to reduce allocations and increase performance. We should really start to have a look at this and see where/how we can make use of new things.