mirror of https://github.com/aseprite/aseprite.git
Add image_benchmark
This commit is contained in:
parent
8d4c4857ee
commit
20b11a0fd3
|
@ -0,0 +1,170 @@
|
||||||
|
// Aseprite Document Library
|
||||||
|
// Copyright (c) 2024 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// This file is released under the terms of the MIT license.
|
||||||
|
// Read LICENSE.txt for more information.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "doc/algorithm/random_image.h"
|
||||||
|
#include "doc/image.h"
|
||||||
|
#include "doc/image_ref.h"
|
||||||
|
|
||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
|
||||||
|
using namespace doc;
|
||||||
|
|
||||||
|
void BM_ForXYGetPixel(benchmark::State& state)
|
||||||
|
{
|
||||||
|
const auto pf = (PixelFormat)state.range(0);
|
||||||
|
const int w = state.range(1);
|
||||||
|
const int h = state.range(2);
|
||||||
|
ImageRef img(Image::create(pf, w, h));
|
||||||
|
doc::algorithm::random_image(img.get());
|
||||||
|
for (auto _ : state) {
|
||||||
|
color_t c = 0;
|
||||||
|
for (int y = 0; y < h; ++y) {
|
||||||
|
for (int x = 0; x < w; ++x) {
|
||||||
|
c += img->getPixel(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
benchmark::DoNotOptimize(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BM_ForEachPixel(benchmark::State& state)
|
||||||
|
{
|
||||||
|
const auto pf = (PixelFormat)state.range(0);
|
||||||
|
const int w = state.range(1);
|
||||||
|
const int h = state.range(2);
|
||||||
|
ImageRef img(Image::create(pf, w, h));
|
||||||
|
doc::algorithm::random_image(img.get());
|
||||||
|
for (auto _ : state) {
|
||||||
|
color_t c = 0;
|
||||||
|
auto func = [&c](color_t u) { c += u; };
|
||||||
|
switch (pf) {
|
||||||
|
case IMAGE_RGB: for_each_pixel<RgbTraits>(img.get(), func); break;
|
||||||
|
case IMAGE_GRAYSCALE: for_each_pixel<GrayscaleTraits>(img.get(), func); break;
|
||||||
|
case IMAGE_INDEXED: for_each_pixel<IndexedTraits>(img.get(), func); break;
|
||||||
|
case IMAGE_BITMAP: for_each_pixel<BitmapTraits>(img.get(), func); break;
|
||||||
|
case IMAGE_TILEMAP: for_each_pixel<TilemapTraits>(img.get(), func); break;
|
||||||
|
}
|
||||||
|
benchmark::DoNotOptimize(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BM_ForXYGetPixelFast(benchmark::State& state)
|
||||||
|
{
|
||||||
|
const auto pf = (PixelFormat)state.range(0);
|
||||||
|
const int w = state.range(1);
|
||||||
|
const int h = state.range(2);
|
||||||
|
ImageRef img(Image::create(pf, w, h));
|
||||||
|
doc::algorithm::random_image(img.get());
|
||||||
|
for (auto _ : state) {
|
||||||
|
color_t c = 0;
|
||||||
|
switch (pf) {
|
||||||
|
case IMAGE_RGB:
|
||||||
|
for (int y = 0; y < h; ++y) {
|
||||||
|
for (int x = 0; x < w; ++x) {
|
||||||
|
c += get_pixel_fast<RgbTraits>(img.get(), x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IMAGE_GRAYSCALE:
|
||||||
|
for (int y = 0; y < h; ++y) {
|
||||||
|
for (int x = 0; x < w; ++x) {
|
||||||
|
c += get_pixel_fast<GrayscaleTraits>(img.get(), x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IMAGE_INDEXED:
|
||||||
|
for (int y = 0; y < h; ++y) {
|
||||||
|
for (int x = 0; x < w; ++x) {
|
||||||
|
c += get_pixel_fast<IndexedTraits>(img.get(), x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IMAGE_BITMAP:
|
||||||
|
for (int y = 0; y < h; ++y) {
|
||||||
|
for (int x = 0; x < w; ++x) {
|
||||||
|
c += get_pixel_fast<BitmapTraits>(img.get(), x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
benchmark::DoNotOptimize(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Func>
|
||||||
|
void dispatch_by_pixel_format(Image* image, const ReadIterator& it, Func func)
|
||||||
|
{
|
||||||
|
switch (image->pixelFormat()) {
|
||||||
|
case IMAGE_RGB: func(it.addr32()); break;
|
||||||
|
case IMAGE_GRAYSCALE: func(it.addr16()); break;
|
||||||
|
case IMAGE_INDEXED: func(it.addr8()); break;
|
||||||
|
#if !DOC_USE_BITMAP_AS_1BPP
|
||||||
|
case IMAGE_BITMAP: func(it.addr8()); break;
|
||||||
|
#endif
|
||||||
|
case IMAGE_TILEMAP: func(it.addr32()); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BM_ReadIterator(benchmark::State& state)
|
||||||
|
{
|
||||||
|
const auto pf = (PixelFormat)state.range(0);
|
||||||
|
const int w = state.range(1);
|
||||||
|
const int h = state.range(2);
|
||||||
|
ImageRef img(Image::create(pf, w, h));
|
||||||
|
doc::algorithm::random_image(img.get());
|
||||||
|
for (auto _ : state) {
|
||||||
|
auto it = img->readArea(img->bounds());
|
||||||
|
while (it.nextLine()) {
|
||||||
|
dispatch_by_pixel_format(img.get(), it, [w](auto addr) {
|
||||||
|
color_t c = 0;
|
||||||
|
for (int x = 0; x < w; ++x, ++addr) {
|
||||||
|
c += *addr;
|
||||||
|
}
|
||||||
|
benchmark::DoNotOptimize(c);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFARGS() \
|
||||||
|
->Args({ IMAGE_RGB, 1024, 1024 }) \
|
||||||
|
->Args({ IMAGE_GRAYSCALE, 1024, 1024 }) \
|
||||||
|
->Args({ IMAGE_INDEXED, 1024, 1024 }) \
|
||||||
|
->Args({ IMAGE_BITMAP, 1024, 1024 })
|
||||||
|
|
||||||
|
#if DOC_USE_BITMAP_AS_1BPP
|
||||||
|
|
||||||
|
// In this case we avoid IMAGE_BITMAP as its iterator goes through
|
||||||
|
// bits instead of bytes, i.e. a pixel cannot be addressed with a
|
||||||
|
// memory pointer.
|
||||||
|
#define DEFARGS_ADDRESSABLE_ONLY() \
|
||||||
|
->Args({ IMAGE_RGB, 1024, 1024 }) \
|
||||||
|
->Args({ IMAGE_GRAYSCALE, 1024, 1024 }) \
|
||||||
|
->Args({ IMAGE_INDEXED, 1024, 1024 })
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define DEFARGS_ADDRESSABLE_ONLY DEFARGS
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BENCHMARK(BM_ForXYGetPixel)
|
||||||
|
DEFARGS()->UseRealTime();
|
||||||
|
|
||||||
|
BENCHMARK(BM_ForEachPixel)
|
||||||
|
DEFARGS()->UseRealTime();
|
||||||
|
|
||||||
|
BENCHMARK(BM_ForXYGetPixelFast)
|
||||||
|
DEFARGS()->UseRealTime();
|
||||||
|
|
||||||
|
BENCHMARK(BM_ReadIterator)
|
||||||
|
DEFARGS_ADDRESSABLE_ONLY()->UseRealTime();
|
||||||
|
|
||||||
|
BENCHMARK_MAIN();
|
Loading…
Reference in New Issue