You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Component shuffling for RGB(A)-like formats with SIMD Intrinsics #1354
We need cheap bulk-conversion between the following formats: Argb32, Bgra32, Rgba32, Bgr24, Rgb24
We are especially interested in Rgb24, Bgr24 <=> Rgba32. I'm having sweat dreams about a community PR dealing with this problem. Should be easy for anyone having basic knowledge of System.Runtime.Intrinsics.
changed the title [-]Component shuffling for RGB(A) like formats with SIMD Intrinsics[/-][+]Component shuffling for RGB(A)-like formats with SIMD Intrinsics[/+]on Sep 16, 2020
Which means that the last two steps will be done automatically, if I'm not missing anything. Can't wait to see the Vector4 <=> Rgb24 before/after comparison. (Which is the main goal of this issue because of the conversion steps in Jpeg decoder and ResizeProcessor.)
@antonfirsov need to add a specific benchmark for that but I know for certain that even my Rgba32 <==> Rgb24 fallback is a lot faster than the original.
@JimBobSquarePants there is one other important metric we need to check to set our expectations for #1410. Can be done by defining 2 new simple benchmark classes (baseline VS SIMD with Count = 2048):
Comparing Vector4 -> Rgba32 (baseline) to Vector4 -> Rgb24 (Jpeg decoder pipeline last step)
Comparing Rgba32 -> Vector4 (baseline) to Rgb24 -> Vector4 (Resize pipeline first step)
The smaller the difference the bigger the happiness.
Vector4 => Rgba32 is still 2.5x faster on .NET Core 3.1 than Vector4 => Rgb24.
We'd need to have a method that goes direct to be able to cut into that since the pipeline is Vector4 => Rgba32 => Rgb24. Not difficult with hardware intrinsics based on my existing code but likely not fun with the old stuff.
What I dream of is a combination of shuffle + convert.
A single pipeline step would do way too much (convert colorspace + convert to byte + pack), making it very hard to maintain the code
Ensuring that the non-HwIntrinsics path does not regress is also very expensive (The Vector<float> -> Vector<byte> conversion shall be directly integrated into the colorspace conversion code.
I'd rather suggest to do the following:
Color converters should convert and pack to a "Vector3" buffer (Span<float> of RGB components only, no padding for alpha)
Apply SimdUtils.NormalizedFloatToByteSaturate to get the Rgb24 buffer
Convert it further with PixelOperations<TPixel> if TPixel != Rgb24
=> Pro: likely still very fast, much more predictible amount of work, no regressions on old platforms
(But still a lot of work!)
Yeah... All my shuffle code has touched conversion between pixel formats only. The Vector4 pipeline remains untouched (other than a speedup for converting to/from Rgba32)
What do you mean by Color converters? The jpeg ones?
What do you mean by Color converters? The jpeg ones?
Yes I meant that.
Couldn't we pack directly into Rgb24
I think I misunderstood you on this one. I thought you want Jpeg color converters to convert directly into Rgb24, my #1354 (comment) is listing arguments against doing that.
A one-step Vector4 => Rgb24 method can help a bit, but wouldn't expect big miracle from it, choose wisely if you want to invest your time into it or not.
Activity
[-]Component shuffling for RGB(A) like formats with SIMD Intrinsics[/-][+]Component shuffling for RGB(A)-like formats with SIMD Intrinsics[/+]JimBobSquarePants commentedon Oct 26, 2020
I'm gonna have a look at this.
antonfirsov commentedon Nov 2, 2020
Btw, the
Span<Vector4> <=> Span<TPixel>conversions are delegating the (pad/slice) shuffle work toPixelOperations<TPixel>conversion methods:https://github.com/SixLabors/ImageSharp/blob/78a584e8482b052d7a9885682299e2f37518d83d/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs
Which means that the last two steps will be done automatically, if I'm not missing anything. Can't wait to see the
Vector4 <=> Rgb24before/after comparison. (Which is the main goal of this issue because of the conversion steps in Jpeg decoder and ResizeProcessor.)JimBobSquarePants commentedon Nov 2, 2020
@antonfirsov need to add a specific benchmark for that but I know for certain that even my
Rgba32 <==> Rgb24fallback is a lot faster than the original.JimBobSquarePants commentedon Nov 2, 2020
@antonfirsov Here you go!
ToVector4_Rgb24
Master
Branch
FromVector4_Rgb24
Master
Branch
JimBobSquarePants commentedon Nov 4, 2020
@antonfirsov Pushed an update that affects
FromVector4_Rgb24based on a suggestion by @Sergio0694 and It's squeezed a few more percentage performance.antonfirsov commentedon Nov 4, 2020
Looks great!
@JimBobSquarePants there is one other important metric we need to check to set our expectations for #1410. Can be done by defining 2 new simple benchmark classes (baseline VS SIMD with Count = 2048):
Vector4 -> Rgba32(baseline) toVector4 -> Rgb24(Jpeg decoder pipeline last step)Rgba32 -> Vector4(baseline) toRgb24 -> Vector4(Resize pipeline first step)The smaller the difference the bigger the happiness.
JimBobSquarePants commentedon Nov 4, 2020
Couldn't we pack directly into
Rgb24by not scaling down in the color converter and packing the planar values as bytes?JimBobSquarePants commentedon Nov 4, 2020
Vector4=>Rgba32is still 2.5x faster on .NET Core 3.1 thanVector4=>Rgb24.We'd need to have a method that goes direct to be able to cut into that since the pipeline is
Vector4=>Rgba32=>Rgb24. Not difficult with hardware intrinsics based on my existing code but likely not fun with the old stuff.What I dream of is a combination of shuffle + convert.
antonfirsov commentedon Nov 4, 2020
That's bad news :(
I don't think going
Vector4 => Rgb24is the best approach here:byte+ pack), making it very hard to maintain the codeVector<float>->Vector<byte>conversion shall be directly integrated into the colorspace conversion code.I'd rather suggest to do the following:
Vector3" buffer (Span<float>of RGB components only, no padding for alpha)SimdUtils.NormalizedFloatToByteSaturateto get theRgb24bufferPixelOperations<TPixel>ifTPixel != Rgb24=> Pro: likely still very fast, much more predictible amount of work, no regressions on old platforms
(But still a lot of work!)
JimBobSquarePants commentedon Nov 4, 2020
Yeah... All my shuffle code has touched conversion between pixel formats only. The
Vector4pipeline remains untouched (other than a speedup for converting to/fromRgba32)What do you mean by Color converters? The jpeg ones?
antonfirsov commentedon Nov 4, 2020
Yes I meant that.
I think I misunderstood you on this one. I thought you want Jpeg color converters to convert directly into
Rgb24, my #1354 (comment) is listing arguments against doing that.A one-step
Vector4 => Rgb24method can help a bit, but wouldn't expect big miracle from it, choose wisely if you want to invest your time into it or not.JimBobSquarePants commentedon Nov 16, 2020
Just realized this was still open.