// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Columns; using BenchmarkDotNet.Configs; using BenchmarkDotNet.Jobs; using SixLabors.ImageSharp.Formats.Heif.Av1.Prediction; namespace SixLabors.ImageSharp.Benchmarks.Codecs.Heif; /// /// Measures frame-wide AV1 palette reconstruction at each available intrinsic tier. /// [Config(typeof(Configuration))] [MemoryDiagnoser(displayGenColumns: false)] [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] [CategoriesColumn] public class Av1PalettePredictionBenchmarks { /// /// The coded frame width, which is an exact multiple of the maximum palette block side. /// private const int Width = 1920; /// /// The coded frame height including the final padded coding-tree row for a 1080-line presentation. /// private const int Height = 1088; /// /// The maximum AV1 palette block side in samples. /// private const int BlockSize = 64; /// /// The eight-entry 8-bit palette reused by each benchmark block. /// private readonly ushort[] palette8 = [3, 37, 71, 109, 143, 181, 217, 251]; /// /// The eight-entry 12-bit palette reused by each benchmark block. /// private readonly ushort[] palette12 = [17, 509, 1001, 1493, 1985, 2477, 2969, 4095]; /// /// The decoded color-index map for one maximum-size palette block. /// private readonly byte[] colorIndexMap = new byte[BlockSize * BlockSize]; /// /// The frame-wide 8-bit reconstruction surface. /// private readonly byte[] destination8 = new byte[Width * Height]; /// /// The frame-wide 12-bit reconstruction surface. /// private readonly short[] destination12 = new short[Width * Height]; /// /// Populates a deterministic, spatially varying color-index map outside the measured traversal. /// [GlobalSetup] public void Setup() { for (int row = 0; row < BlockSize; row++) { for (int column = 0; column < BlockSize; column++) { this.colorIndexMap[(row * BlockSize) + column] = (byte)(((row * 5) + (column * 3)) & 7); } } } /// /// Measures frame-wide 8-bit palette reconstruction. /// /// The final reconstructed sample, keeping the frame output observable. [Benchmark] [BenchmarkCategory("8Bit")] public byte Predict8BitFrame() { for (int row = 0; row < Height; row += BlockSize) { for (int column = 0; column < Width; column += BlockSize) { Av1PalettePredictor.Predict(this.palette8, this.colorIndexMap, BlockSize, this.destination8.AsSpan((row * Width) + column), Width, BlockSize, BlockSize); } } return this.destination8[^1]; } /// /// Measures frame-wide 12-bit palette reconstruction. /// /// The final reconstructed sample, keeping the frame output observable. [Benchmark] [BenchmarkCategory("12Bit")] public short Predict12BitFrame() { for (int row = 0; row < Height; row += BlockSize) { for (int column = 0; column < Width; column += BlockSize) { Av1PalettePredictor.Predict(this.palette12, this.colorIndexMap, BlockSize, this.destination12.AsSpan((row * Width) + column), Width, BlockSize, BlockSize); } } return this.destination12[^1]; } /// /// Configures production-process measurements for hardware, forced Vector512, AVX2, Vector128, and scalar paths. /// public sealed class Configuration : ManualConfig { /// /// Initializes a new instance of the class. /// public Configuration() { this.AddJob(Job.ShortRun.WithId("Hardware").AsBaseline()); this.AddJob( Job.ShortRun .WithId("Vector512") .WithEnvironmentVariable("DOTNET_PreferredVectorBitWidth", "512") .WithEnvironmentVariable("COMPlus_PreferredVectorBitWidth", "512")); this.AddJob( Job.ShortRun .WithId("Avx2") .WithEnvironmentVariable("DOTNET_EnableAVX512F", "0")); this.AddJob( Job.ShortRun .WithId("Vector128") .WithEnvironmentVariable("DOTNET_EnableAVX512F", "0") .WithEnvironmentVariable("DOTNET_EnableAVX2", "0")); this.AddJob( Job.ShortRun .WithId("Scalar") .WithEnvironmentVariable("DOTNET_EnableHWIntrinsic", "0")); } } }