diff --git a/src/ImageSharp/Common/Helpers/Numerics.cs b/src/ImageSharp/Common/Helpers/Numerics.cs index 86a60704a..201500e1c 100644 --- a/src/ImageSharp/Common/Helpers/Numerics.cs +++ b/src/ImageSharp/Common/Helpers/Numerics.cs @@ -474,8 +474,10 @@ internal static class Numerics [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Premultiply(ref Vector4 source) { - Vector4 alpha = PermuteW(source); - source = WithW(source * alpha, alpha); + // Load into a local variable to prevent accessing the source from memory multiple times. + Vector4 src = source; + Vector4 alpha = PermuteW(src); + source = WithW(src * alpha, alpha); } /// diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/PremultiplyVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/PremultiplyVector4.cs index cab81cb7f..44496a249 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/PremultiplyVector4.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/PremultiplyVector4.cs @@ -25,7 +25,19 @@ public class PremultiplyVector4 } [Benchmark] - public void Premultiply() => Numerics.Premultiply(Vectors); + public void Premultiply() + { + ref Vector4 baseRef = ref MemoryMarshal.GetReference(Vectors); + + for (int i = 0; i < Vectors.Length; i++) + { + ref Vector4 v = ref Unsafe.Add(ref baseRef, i); + Numerics.Premultiply(ref v); + } + } + + [Benchmark] + public void PremultiplyBulk() => Numerics.Premultiply(Vectors); [MethodImpl(InliningOptions.ShortMethod)] private static void Premultiply(ref Vector4 source) diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/UnPremultiplyVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/UnPremultiplyVector4.cs index d653fca29..c2b371b8a 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/UnPremultiplyVector4.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/UnPremultiplyVector4.cs @@ -20,12 +20,25 @@ public class UnPremultiplyVector4 for (int i = 0; i < Vectors.Length; i++) { ref Vector4 v = ref Unsafe.Add(ref baseRef, i); + UnPremultiply(ref v); } } [Benchmark] - public void UnPremultiply() => Numerics.UnPremultiply(Vectors); + public void UnPremultiply() + { + ref Vector4 baseRef = ref MemoryMarshal.GetReference(Vectors); + + for (int i = 0; i < Vectors.Length; i++) + { + ref Vector4 v = ref Unsafe.Add(ref baseRef, i); + Numerics.UnPremultiply(ref v); + } + } + + [Benchmark] + public void UnPremultiplyBulk() => Numerics.UnPremultiply(Vectors); [MethodImpl(InliningOptions.ShortMethod)] private static void UnPremultiply(ref Vector4 source)