166 lines
4.7 KiB
C++
166 lines
4.7 KiB
C++
/*
|
|
* Copyright (C) 2026 Behdad Esfahbod
|
|
*
|
|
* This is part of HarfBuzz, a text shaping library.
|
|
*
|
|
* Permission is hereby granted, without written agreement and without
|
|
* license or royalty fees, to use, copy, modify, and distribute this
|
|
* software and its documentation for any purpose, provided that the
|
|
* above copyright notice and the following two paragraphs appear in
|
|
* all copies of this software.
|
|
*
|
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
|
* DAMAGE.
|
|
*
|
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
|
*
|
|
* Author(s): Behdad Esfahbod
|
|
*/
|
|
|
|
#include "hb-benchmark.hh"
|
|
|
|
#include <hb-gpu.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"
|
|
|
|
static struct test_input_t
|
|
{
|
|
const char *font_path;
|
|
} default_tests[] =
|
|
{
|
|
{SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf"},
|
|
{SUBSET_FONT_BASE_PATH "SourceSansPro-Regular.otf"},
|
|
{SUBSET_FONT_BASE_PATH "AdobeVFPrototype.otf"},
|
|
{SUBSET_FONT_BASE_PATH "Comfortaa-Regular-new.ttf"},
|
|
{SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf"},
|
|
{SUBSET_FONT_BASE_PATH "NotoSerifMyanmar-Regular.otf"},
|
|
};
|
|
|
|
static test_input_t *tests = default_tests;
|
|
static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
|
|
|
|
static void BM_GpuDrawEncode (benchmark::State &state,
|
|
const test_input_t &test_input)
|
|
{
|
|
hb_face_t *face = hb_benchmark_face_create_from_file_or_fail (test_input.font_path, 0);
|
|
if (!face)
|
|
{
|
|
state.SkipWithError ("Failed to open font file");
|
|
return;
|
|
}
|
|
|
|
hb_font_t *font = hb_font_create (face);
|
|
unsigned num_glyphs = hb_face_get_glyph_count (face);
|
|
hb_gpu_draw_t *draw = hb_gpu_draw_create_or_fail ();
|
|
assert (draw);
|
|
|
|
for (auto _ : state)
|
|
for (unsigned gid = 0; gid < num_glyphs; ++gid)
|
|
{
|
|
hb_gpu_draw_clear (draw);
|
|
hb_gpu_draw_glyph (draw, font, gid);
|
|
hb_blob_t *blob = hb_gpu_draw_encode (draw, nullptr);
|
|
hb_gpu_draw_recycle_blob (draw, blob);
|
|
}
|
|
|
|
hb_gpu_draw_destroy (draw);
|
|
hb_font_destroy (font);
|
|
hb_face_destroy (face);
|
|
}
|
|
|
|
static void BM_GpuPaintEncode (benchmark::State &state,
|
|
const test_input_t &test_input)
|
|
{
|
|
hb_face_t *face = hb_benchmark_face_create_from_file_or_fail (test_input.font_path, 0);
|
|
if (!face)
|
|
{
|
|
state.SkipWithError ("Failed to open font file");
|
|
return;
|
|
}
|
|
|
|
hb_font_t *font = hb_font_create (face);
|
|
unsigned num_glyphs = hb_face_get_glyph_count (face);
|
|
hb_gpu_paint_t *paint = hb_gpu_paint_create_or_fail ();
|
|
assert (paint);
|
|
|
|
for (auto _ : state)
|
|
for (unsigned gid = 0; gid < num_glyphs; ++gid)
|
|
{
|
|
hb_gpu_paint_glyph (paint, font, gid);
|
|
hb_blob_t *blob = hb_gpu_paint_encode (paint, nullptr);
|
|
if (blob)
|
|
hb_gpu_paint_recycle_blob (paint, blob);
|
|
}
|
|
|
|
hb_gpu_paint_destroy (paint);
|
|
hb_font_destroy (font);
|
|
hb_face_destroy (face);
|
|
}
|
|
|
|
static const char *font_file = nullptr;
|
|
|
|
static GOptionEntry entries[] =
|
|
{
|
|
{"font-file", 0, 0, G_OPTION_ARG_STRING, &font_file, "Font file-path to benchmark", "FONTFILE"},
|
|
{nullptr}
|
|
};
|
|
|
|
int main (int argc, char **argv)
|
|
{
|
|
benchmark::Initialize (&argc, argv);
|
|
|
|
GOptionContext *context = g_option_context_new ("");
|
|
g_option_context_set_summary (context, "Benchmark GPU glyph encoding");
|
|
g_option_context_add_main_entries (context, entries, nullptr);
|
|
g_option_context_parse (context, &argc, &argv, nullptr);
|
|
g_option_context_free (context);
|
|
|
|
argc--;
|
|
argv++;
|
|
if (!font_file && argc)
|
|
{
|
|
font_file = *argv;
|
|
argc--;
|
|
argv++;
|
|
}
|
|
|
|
if (font_file)
|
|
{
|
|
num_tests = 1;
|
|
tests = (test_input_t *) calloc (num_tests, sizeof (test_input_t));
|
|
tests[0].font_path = font_file;
|
|
}
|
|
|
|
for (unsigned i = 0; i < num_tests; i++)
|
|
{
|
|
auto &test_input = tests[i];
|
|
const char *base = strrchr (test_input.font_path, '/');
|
|
base = base ? base + 1 : test_input.font_path;
|
|
|
|
char draw_name[1024] = "BM_GpuDrawEncode/";
|
|
strcat (draw_name, base);
|
|
benchmark::RegisterBenchmark (draw_name, BM_GpuDrawEncode, test_input)
|
|
->Unit (benchmark::kMillisecond);
|
|
|
|
char paint_name[1024] = "BM_GpuPaintEncode/";
|
|
strcat (paint_name, base);
|
|
benchmark::RegisterBenchmark (paint_name, BM_GpuPaintEncode, test_input)
|
|
->Unit (benchmark::kMillisecond);
|
|
}
|
|
|
|
benchmark::RunSpecifiedBenchmarks ();
|
|
benchmark::Shutdown ();
|
|
|
|
if (tests != default_tests)
|
|
free (tests);
|
|
}
|