Browse Source

JpegColorConverter.FromYCbCrSimdAvx2 works!

af/merge-core
Anton Firszov 9 years ago
parent
commit
134fa595ed
  1. 5
      src/ImageSharp/Common/Tuples/Vector4Pair.cs
  2. 3
      src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
  3. 5
      src/ImageSharp/Formats/Jpeg/Common/Block8x8F.CopyTo.cs
  4. 5
      src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs
  5. 5
      src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs
  6. 5
      src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs
  7. 5
      src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs
  8. 5
      src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs
  9. 35
      src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs
  10. 7
      src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs
  11. 11
      src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.cs
  12. 3
      src/ImageSharp/Formats/Jpeg/Common/SizeExtensions.cs
  13. 2
      tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4.cs
  14. 4
      tests/ImageSharp.Benchmarks/Config.cs
  15. 2
      tests/ImageSharp.Benchmarks/General/ArrayCopy.cs
  16. 2
      tests/ImageSharp.Benchmarks/Image/EncodeBmpMultiple.cs
  17. 2
      tests/ImageSharp.Benchmarks/Image/Jpeg/DecodeJpeg.cs
  18. 2
      tests/ImageSharp.Benchmarks/Image/Jpeg/DecodeJpegMultiple.cs
  19. 2
      tests/ImageSharp.Benchmarks/Image/Jpeg/EncodeJpegMultiple.cs
  20. 62
      tests/ImageSharp.Benchmarks/Image/Jpeg/YCbCrColorConversion.cs
  21. 2
      tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs

5
src/ImageSharp/Common/Tuples/Vector4Pair.cs

@ -71,5 +71,10 @@ namespace SixLabors.ImageSharp.Common.Tuples
v *= new Vector<float>(1 / 255f);
self = v;
}
public override string ToString()
{
return $"{this.A}, {this.B}";
}
}
}

3
src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;

5
src/ImageSharp/Formats/Jpeg/Common/Block8x8F.CopyTo.cs

@ -1,4 +1,7 @@
using System.Numerics;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;

5
src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs

@ -1,4 +1,7 @@
using System;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters

5
src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs

@ -1,4 +1,7 @@
using System;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters

5
src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs

@ -1,4 +1,7 @@
using System;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters

5
src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs

@ -1,4 +1,7 @@
using System;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters

5
src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs

@ -1,4 +1,7 @@
using System;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Common.Tuples;

35
src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCr.cs → src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs

@ -1,8 +1,12 @@
using System;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Common.Tuples;
// ReSharper disable ImpureMethodCallOnReadonlyValueField
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
@ -14,7 +18,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters
{
}
public static bool IsAvailable => Vector.IsHardwareAccelerated && Vector<float>.Count == 8;
public static bool IsAvailable => Vector.IsHardwareAccelerated && SimdUtils.IsAvx2CompatibleArchitecture;
public override void ConvertToRGBA(ComponentValues values, Span<Vector4> result)
{
@ -56,6 +60,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters
// Walking 8 elements at one step:
int n = result.Length / 8;
var rr = default(Vector4Pair);
var gg = default(Vector4Pair);
var bb = default(Vector4Pair);
ref Vector<float> rrRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref rr);
ref Vector<float> ggRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref gg);
ref Vector<float> bbRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref bb);
var scale = new Vector<float>(1 / 255f);
for (int i = 0; i < n; i++)
{
// y = yVals[i];
@ -73,15 +87,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters
Vector<float> g = y - (cb * new Vector<float>(0.344136F)) - (cr * new Vector<float>(0.714136F));
Vector<float> b = y + (cb * new Vector<float>(1.772F));
// Vector<float> has no .Clamp(), need to switch to Vector4 for the next operation:
// TODO: Is it worth to use Vector<float> at all?
Vector4Pair rr = Unsafe.As<Vector<float>, Vector4Pair>(ref r);
Vector4Pair gg = Unsafe.As<Vector<float>, Vector4Pair>(ref g);
Vector4Pair bb = Unsafe.As<Vector<float>, Vector4Pair>(ref b);
r = r.FastRound();
g = g.FastRound();
b = b.FastRound();
r *= scale;
g *= scale;
b *= scale;
rr.RoundAndDownscaleAvx2();
gg.RoundAndDownscaleAvx2();
bb.RoundAndDownscaleAvx2();
rrRefAsVector = r;
ggRefAsVector = g;
bbRefAsVector = b;
// Collect (r0,r1...r8) (g0,g1...g8) (b0,b1...b8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order:
ref Vector4Octet destination = ref Unsafe.Add(ref resultBase, i);

7
src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs

@ -1,11 +1,14 @@
using System;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
{
internal class FromYccK : ColorConverters.JpegColorConverter
internal class FromYccK : JpegColorConverter
{
public FromYccK()
: base(JpegColorSpace.Ycck)

11
src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.Linq;
@ -17,7 +20,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters
/// </summary>
private static readonly JpegColorConverter[] Converters =
{
new FromYCbCrSimd(), new FromYccK(), new FromCmyk(), new FromGrayScale(), new FromRgb()
GetYCbCrConverter(), new FromYccK(), new FromCmyk(), new FromGrayScale(), new FromRgb()
};
/// <summary>
@ -54,6 +57,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters
/// <param name="result">The destination buffer of <see cref="Vector4"/> values</param>
public abstract void ConvertToRGBA(ComponentValues values, Span<Vector4> result);
/// <summary>
/// Returns the <see cref="JpegColorConverter"/> for the YCbCr colorspace that matches the current CPU architecture.
/// </summary>
private static JpegColorConverter GetYCbCrConverter() =>
FromYCbCrSimdAvx2.IsAvailable ? (JpegColorConverter)new FromYCbCrSimdAvx2() : new FromYCbCrSimd();
/// <summary>
/// A stack-only struct to reference the input buffers using <see cref="ReadOnlySpan{T}"/>-s.
/// </summary>

3
src/ImageSharp/Formats/Jpeg/Common/SizeExtensions.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using SixLabors.Primitives;

2
tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Color.Bulk
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
[Config(typeof(Config.Short))]
[Config(typeof(Config.ShortClr))]
public abstract class PackFromVector4<TPixel>
where TPixel : struct, IPixel<TPixel>
{

4
tests/ImageSharp.Benchmarks/Config.cs

@ -17,9 +17,9 @@ namespace SixLabors.ImageSharp.Benchmarks
this.Add(new BenchmarkDotNet.Diagnosers.MemoryDiagnoser());
}
public class Short : Config
public class ShortClr : Config
{
public Short()
public ShortClr()
{
this.Add(
Job.Clr.WithLaunchCount(1)

2
tests/ImageSharp.Benchmarks/General/ArrayCopy.cs

@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General
using BenchmarkDotNet.Attributes;
[Config(typeof(Config.Short))]
[Config(typeof(Config.ShortClr))]
public class ArrayCopy
{
[Params(10, 100, 1000, 10000)]

2
tests/ImageSharp.Benchmarks/Image/EncodeBmpMultiple.cs

@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Image
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
[Config(typeof(Config.Short))]
[Config(typeof(Config.ShortClr))]
public class EncodeBmpMultiple : MultiImageBenchmarkBase.WithImagesPreloaded
{
protected override IEnumerable<string> InputImageSubfoldersOrFiles => new[] { "Bmp/", "Jpg/baseline" };

2
tests/ImageSharp.Benchmarks/Image/Jpeg/DecodeJpeg.cs

@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Image.Jpeg
using CoreSize = SixLabors.Primitives.Size;
[Config(typeof(Config.Short))]
[Config(typeof(Config.ShortClr))]
public class DecodeJpeg : BenchmarkBase
{
private byte[] jpegBytes;

2
tests/ImageSharp.Benchmarks/Image/Jpeg/DecodeJpegMultiple.cs

@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Image.Jpeg
using CoreImage = SixLabors.ImageSharp.Image;
[Config(typeof(Config.Short))]
[Config(typeof(Config.ShortClr))]
public class DecodeJpegMultiple : MultiImageBenchmarkBase
{
protected override IEnumerable<string> InputImageSubfoldersOrFiles => new[]

2
tests/ImageSharp.Benchmarks/Image/Jpeg/EncodeJpegMultiple.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Image.Jpeg
using SixLabors.ImageSharp.Formats.Jpeg;
[Config(typeof(Config.Short))] // It's long enough to iterate through multiple files
[Config(typeof(Config.ShortClr))] // It's long enough to iterate through multiple files
public class EncodeJpegMultiple : MultiImageBenchmarkBase.WithImagesPreloaded
{
protected override IEnumerable<string> InputImageSubfoldersOrFiles => new[] { "Bmp/", "Jpg/baseline" };

62
tests/ImageSharp.Benchmarks/Image/Jpeg/YCbCrColorConversion.cs

@ -1,15 +1,64 @@
namespace SixLabors.ImageSharp.Benchmarks.Image.Jpeg
{
using System;
using System.Numerics;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder;
using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters;
using SixLabors.ImageSharp.Memory;
using JpegColorConverter = SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters.JpegColorConverter;
[Config(typeof(Config.ShortClr))]
public class YCbCrColorConversion
{
private static JpegColorConverter.ComponentValues CreateRandomValues(
private Buffer2D<float>[] input;
private Vector4[] output;
public const int Count = 64;
[GlobalSetup]
public void Setup()
{
this.input = CreateRandomValues(3, Count);
this.output = new Vector4[Count];
}
[GlobalCleanup]
public void Cleanup()
{
foreach (Buffer2D<float> buffer in this.input)
{
buffer.Dispose();
}
}
[Benchmark(Baseline = true)]
public void Scalar()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
JpegColorConverter.FromYCbCrBasic.ConvertCore(values, this.output);
}
[Benchmark]
public void SimdVector4()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
JpegColorConverter.FromYCbCrSimd.ConvertCore(values, this.output);
}
[Benchmark]
public void SimdAvx2()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
JpegColorConverter.FromYCbCrSimdAvx2.ConvertCore(values, this.output);
}
private static Buffer2D<float>[] CreateRandomValues(
int componentCount,
int inputBufferLength,
float minVal = 0f,
@ -29,8 +78,9 @@
// no need to dispose when buffer is not array owner
buffers[i] = new Buffer2D<float>(values, values.Length, 1);
}
return new JpegColorConverter.ComponentValues(buffers, 0);
}
return buffers;
}
}
}

2
tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs

@ -89,6 +89,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
return;
}
//JpegColorConverter.FromYCbCrSimdAvx2.LogPlz = s => this.Output.WriteLine(s);
ValidateConversion(
new JpegColorConverter.FromYCbCrSimdAvx2(),
3,

Loading…
Cancel
Save