#include <algorithm>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
struct demo_entry {
const char* name;
int (*fn)(unsigned, unsigned, const std::vector<double>&, const char*);
};
#define DEMO(n) int render_##n(unsigned, unsigned, const std::vector<double>&, const char*);
DEMO(simple_line)
DEMO(perspective)
DEMO(conv_dash_marker)
DEMO(lion_outline)
DEMO(rasterizers2)
DEMO(image_perspective)
DEMO(image_transforms)
DEMO(image_filters)
DEMO(compositing2)
DEMO(flash_rasterizer)
DEMO(flash_rasterizer2)
#undef DEMO
static const demo_entry g_demos[] = {
{"simple_line", render_simple_line},
{"perspective", render_perspective},
{"conv_dash_marker", render_conv_dash_marker},
{"lion_outline", render_lion_outline},
{"rasterizers2", render_rasterizers2},
{"image_perspective", render_image_perspective},
{"image_transforms", render_image_transforms},
{"image_filters", render_image_filters},
{"compositing2", render_compositing2},
{"flash_rasterizer", render_flash_rasterizer},
{"flash_rasterizer2", render_flash_rasterizer2},
};
static const demo_entry* find_demo(const char* name) {
for (const auto& d : g_demos) {
if (strcmp(name, d.name) == 0) return &d;
}
return nullptr;
}
static int run_bench(int argc, char** argv) {
if (argc < 5) {
fprintf(stderr, "Usage: %s bench <demo> <width> <height> [params...] [--iters N]\n", argv[0]);
return 2;
}
const char* demo = argv[2];
unsigned width = (unsigned)strtoul(argv[3], nullptr, 10);
unsigned height = (unsigned)strtoul(argv[4], nullptr, 10);
std::vector<double> params;
int iters = 10;
for (int i = 5; i < argc; ++i) {
if (strcmp(argv[i], "--iters") == 0 && i + 1 < argc) {
iters = (int)strtol(argv[i + 1], nullptr, 10);
++i;
} else {
params.push_back(strtod(argv[i], nullptr));
}
}
if (iters < 1) {
fprintf(stderr, "--iters must be at least 1\n");
return 2;
}
const demo_entry* d = find_demo(demo);
if (!d) {
fprintf(stderr, "Unknown demo: %s\n", demo);
return 1;
}
volatile int sink = 0;
for (int w = 0; w < 2; ++w) sink += d->fn(width, height, params, nullptr);
std::vector<double> times;
times.reserve((size_t)iters);
for (int it = 0; it < iters; ++it) {
auto start = std::chrono::steady_clock::now();
int rc = d->fn(width, height, params, nullptr);
auto end = std::chrono::steady_clock::now();
sink += rc;
double ms = std::chrono::duration<double, std::milli>(end - start).count();
times.push_back(ms);
printf("iter %3d: %.2f ms\n", it + 1, ms);
}
(void)sink;
std::vector<double> sorted = times;
std::sort(sorted.begin(), sorted.end());
double best = sorted.front();
size_t n = sorted.size();
double median = (n % 2 == 1) ? sorted[n / 2] : (sorted[n / 2 - 1] + sorted[n / 2]) / 2.0;
double sum = 0.0;
for (double t : times) sum += t;
double mean = sum / (double)n;
printf("best= %.2f ms median= %.2f ms mean= %.2f ms\n", best, median, mean);
return 0;
}
int main(int argc, char** argv) {
if (argc >= 2 && strcmp(argv[1], "bench") == 0) {
return run_bench(argc, argv);
}
if (argc < 5) {
fprintf(stderr, "Usage: %s <demo> <width> <height> <output.raw> [params...]\n", argv[0]);
fprintf(stderr, "Demos:");
for (const auto& d : g_demos) fprintf(stderr, " %s", d.name);
fprintf(stderr, "\n");
return 2;
}
const char* demo = argv[1];
unsigned width = (unsigned)strtoul(argv[2], nullptr, 10);
unsigned height = (unsigned)strtoul(argv[3], nullptr, 10);
const char* out = argv[4];
std::vector<double> params;
for (int i = 5; i < argc; ++i) params.push_back(strtod(argv[i], nullptr));
for (const auto& d : g_demos) {
if (strcmp(demo, d.name) == 0) {
return d.fn(width, height, params, out);
}
}
fprintf(stderr, "Unknown demo: %s\n", demo);
return 1;
}