aboutsummaryrefslogtreecommitdiffhomepage
path: root/bench/benchmain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'bench/benchmain.cpp')
-rw-r--r--bench/benchmain.cpp1000
1 files changed, 329 insertions, 671 deletions
diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp
index 472d4b95dc..289d5cb0a2 100644
--- a/bench/benchmain.cpp
+++ b/bench/benchmain.cpp
@@ -6,47 +6,37 @@
* found in the LICENSE file.
*/
-
-#include "BenchTimer.h"
-
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrContextFactory.h"
-#include "gl/GrGLDefines.h"
#include "GrRenderTarget.h"
#include "SkGpuDevice.h"
+#include "gl/GrGLDefines.h"
#else
class GrContext;
#endif // SK_SUPPORT_GPU
+#include "BenchTimer.h"
#include "SkBenchLogger.h"
#include "SkBenchmark.h"
#include "SkBitmapDevice.h"
#include "SkCanvas.h"
#include "SkCommandLineFlags.h"
#include "SkDeferredCanvas.h"
-#include "SkColorPriv.h"
#include "SkGraphics.h"
#include "SkImageEncoder.h"
-#include "SkNWayCanvas.h"
+#include "SkOSFile.h"
#include "SkPicture.h"
#include "SkString.h"
-#include "SkTArray.h"
-#include "TimerData.h"
-
-enum benchModes {
- kNormal_benchModes,
- kDeferred_benchModes,
- kDeferredSilent_benchModes,
- kRecord_benchModes,
- kPictureRecord_benchModes
-};
-#ifdef SK_DEBUG
-static const bool kDebugOnly = true;
-#else
-static const bool kDebugOnly = false;
-#endif
+enum BenchMode {
+ kNormal_BenchMode,
+ kDeferred_BenchMode,
+ kDeferredSilent_BenchMode,
+ kRecord_BenchMode,
+ kPictureRecord_BenchMode
+};
+const char* BenchMode_Name[] = { "normal", "deferred", "deferredSilent", "record", "picturerecord" };
///////////////////////////////////////////////////////////////////////////////
@@ -58,43 +48,21 @@ static void erase(SkBitmap& bm) {
}
}
-#if 0
-static bool equal(const SkBitmap& bm1, const SkBitmap& bm2) {
- if (bm1.width() != bm2.width() ||
- bm1.height() != bm2.height() ||
- bm1.config() != bm2.config()) {
- return false;
- }
-
- size_t pixelBytes = bm1.width() * bm1.bytesPerPixel();
- for (int y = 0; y < bm1.height(); y++) {
- if (memcmp(bm1.getAddr(0, y), bm2.getAddr(0, y), pixelBytes)) {
- return false;
- }
- }
- return true;
-}
-#endif
-
class Iter {
public:
- Iter(void* param) {
- fBench = BenchRegistry::Head();
- fParam = param;
- }
+ Iter() : fBench(BenchRegistry::Head()) {}
SkBenchmark* next() {
if (fBench) {
BenchRegistry::Factory f = fBench->factory();
fBench = fBench->next();
- return f(fParam);
+ return f(NULL);
}
return NULL;
}
private:
const BenchRegistry* fBench;
- void* fParam;
};
class AutoPrePostDraw {
@@ -144,13 +112,12 @@ static void saveFile(const char name[], const char config[], const char dir[],
}
}
- SkString str;
- make_filename(name, &str);
- str.appendf("_%s.png", config);
- str.prepend(dir);
- ::remove(str.c_str());
- SkImageEncoder::EncodeFile(str.c_str(), copy, SkImageEncoder::kPNG_Type,
- 100);
+ SkString filename;
+ make_filename(name, &filename);
+ filename.appendf("_%s.png", config);
+ SkString path = SkOSPath::SkPathJoin(dir, filename.c_str());
+ ::remove(path.c_str());
+ SkImageEncoder::EncodeFile(path.c_str(), copy, SkImageEncoder::kPNG_Type, 100);
}
static void performClip(SkCanvas* canvas, int w, int h) {
@@ -184,14 +151,6 @@ static void performScale(SkCanvas* canvas, int w, int h) {
canvas->translate(-x, -y);
}
-static bool parse_bool_arg(char * const* argv, char* const* stop, bool* var) {
- if (argv < stop) {
- *var = atoi(*argv) != 0;
- return true;
- }
- return false;
-}
-
enum Backend {
kNonRendering_Backend,
kRaster_Backend,
@@ -237,111 +196,82 @@ static SkBaseDevice* make_device(SkBitmap::Config config, const SkIPoint& size,
#if SK_SUPPORT_GPU
GrContextFactory gContextFactory;
typedef GrContextFactory::GLContextType GLContextType;
-static const GLContextType kDontCareGLCtxType = GrContextFactory::kNative_GLContextType;
+static const GLContextType kNative = GrContextFactory::kNative_GLContextType;
+#if SK_ANGLE
+static const GLContextType kANGLE = GrContextFactory::kANGLE_GLContextType;
+#else
+static const GLContextType kANGLE = kNative;
+#endif
+static const GLContextType kDebug = GrContextFactory::kDebug_GLContextType;
+static const GLContextType kNull = GrContextFactory::kNull_GLContextType;
#else
typedef int GLContextType;
-static const GLContextType kDontCareGLCtxType = 0;
+static const GLContextType kNative = 0, kANGLE = 0, kDebug = 0, kNull = 0;
+#endif
+
+#ifdef SK_DEBUG
+static const bool kIsDebug = true;
+#else
+static const bool kIsDebug = false;
#endif
-static const struct {
- SkBitmap::Config fConfig;
- const char* fName;
- int fSampleCnt;
- Backend fBackend;
- GLContextType fContextType;
- bool fRunByDefault;
+static const struct Config {
+ SkBitmap::Config config;
+ const char* name;
+ int sampleCount;
+ Backend backend;
+ GLContextType contextType;
+ bool runByDefault;
} gConfigs[] = {
- { SkBitmap::kNo_Config, "NONRENDERING", 0, kNonRendering_Backend, kDontCareGLCtxType, true },
- { SkBitmap::kARGB_8888_Config, "8888", 0, kRaster_Backend, kDontCareGLCtxType, true },
- { SkBitmap::kRGB_565_Config, "565", 0, kRaster_Backend, kDontCareGLCtxType, true },
+ { SkBitmap::kNo_Config, "NONRENDERING", 0, kNonRendering_Backend, kNative, true},
+ { SkBitmap::kARGB_8888_Config, "8888", 0, kRaster_Backend, kNative, true},
+ { SkBitmap::kRGB_565_Config, "565", 0, kRaster_Backend, kNative, true},
#if SK_SUPPORT_GPU
- { SkBitmap::kARGB_8888_Config, "GPU", 0, kGPU_Backend, GrContextFactory::kNative_GLContextType, true },
- { SkBitmap::kARGB_8888_Config, "MSAA4", 4, kGPU_Backend, GrContextFactory::kNative_GLContextType, false },
- { SkBitmap::kARGB_8888_Config, "MSAA16", 16, kGPU_Backend, GrContextFactory::kNative_GLContextType, false },
+ { SkBitmap::kARGB_8888_Config, "GPU", 0, kGPU_Backend, kNative, true},
+ { SkBitmap::kARGB_8888_Config, "MSAA4", 4, kGPU_Backend, kNative, false},
+ { SkBitmap::kARGB_8888_Config, "MSAA16", 16, kGPU_Backend, kNative, false},
#if SK_ANGLE
- { SkBitmap::kARGB_8888_Config, "ANGLE", 0, kGPU_Backend, GrContextFactory::kANGLE_GLContextType, true },
+ { SkBitmap::kARGB_8888_Config, "ANGLE", 0, kGPU_Backend, kANGLE, true},
#endif // SK_ANGLE
- { SkBitmap::kARGB_8888_Config, "Debug", 0, kGPU_Backend, GrContextFactory::kDebug_GLContextType, kDebugOnly },
- { SkBitmap::kARGB_8888_Config, "NULLGPU", 0, kGPU_Backend, GrContextFactory::kNull_GLContextType, true },
+ { SkBitmap::kARGB_8888_Config, "Debug", 0, kGPU_Backend, kDebug, kIsDebug},
+ { SkBitmap::kARGB_8888_Config, "NULLGPU", 0, kGPU_Backend, kNull, true},
#endif // SK_SUPPORT_GPU
};
-static int findConfig(const char config[]) {
- for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); i++) {
- if (!strcmp(config, gConfigs[i].fName)) {
- return i;
- }
- }
- return -1;
-}
-
-static void help() {
- SkString configsStr;
- static const size_t kConfigCount = SK_ARRAY_COUNT(gConfigs);
- for (size_t i = 0; i < kConfigCount; ++i) {
- configsStr.appendf("%s%s", gConfigs[i].fName, ((i == kConfigCount - 1) ? "" : "|"));
- }
-
- SkDebugf("Usage: bench [-o outDir] [--repeat nr] [--logPerIter] "
- "[--timers [wcgWC]*] [--rotate]\n"
- " [--scale] [--clip] [--min] [--forceAA 1|0] [--forceFilter 1|0]\n"
- " [--forceDither 1|0] [--forceBlend 1|0]"
-#if SK_SUPPORT_GPU
- " [--gpuCacheSize <bytes> <count>]"
-#endif
- "\n"
- " [--strokeWidth width] [--match name]\n"
- " [--mode normal|deferred|deferredSilent|record|picturerecord]\n"
- " [--config ");
- SkDebugf("%s]\n", configsStr.c_str());
- SkDebugf(" [-Dfoo bar] [--logFile filename] [-h|--help]");
- SkDebugf("\n\n");
- SkDebugf(" -o outDir : Image of each bench will be put in outDir.\n");
- SkDebugf(" --repeat nr : Each bench repeats for nr times.\n");
- SkDebugf(" --logPerIter : "
- "Log each repeat timer instead of mean, default is disabled.\n");
- SkDebugf(" --timers [wcgWC]* : "
- "Display wall, cpu, gpu, truncated wall or truncated cpu time for each bench.\n");
- SkDebugf(" --rotate : Rotate before each bench runs.\n");
- SkDebugf(" --scale : Scale before each bench runs.\n");
- SkDebugf(" --clip : Clip before each bench runs.\n");
- SkDebugf(" --min : Print the minimum times (instead of average).\n");
- SkDebugf(" --forceAA 1|0 : "
- "Enable/disable anti-aliased, default is enabled.\n");
- SkDebugf(" --forceFilter 1|0 : "
- "Enable/disable bitmap filtering, default is disabled.\n");
- SkDebugf(" --forceDither 1|0 : "
- "Enable/disable dithering, default is disabled.\n");
- SkDebugf(" --forceBlend 1|0 : "
- "Enable/disable dithering, default is disabled.\n");
-#if SK_SUPPORT_GPU
- SkDebugf(" --gpuCacheSize <bytes> <count>: "
- "limits gpu cache to bytes size or object count.\n");
- SkDebugf(" -1 for either value means use the default. 0 for either disables the cache.\n");
-#endif
- SkDebugf(" --strokeWidth width : The width for path stroke.\n");
- SkDebugf(" --match [~][^]substring[$] [...] of test name to run.\n"
- " Multiple matches may be separated by spaces.\n"
- " ~ causes a matching test to always be skipped\n"
- " ^ requires the start of the test to match\n"
- " $ requires the end of the test to match\n"
- " ^ and $ requires an exact match\n"
- " If a test does not match any list entry,\n"
- " it is skipped unless some list entry starts with ~\n");
- SkDebugf(" --mode normal|deferred|deferredSilent|record|picturerecord :\n"
- " Run in the corresponding mode\n"
- " normal, Use a normal canvas to draw to;\n"
- " deferred, Use a deferrred canvas when drawing;\n"
- " deferredSilent, deferred with silent playback;\n"
- " record, Benchmark the time to record to an SkPicture;\n"
- " picturerecord, Benchmark the time to do record from a \n"
- " SkPicture to a SkPicture.\n");
- SkDebugf(" --logFile filename : destination for writing log output, in addition to stdout.\n");
- SkDebugf(" --config %s:\n", configsStr.c_str());
- SkDebugf(" Run bench in corresponding config mode.\n");
- SkDebugf(" -Dfoo bar : Add extra definition to bench.\n");
- SkDebugf(" -h|--help : Show this help message.\n");
-}
+DEFINE_string(outDir, "", "If given, image of each bench will be put in outDir.");
+DEFINE_string(timers, "cg", "Timers to display. "
+ "Options: w(all) W(all, truncated) c(pu) C(pu, truncated) g(pu)");
+
+DEFINE_bool(rotate, false, "Rotate canvas before bench run?");
+DEFINE_bool(scale, false, "Scale canvas before bench run?");
+DEFINE_bool(clip, false, "Clip canvas before bench run?");
+
+DEFINE_bool(forceAA, true, "Force anti-aliasing?");
+DEFINE_bool(forceFilter, false, "Force bitmap filtering?");
+DEFINE_string(forceDither, "default", "Force dithering: true, false, or default?");
+DEFINE_bool(forceBlend, false, "Force alpha blending?");
+
+DEFINE_int32(gpuCacheBytes, -1, "GPU cache size limit in bytes. 0 to disable cache.");
+DEFINE_int32(gpuCacheCount, -1, "GPU cache size limit in object count. 0 to disable cache.");
+
+DEFINE_string(match, "", "[~][^]substring[$] [...] of test name to run.\n"
+ "Multiple matches may be separated by spaces.\n"
+ "~ causes a matching test to always be skipped\n"
+ "^ requires the start of the test to match\n"
+ "$ requires the end of the test to match\n"
+ "^ and $ requires an exact match\n"
+ "If a test does not match any list entry,\n"
+ "it is skipped unless some list entry starts with ~\n");
+DEFINE_string(mode, "normal",
+ "normal: draw to a normal canvas;\n"
+ "deferred: draw to a deferred canvas;\n"
+ "deferredSilent: deferred with silent playback;\n"
+ "record: draw to an SkPicture;\n"
+ "picturerecord: draw from an SkPicture to an SkPicture.\n");
+DEFINE_string(config, "", "Run configs given. If empty, runs the defaults set in gConfigs.");
+DEFINE_string(logFile, "", "Also write stdout here.");
+DEFINE_int32(benchMs, 20, "Target time in ms to run each benchmark config.");
+DEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per 1000 loops.");
int tool_main(int argc, char** argv);
int tool_main(int argc, char** argv) {
@@ -349,289 +279,79 @@ int tool_main(int argc, char** argv) {
gPrintInstCount = true;
#endif
SkAutoGraphics ag;
+ SkCommandLineFlags::Parse(argc, argv);
- SkTDict<const char*> defineDict(1024);
- int repeatDraw = 1;
-
- int forceAlpha = 0xFF;
- bool forceAA = true;
- bool forceFilter = false;
- SkTriState::State forceDither = SkTriState::kDefault;
+ // First, parse some flags.
- static const uint32_t kDefaultTimerTypes = TimerData::kCpu_Flag | TimerData::kGpu_Flag;
- static const TimerData::Result kDefaultTimerResult = TimerData::kAvg_Result;
- uint32_t timerTypes = kDefaultTimerTypes;
- TimerData::Result timerResult = kDefaultTimerResult;
+ SkBenchLogger logger;
+ if (FLAGS_logFile.count()) {
+ logger.SetLogFile(FLAGS_logFile[0]);
+ }
- bool doScale = false;
- bool doRotate = false;
- bool doClip = false;
- bool hasStrokeWidth = false;
+ const uint8_t alpha = FLAGS_forceBlend ? 0x80 : 0xFF;
+ SkTriState::State dither = SkTriState::kDefault;
+ for (size_t i = 0; i < 3; i++) {
+ if (strcmp(SkTriState::Name[i], FLAGS_forceDither[0]) == 0) {
+ dither = static_cast<SkTriState::State>(i);
+ }
+ }
-#if SK_SUPPORT_GPU
- struct {
- int fBytes;
- int fCount;
- } gpuCacheSize = { -1, -1 }; // -1s mean use the default
-#endif
+ BenchMode benchMode = kNormal_BenchMode;
+ for (size_t i = 0; i < SK_ARRAY_COUNT(BenchMode_Name); i++) {
+ if (strcmp(FLAGS_mode[0], BenchMode_Name[i]) == 0) {
+ benchMode = static_cast<BenchMode>(i);
+ }
+ }
- float strokeWidth;
- SkTDArray<const char*> fMatches;
- benchModes benchMode = kNormal_benchModes;
- SkString perIterTimeformat("%.2f");
- SkString normalTimeFormat("%6.2f");
-
- SkString outDir;
- SkBitmap::Config outConfig = SkBitmap::kNo_Config;
- const char* configName = "";
- Backend backend = kRaster_Backend; // for warning
- int sampleCount = 0;
SkTDArray<int> configs;
- bool userConfig = false;
-
- SkBenchLogger logger;
-
- char* const* stop = argv + argc;
- for (++argv; argv < stop; ++argv) {
- if (strcmp(*argv, "-o") == 0) {
- argv++;
- if (argv < stop && **argv) {
- outDir.set(*argv);
- if (outDir.c_str()[outDir.size() - 1] != '/') {
- outDir.append("/");
- }
- }
- } else if (strcmp(*argv, "--repeat") == 0) {
- argv++;
- if (argv < stop) {
- repeatDraw = atoi(*argv);
- if (repeatDraw < 1) {
- repeatDraw = 1;
- }
- } else {
- logger.logError("missing arg for --repeat\n");
- help();
- return -1;
- }
- } else if (strcmp(*argv, "--logPerIter") == 0) {
- timerResult = TimerData::kPerIter_Result;
- } else if (strcmp(*argv, "--timers") == 0) {
- argv++;
- if (argv < stop) {
- timerTypes = 0;
- for (char* t = *argv; *t; ++t) {
- switch (*t) {
- case 'w': timerTypes |= TimerData::kWall_Flag; break;
- case 'c': timerTypes |= TimerData::kCpu_Flag; break;
- case 'W': timerTypes |= TimerData::kTruncatedWall_Flag; break;
- case 'C': timerTypes |= TimerData::kTruncatedCpu_Flag; break;
- case 'g': timerTypes |= TimerData::kGpu_Flag; break;
- }
- }
- } else {
- logger.logError("missing arg for --timers\n");
- help();
- return -1;
- }
- } else if (!strcmp(*argv, "--rotate")) {
- doRotate = true;
- } else if (!strcmp(*argv, "--scale")) {
- doScale = true;
- } else if (!strcmp(*argv, "--clip")) {
- doClip = true;
- } else if (!strcmp(*argv, "--min")) {
- timerResult = TimerData::kMin_Result;
- } else if (strcmp(*argv, "--forceAA") == 0) {
- if (!parse_bool_arg(++argv, stop, &forceAA)) {
- logger.logError("missing arg for --forceAA\n");
- help();
- return -1;
- }
- } else if (strcmp(*argv, "--forceFilter") == 0) {
- if (!parse_bool_arg(++argv, stop, &forceFilter)) {
- logger.logError("missing arg for --forceFilter\n");
- help();
- return -1;
- }
- } else if (strcmp(*argv, "--forceDither") == 0) {
- bool tmp;
- if (!parse_bool_arg(++argv, stop, &tmp)) {
- logger.logError("missing arg for --forceDither\n");
- help();
- return -1;
- }
- forceDither = tmp ? SkTriState::kTrue : SkTriState::kFalse;
- } else if (strcmp(*argv, "--forceBlend") == 0) {
- bool wantAlpha = false;
- if (!parse_bool_arg(++argv, stop, &wantAlpha)) {
- logger.logError("missing arg for --forceBlend\n");
- help();
- return -1;
- }
- forceAlpha = wantAlpha ? 0x80 : 0xFF;
-#if SK_SUPPORT_GPU
- } else if (strcmp(*argv, "--gpuCacheSize") == 0) {
- if (stop - argv > 2) {
- gpuCacheSize.fBytes = atoi(*++argv);
- gpuCacheSize.fCount = atoi(*++argv);
- } else {
- SkDebugf("missing arg for --gpuCacheSize\n");
- help();
- return -1;
- }
-#endif
- } else if (strcmp(*argv, "--mode") == 0) {
- argv++;
- if (argv < stop) {
- if (strcmp(*argv, "normal") == 0) {
- benchMode = kNormal_benchModes;
- } else if (strcmp(*argv, "deferred") == 0) {
- benchMode = kDeferred_benchModes;
- } else if (strcmp(*argv, "deferredSilent") == 0) {
- benchMode = kDeferredSilent_benchModes;
- } else if (strcmp(*argv, "record") == 0) {
- benchMode = kRecord_benchModes;
- } else if (strcmp(*argv, "picturerecord") == 0) {
- benchMode = kPictureRecord_benchModes;
- } else {
- logger.logError("bad arg for --mode\n");
- help();
- return -1;
- }
- } else {
- logger.logError("missing arg for --mode\n");
- help();
- return -1;
- }
- } else if (strcmp(*argv, "--strokeWidth") == 0) {
- argv++;
- if (argv < stop) {
- const char *strokeWidthStr = *argv;
- if (sscanf(strokeWidthStr, "%f", &strokeWidth) != 1) {
- logger.logError("bad arg for --strokeWidth\n");
- help();
- return -1;
- }
- hasStrokeWidth = true;
- } else {
- logger.logError("missing arg for --strokeWidth\n");
- help();
- return -1;
- }
- } else if (strcmp(*argv, "--match") == 0) {
- argv++;
- while (argv < stop && (*argv)[0] != '-') {
- *fMatches.append() = *argv++;
- }
- argv--;
- if (!fMatches.count()) {
- logger.logError("missing arg for --match\n");
- help();
- return -1;
- }
- } else if (strcmp(*argv, "--config") == 0) {
- argv++;
- if (argv < stop) {
- int index = findConfig(*argv);
- if (index >= 0) {
- *configs.append() = index;
- userConfig = true;
- } else {
- SkString str;
- str.printf("unrecognized config %s\n", *argv);
- logger.logError(str);
- help();
- return -1;
- }
- } else {
- logger.logError("missing arg for --config\n");
- help();
- return -1;
- }
- } else if (strcmp(*argv, "--logFile") == 0) {
- argv++;
- if (argv < stop) {
- if (!logger.SetLogFile(*argv)) {
- SkString str;
- str.printf("Could not open %s for writing.", *argv);
- logger.logError(str);
- return -1;
- }
- } else {
- logger.logError("missing arg for --logFile\n");
- help();
- return -1;
- }
- } else if (strlen(*argv) > 2 && strncmp(*argv, "-D", 2) == 0) {
- argv++;
- if (argv < stop) {
- defineDict.set(argv[-1] + 2, *argv);
- } else {
- logger.logError("incomplete '-Dfoo bar' definition\n");
- help();
- return -1;
+ // Try user-given configs first.
+ for (int i = 0; i < FLAGS_config.count(); i++) {
+ for (size_t j = 0; j < SK_ARRAY_COUNT(gConfigs); j++) {
+ if (0 == strcmp(FLAGS_config[i], gConfigs[j].name)) {
+ *configs.append() = j;
}
- } else if (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0) {
- help();
- return 0;
- } else {
- SkString str;
- str.printf("unrecognized arg %s\n", *argv);
- logger.logError(str);
- help();
- return -1;
}
}
- if ((benchMode == kRecord_benchModes || benchMode == kPictureRecord_benchModes)
- && !outDir.isEmpty()) {
- logger.logError("'--mode record' and '--mode picturerecord' are not"
- " compatible with -o.\n");
- return -1;
- }
- if ((benchMode == kRecord_benchModes || benchMode == kPictureRecord_benchModes)) {
- perIterTimeformat.set("%.4f");
- normalTimeFormat.set("%6.4f");
- }
- if (!userConfig) {
- // if no config is specified by user, add the default configs
- for (unsigned int i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
- if (gConfigs[i].fRunByDefault) {
+ // If there weren't any, fill in with defaults.
+ if (configs.count() == 0) {
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
+ if (gConfigs[i].runByDefault) {
*configs.append() = i;
}
}
}
- if (kNormal_benchModes != benchMode) {
+ // Filter out things we can't run.
+ if (kNormal_BenchMode != benchMode) {
// Non-rendering configs only run in normal mode
for (int i = 0; i < configs.count(); ++i) {
- int configIdx = configs[i];
- if (kNonRendering_Backend == gConfigs[configIdx].fBackend) {
+ const Config& config = gConfigs[configs[i]];
+ if (kNonRendering_Backend == config.backend) {
configs.remove(i, 1);
--i;
}
}
}
-
#if SK_SUPPORT_GPU
for (int i = 0; i < configs.count(); ++i) {
- int configIdx = configs[i];
+ const Config& config = gConfigs[configs[i]];
- if (kGPU_Backend == gConfigs[configIdx].fBackend && gConfigs[configIdx].fSampleCnt > 0) {
- GrContext* context = gContextFactory.get(gConfigs[configIdx].fContextType);
+ if (kGPU_Backend == config.backend) {
+ GrContext* context = gContextFactory.get(config.contextType);
if (NULL == context) {
SkString error;
error.printf("Error creating GrContext for config %s. Config will be skipped.\n",
- gConfigs[configIdx].fName);
- logger.logError(error.c_str());
+ config.name);
+ logger.logError(error);
configs.remove(i);
--i;
continue;
}
- if (gConfigs[configIdx].fSampleCnt > context->getMaxSampleCount()){
+ if (config.sampleCount > context->getMaxSampleCount()){
SkString error;
error.printf("Sample count (%d) for config %s is unsupported. "
"Config will be skipped.\n",
- gConfigs[configIdx].fSampleCnt, gConfigs[configIdx].fName);
- logger.logError(error.c_str());
+ config.sampleCount, config.name);
+ logger.logError(error);
configs.remove(i);
--i;
continue;
@@ -640,334 +360,272 @@ int tool_main(int argc, char** argv) {
}
#endif
- // report our current settings
- {
- SkString str;
- const char* deferredMode = benchMode == kDeferred_benchModes ? "yes" :
- (benchMode == kDeferredSilent_benchModes ? "silent" : "no");
- str.printf("skia bench: alpha=0x%02X antialias=%d filter=%d "
- "deferred=%s logperiter=%d",
- forceAlpha, forceAA, forceFilter, deferredMode,
- TimerData::kPerIter_Result == timerResult);
- str.appendf(" rotate=%d scale=%d clip=%d min=%d",
- doRotate, doScale, doClip, TimerData::kMin_Result == timerResult);
- str.appendf(" record=%d picturerecord=%d",
- benchMode == kRecord_benchModes,
- benchMode == kPictureRecord_benchModes);
- const char * ditherName;
- switch (forceDither) {
- case SkTriState::kDefault: ditherName = "default"; break;
- case SkTriState::kTrue: ditherName = "true"; break;
- case SkTriState::kFalse: ditherName = "false"; break;
- default: ditherName = "<invalid>"; break;
- }
- str.appendf(" dither=%s", ditherName);
-
- if (hasStrokeWidth) {
- str.appendf(" strokeWidth=%f", strokeWidth);
- } else {
- str.append(" strokeWidth=none");
- }
-
-#if defined(SK_SCALAR_IS_FLOAT)
- str.append(" scalar=float");
-#elif defined(SK_SCALAR_IS_FIXED)
- str.append(" scalar=fixed");
+ // All flags should be parsed now. Report our settings.
+ if (kIsDebug) {
+ logger.logError("bench was built in Debug mode, so we're going to hide the times."
+ " It's for your own good!\n");
+ }
+ SkString str("skia bench:");
+ str.appendf(" mode=%s", FLAGS_mode[0]);
+ str.appendf(" alpha=0x%02X antialias=%d filter=%d dither=%s",
+ alpha, FLAGS_forceAA, FLAGS_forceFilter, SkTriState::Name[dither]);
+ str.appendf(" rotate=%d scale=%d clip=%d", FLAGS_rotate, FLAGS_scale, FLAGS_clip);
+
+#if defined(SK_SCALAR_IS_FIXED)
+ str.append(" scalar=fixed");
+#else
+ str.append(" scalar=float");
#endif
#if defined(SK_BUILD_FOR_WIN32)
- str.append(" system=WIN32");
+ str.append(" system=WIN32");
#elif defined(SK_BUILD_FOR_MAC)
- str.append(" system=MAC");
+ str.append(" system=MAC");
#elif defined(SK_BUILD_FOR_ANDROID)
- str.append(" system=ANDROID");
+ str.append(" system=ANDROID");
#elif defined(SK_BUILD_FOR_UNIX)
- str.append(" system=UNIX");
+ str.append(" system=UNIX");
#else
- str.append(" system=other");
+ str.append(" system=other");
#endif
#if defined(SK_DEBUG)
- str.append(" DEBUG");
+ str.append(" DEBUG");
#endif
- str.append("\n");
- logger.logProgress(str);
- }
+ str.append("\n");
+ logger.logProgress(str);
+
- SkTArray<BenchTimer*> timers(SK_ARRAY_COUNT(gConfigs));
+ // Set texture cache limits if non-default.
for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
#if SK_SUPPORT_GPU
- SkGLContextHelper* glCtx = NULL;
- if (kGPU_Backend == gConfigs[i].fBackend) {
- GrContext* context = gContextFactory.get(gConfigs[i].fContextType);
- if (NULL != context) {
- // Set the user specified cache limits if non-default.
- size_t bytes;
- int count;
- context->getTextureCacheLimits(&count, &bytes);
- if (-1 != gpuCacheSize.fBytes) {
- bytes = static_cast<size_t>(gpuCacheSize.fBytes);
- }
- if (-1 != gpuCacheSize.fCount) {
- count = gpuCacheSize.fCount;
- }
- context->setTextureCacheLimits(count, bytes);
- }
- glCtx = gContextFactory.getGLContext(gConfigs[i].fContextType);
+ const Config& config = gConfigs[i];
+ if (kGPU_Backend != config.backend) {
+ continue;
}
- timers.push_back(SkNEW_ARGS(BenchTimer, (glCtx)));
-#else
- timers.push_back(SkNEW(BenchTimer));
+ GrContext* context = gContextFactory.get(config.contextType);
+ if (NULL == context) {
+ continue;
+ }
+
+ size_t bytes;
+ int count;
+ context->getTextureCacheLimits(&count, &bytes);
+ if (-1 != FLAGS_gpuCacheBytes) {
+ bytes = static_cast<size_t>(FLAGS_gpuCacheBytes);
+ }
+ if (-1 != FLAGS_gpuCacheCount) {
+ count = FLAGS_gpuCacheCount;
+ }
+ context->setTextureCacheLimits(count, bytes);
#endif
}
- Iter iter(&defineDict);
+ // Find the longest name of the benches we're going to run to make the output pretty.
+ Iter names;
SkBenchmark* bench;
- while ((bench = iter.next()) != NULL) {
+ int longestName = 0;
+ while ((bench = names.next()) != NULL) {
SkAutoTUnref<SkBenchmark> benchUnref(bench);
-
- SkIPoint dim = bench->getSize();
- if (dim.fX <= 0 || dim.fY <= 0) {
+ if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
continue;
}
+ const int length = strlen(bench->getName());
+ longestName = length > longestName ? length : longestName;
+ }
- bench->setForceAlpha(forceAlpha);
- bench->setForceAA(forceAA);
- bench->setForceFilter(forceFilter);
- bench->setDither(forceDither);
- if (hasStrokeWidth) {
- bench->setStrokeWidth(strokeWidth);
- }
-
- // only run benchmarks if their name contains matchStr
- if (SkCommandLineFlags::ShouldSkip(fMatches, bench->getName())) {
+ // Run each bench in each configuration it supports and we asked for.
+ Iter iter;
+ while ((bench = iter.next()) != NULL) {
+ SkAutoTUnref<SkBenchmark> benchUnref(bench);
+ if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
continue;
}
- bool loggedBenchStart = false;
-
+ bench->setForceAlpha(alpha);
+ bench->setForceAA(FLAGS_forceAA);
+ bench->setForceFilter(FLAGS_forceFilter);
+ bench->setDither(dither);
AutoPrePostDraw appd(bench);
- for (int x = 0; x < configs.count(); ++x) {
- int configIndex = configs[x];
-
- bool setupFailed = false;
+ bool loggedBenchName = false;
+ for (int i = 0; i < configs.count(); ++i) {
+ const int configIndex = configs[i];
+ const Config& config = gConfigs[configIndex];
- if (kNonRendering_Backend == gConfigs[configIndex].fBackend) {
- if (bench->isRendering()) {
- continue;
- }
- } else {
- if (!bench->isRendering()) {
- continue;
- }
+ if ((kNonRendering_Backend == config.backend) == bench->isRendering()) {
+ continue;
}
- outConfig = gConfigs[configIndex].fConfig;
- configName = gConfigs[configIndex].fName;
- backend = gConfigs[configIndex].fBackend;
- sampleCount = gConfigs[configIndex].fSampleCnt;
GrContext* context = NULL;
- BenchTimer* timer = timers[configIndex];
-
#if SK_SUPPORT_GPU
SkGLContextHelper* glContext = NULL;
- if (kGPU_Backend == backend) {
- context = gContextFactory.get(gConfigs[configIndex].fContextType);
+ if (kGPU_Backend == config.backend) {
+ context = gContextFactory.get(config.contextType);
if (NULL == context) {
continue;
}
- glContext = gContextFactory.getGLContext(gConfigs[configIndex].fContextType);
+ glContext = gContextFactory.getGLContext(config.contextType);
}
#endif
- SkBaseDevice* device = NULL;
- SkCanvas* canvas = NULL;
- SkPicture pictureRecordFrom;
- SkPicture pictureRecordTo;
-
- if (kNonRendering_Backend != backend) {
- device = make_device(outConfig, dim, backend, sampleCount, context);
- if (NULL == device) {
+ SkAutoTUnref<SkBaseDevice> device;
+ SkAutoTUnref<SkCanvas> canvas;
+ SkPicture recordFrom, recordTo;
+ const SkIPoint dim = bench->getSize();
+
+ const SkPicture::RecordingFlags kRecordFlags =
+ SkPicture::kUsePathBoundsForClip_RecordingFlag;
+
+ if (kNonRendering_Backend != config.backend) {
+ device.reset(make_device(config.config,
+ dim,
+ config.backend,
+ config.sampleCount,
+ context));
+ if (!device.get()) {
SkString error;
- error.printf("Device creation failure for config %s. Will skip.\n", configName);
- logger.logError(error.c_str());
- setupFailed = true;
- } else {
- switch(benchMode) {
- case kDeferredSilent_benchModes:
- case kDeferred_benchModes:
- canvas = SkDeferredCanvas::Create(device);
- break;
- case kRecord_benchModes:
- canvas = pictureRecordTo.beginRecording(dim.fX, dim.fY,
- SkPicture::kUsePathBoundsForClip_RecordingFlag);
- canvas->ref();
- break;
- case kPictureRecord_benchModes: {
- // This sets up picture-to-picture recording.
- // The C++ drawing calls for the benchmark are recorded into
- // pictureRecordFrom. As the benchmark, we will time how
- // long it takes to playback pictureRecordFrom into
- // pictureRecordTo.
- SkCanvas* tempCanvas = pictureRecordFrom.beginRecording(dim.fX, dim.fY,
- SkPicture::kUsePathBoundsForClip_RecordingFlag);
- bench->draw(tempCanvas);
- pictureRecordFrom.endRecording();
- canvas = pictureRecordTo.beginRecording(dim.fX, dim.fY,
- SkPicture::kUsePathBoundsForClip_RecordingFlag);
- canvas->ref();
- break;
- }
- case kNormal_benchModes:
- canvas = new SkCanvas(device);
- break;
- default:
- SkASSERT(0);
- }
- device->unref();
- canvas->clear(SK_ColorWHITE);
- }
- }
- SkAutoUnref canvasUnref(canvas);
- if (!setupFailed) {
- if (NULL != canvas) {
- if (doClip) {
- performClip(canvas, dim.fX, dim.fY);
- }
- if (doScale) {
- performScale(canvas, dim.fX, dim.fY);
- }
- if (doRotate) {
- performRotate(canvas, dim.fX, dim.fY);
- }
+ error.printf("Device creation failure for config %s. Will skip.\n", config.name);
+ logger.logError(error);
+ continue;
}
- if (!loggedBenchStart) {
- loggedBenchStart = true;
- SkString str;
- str.printf("running bench [%d %d] %28s", dim.fX, dim.fY, bench->getName());
- logger.logProgress(str);
+ switch(benchMode) {
+ case kDeferredSilent_BenchMode:
+ case kDeferred_BenchMode:
+ canvas.reset(SkDeferredCanvas::Create(device.get()));
+ break;
+ case kRecord_BenchMode:
+ canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
+ break;
+ case kPictureRecord_BenchMode:
+ bench->draw(recordFrom.beginRecording(dim.fX, dim.fY, kRecordFlags));
+ recordFrom.endRecording();
+ canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
+ break;
+ case kNormal_BenchMode:
+ canvas.reset(new SkCanvas(device.get()));
+ break;
+ default:
+ SkASSERT(false);
}
+ }
- // warm up caches if needed
- if (repeatDraw > 1 && NULL != canvas) {
-#if SK_SUPPORT_GPU
- // purge the GPU resources to reduce variance
- if (NULL != context) {
- context->freeGpuResources();
- }
-#endif
- SkAutoCanvasRestore acr(canvas, true);
- if (benchMode == kPictureRecord_benchModes) {
- pictureRecordFrom.draw(canvas);
- } else {
- bench->draw(canvas);
- }
-
- if (kDeferredSilent_benchModes == benchMode) {
- static_cast<SkDeferredCanvas*>(canvas)->silentFlush();
- } else {
- canvas->flush();
- }
-#if SK_SUPPORT_GPU
- if (NULL != context) {
- context->flush();
- SK_GL(*glContext, Finish());
- }
-#endif
- }
+ if (NULL != canvas) {
+ canvas->clear(SK_ColorWHITE);
+ if (FLAGS_clip) { performClip(canvas, dim.fX, dim.fY); }
+ if (FLAGS_scale) { performScale(canvas, dim.fX, dim.fY); }
+ if (FLAGS_rotate) { performRotate(canvas, dim.fX, dim.fY); }
+ }
+
+ if (!loggedBenchName) {
+ loggedBenchName = true;
+ SkString str;
+ str.printf("running bench [%3d %3d] %*s ",
+ dim.fX, dim.fY, longestName, bench->getName());
+ logger.logProgress(str);
+ }
- // record timer values for each repeat, and their sum
- TimerData timerData(repeatDraw);
- for (int i = 0; i < repeatDraw; i++) {
- if ((benchMode == kRecord_benchModes || benchMode == kPictureRecord_benchModes)) {
- // This will clear the recorded commands so that they do not
- // accumulate.
- canvas = pictureRecordTo.beginRecording(dim.fX, dim.fY,
- SkPicture::kUsePathBoundsForClip_RecordingFlag);
- }
-
- timer->start(bench->getDurationScale());
- if (NULL != canvas) {
- canvas->save();
- }
- if (benchMode == kPictureRecord_benchModes) {
- pictureRecordFrom.draw(canvas);
- } else {
- bench->draw(canvas);
- }
-
- if (kDeferredSilent_benchModes == benchMode) {
- static_cast<SkDeferredCanvas*>(canvas)->silentFlush();
- } else if (NULL != canvas) {
- canvas->flush();
- }
-
- if (NULL != canvas) {
- canvas->restore();
- }
-
- // stop the truncated timer after the last canvas call but
- // don't wait for all the GL calls to complete
- timer->truncatedEnd();
#if SK_SUPPORT_GPU
- if (NULL != glContext) {
- context->flush();
- SK_GL(*glContext, Finish());
- }
+ SkGLContextHelper* contextHelper = NULL;
+ if (kGPU_Backend == config.backend) {
+ contextHelper = gContextFactory.getGLContext(config.contextType);
+ }
+ BenchTimer timer(contextHelper);
+#else
+ BenchTimer timer;
#endif
- // stop the inclusive and gpu timers once all the GL calls
- // have completed
- timer->end();
- SkAssertResult(timerData.appendTimes(timer));
+ bench->setLoops(0);
+ do {
+ // Ramp up 1 -> 4 -> 16 -> ... -> ~1 billion.
+ const int loops = bench->getLoops();
+ if (loops >= (1<<30)) {
+ // If you find it takes more than a billion loops to get up to 20ms of runtime,
+ // you've got a computer clocked at several THz or have a broken benchmark. ;)
+ // "1B ought to be enough for anybody."
+ SkString str;
+ str.printf("Can't ramp %s to %dms.\n", bench->getName(), FLAGS_benchMs);
+ logger.logError(str);
+ break;
+ }
+ bench->setLoops(loops == 0 ? 1 : loops * 4);
+
+ if ((benchMode == kRecord_BenchMode || benchMode == kPictureRecord_BenchMode)) {
+ // Clear the recorded commands so that they do not accumulate.
+ canvas.reset(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags));
+ }
+ timer.start();
+ if (NULL != canvas) {
+ canvas->save();
}
- const char* timeFormat;
- if (repeatDraw > 1 && TimerData::kPerIter_Result == timerResult) {
- timeFormat = perIterTimeformat.c_str();
+ if (benchMode == kPictureRecord_BenchMode) {
+ recordFrom.draw(canvas);
} else {
- timeFormat = normalTimeFormat.c_str();
+ bench->draw(canvas);
}
- uint32_t filteredTimerTypes = timerTypes;
- if (NULL == context) {
- filteredTimerTypes &= ~TimerData::kGpu_Flag;
+
+ if (kDeferredSilent_BenchMode == benchMode) {
+ static_cast<SkDeferredCanvas*>(canvas.get())->silentFlush();
+ } else if (NULL != canvas) {
+ canvas->flush();
+ }
+
+ if (NULL != canvas) {
+ canvas->restore();
+ }
+
+
+ // Stop truncated timers before GL calls complete, and stop the full timers after.
+ timer.truncatedEnd();
+#if SK_SUPPORT_GPU
+ if (NULL != glContext) {
+ context->flush();
+ SK_GL(*glContext, Finish());
}
- SkString result = timerData.getResult(timeFormat,
- timerResult,
- configName,
- filteredTimerTypes);
- logger.logProgress(result);
-
- if (outDir.size() > 0 && kNonRendering_Backend != backend) {
- saveFile(bench->getName(), configName, outDir.c_str(),
- device->accessBitmap(false));
+#endif
+ timer.end();
+ } while (!kIsDebug && timer.fWall < FLAGS_benchMs); // One loop only in debug mode.
+
+ if (FLAGS_outDir.count() && kNonRendering_Backend != config.backend) {
+ saveFile(bench->getName(),
+ config.name,
+ FLAGS_outDir[0],
+ device->accessBitmap(false));
+ }
+
+ if (kIsDebug) {
+ // Let's not mislead ourselves by looking at Debug build bench times!
+ continue;
+ }
+
+ // Normalize to ms per 1000 iterations.
+ const double normalize = 1000.0 / bench->getLoops();
+ const struct { char shortName; const char* longName; double ms; } times[] = {
+ {'w', "msecs", normalize * timer.fWall},
+ {'W', "Wmsecs", normalize * timer.fTruncatedWall},
+ {'c', "cmsecs", normalize * timer.fCpu},
+ {'C', "Cmsecs", normalize * timer.fTruncatedCpu},
+ {'g', "gmsecs", normalize * timer.fGpu},
+ };
+
+ SkString result;
+ result.appendf(" %s:", config.name);
+ for (size_t i = 0; i < SK_ARRAY_COUNT(times); i++) {
+ if (strchr(FLAGS_timers[0], times[i].shortName) && times[i].ms > 0) {
+ result.appendf(" %s = ", times[i].longName);
+ result.appendf(FLAGS_timeFormat[0], times[i].ms);
}
}
+ logger.logProgress(result);
}
- if (loggedBenchStart) {
- logger.logProgress(SkString("\n"));
+ if (loggedBenchName) {
+ logger.logProgress("\n");
}
}
#if SK_SUPPORT_GPU
-#if GR_CACHE_STATS
- for (int i = 0; i <= GrContextFactory::kLastGLContextType; ++i) {
- GrContextFactory::GLContextType ctxType = (GrContextFactory::GLContextType)i;
- GrContext* context = gContextFactory.get(ctxType);
- if (NULL != context) {
- SkDebugf("Cache Stats for %s context:\n", GrContextFactory::GLContextTypeName(ctxType));
- context->printCacheStats();
- SkDebugf("\n");
- }
- }
-#endif
- // Destroy the GrContext before the inst tracking printing at main() exit occurs.
gContextFactory.destroyContexts();
#endif
- for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
- SkDELETE(timers[i]);
- }
-
return 0;
}