Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Unified Diff: tools/bbh_shootout.cpp

Issue 23121002: Add correctness test to bbh_shootout. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/bbh_shootout.cpp
diff --git a/tools/bbh_shootout.cpp b/tools/bbh_shootout.cpp
index 9de0bfcf828ab91a493307d2173beb9bfbdeb085..76e8d074c3f78a37c82a67dd70325c913aa714ed 100644
--- a/tools/bbh_shootout.cpp
+++ b/tools/bbh_shootout.cpp
@@ -19,7 +19,7 @@
static const int kNumNormalRecordings = SkBENCHLOOP(10);
static const int kNumRTreeRecordings = SkBENCHLOOP(10);
-static const int kNumPlaybacks = SkBENCHLOOP(4);
+static const int kNumPlaybacks = SkBENCHLOOP(1);
static const size_t kNumBaseBenchmarks = 3;
static const size_t kNumTileSizes = 3;
static const size_t kNumBbhPlaybackBenchmarks = 3;
@@ -39,14 +39,19 @@ struct Histogram {
SkString fPath;
};
-typedef void (*BenchmarkFunction)
- (BenchmarkType, const SkISize&, const SkString&, SkPicture*, BenchTimer*);
+////////////////////////////////////////////////////////////////////////////////
// Defined below.
+struct BenchmarkControl;
+
+typedef void (*BenchmarkFunction)
+ (const BenchmarkControl&, const SkString&, SkPicture*, BenchTimer*);
+
static void benchmark_playback(
- BenchmarkType, const SkISize&, const SkString&, SkPicture*, BenchTimer*);
+ const BenchmarkControl&, const SkString&, SkPicture*, BenchTimer*);
static void benchmark_recording(
- BenchmarkType, const SkISize&, const SkString&, SkPicture*, BenchTimer*);
+ const BenchmarkControl&, const SkString&, SkPicture*, BenchTimer*);
+////////////////////////////////////////////////////////////////////////////////
/**
* Acts as a POD containing information needed to run a benchmark.
@@ -64,10 +69,10 @@ struct BenchmarkControl {
static BenchmarkControl Make(size_t i) {
SkASSERT(kNumBenchmarks > i);
BenchmarkControl benchControl;
- benchControl.fTileSize = getTileSize(i);
- benchControl.fType = getBenchmarkType(i);
- benchControl.fFunction = getBenchmarkFunc(i);
- benchControl.fName = getBenchmarkName(i);
+ benchControl.fTileSize = GetTileSize(i);
+ benchControl.fType = GetBenchmarkType(i);
+ benchControl.fFunction = GetBenchmarkFunc(i);
+ benchControl.fName = GetBenchmarkName(i);
return benchControl;
}
@@ -79,7 +84,7 @@ struct BenchmarkControl {
static SkISize fTileSizes[kNumTileSizes];
- static SkISize getTileSize(size_t i) {
+ static SkISize GetTileSize(size_t i) {
// Two of the base benchmarks don't need a tile size. But to maintain simplicity
// down the pipeline we have to let a couple of values unused.
if (i < kNumBaseBenchmarks) {
@@ -92,15 +97,15 @@ struct BenchmarkControl {
return SkISize::Make(0, 0);
}
- static BenchmarkType getBenchmarkType(size_t i) {
+ static BenchmarkType GetBenchmarkType(size_t i) {
if (i < kNumBaseBenchmarks) {
switch (i) {
- case kNormalRecord:
- return kNormal_BenchmarkType;
- case kNormalPlayback:
- return kNormal_BenchmarkType;
- case kRTreeRecord:
- return kRTree_BenchmarkType;
+ case kNormalRecord:
+ return kNormal_BenchmarkType;
+ case kNormalPlayback:
+ return kNormal_BenchmarkType;
+ case kRTreeRecord:
+ return kRTree_BenchmarkType;
}
}
if (i < kNumBenchmarks) {
@@ -110,7 +115,7 @@ struct BenchmarkControl {
return kRTree_BenchmarkType;
}
- static BenchmarkFunction getBenchmarkFunc(size_t i) {
+ static BenchmarkFunction GetBenchmarkFunc(size_t i) {
// Base functions.
switch (i) {
case kNormalRecord:
@@ -128,7 +133,7 @@ struct BenchmarkControl {
return NULL;
}
- static SkString getBenchmarkName(size_t i) {
+ static SkString GetBenchmarkName(size_t i) {
// Base benchmark names
switch (i) {
case kNormalRecord:
@@ -171,10 +176,29 @@ static SkPicture* pic_from_path(const char path[]) {
}
/**
+ * Returns true when a tiled renderer with no bounding box hierarchy produces the given bitmap.
+ */
+static bool compare_picture(const SkString& path, const SkBitmap& inBitmap, SkPicture* pic) {
+ SkBitmap* bitmap;
+ sk_tools::TiledPictureRenderer renderer;
+ renderer.setBBoxHierarchyType(sk_tools::PictureRenderer::kNone_BBoxHierarchyType);
+ renderer.init(pic);
+ renderer.setup();
+ renderer.render(&path, &bitmap);
+ SkAutoTDelete<SkBitmap> bmDeleter(bitmap);
+ renderer.end();
+
+ if (bitmap->getSize() != inBitmap.getSize()) {
+ return false;
+ }
+ return !memcmp(bitmap->getPixels(), inBitmap.getPixels(), bitmap->getSize());
+}
+
+/**
* This function is the sink to which all work ends up going.
* Renders the picture into the renderer. It may or may not use an RTree.
* The renderer is chosen upstream. If we want to measure recording, we will
- * use a RecordPictureRenderer. If we want to measure rendering, we eill use a
+ * use a RecordPictureRenderer. If we want to measure rendering, we will use a
* TiledPictureRenderer.
*/
static void do_benchmark_work(sk_tools::PictureRenderer* renderer,
@@ -202,36 +226,50 @@ static void do_benchmark_work(sk_tools::PictureRenderer* renderer,
* If the renderer is not tiled, assume we are measuring recording.
*/
bool isPlayback = (NULL != renderer->getTiledRenderer());
+ // Will be non-null during RTree picture playback. For correctness test.
+ SkBitmap* bitmap = NULL;
SkDebugf("%s %s %s %d times...\n", msgPrefix.c_str(), msg, path.c_str(), numRepeats);
for (int i = 0; i < numRepeats; ++i) {
+ // Set up the bitmap.
+ SkBitmap** out = NULL;
+ if (i == 0 && kRTree_BenchmarkType == benchmarkType && isPlayback) {
+ out = &bitmap;
+ }
+
renderer->setup();
// Render once to fill caches.
renderer->render(NULL);
// Render again to measure
timer->start();
- bool result = renderer->render(NULL);
+ bool result = renderer->render(NULL, out);
timer->end();
+
// We only care about a false result on playback. RecordPictureRenderer::render will always
// return false because we are passing a NULL file name on purpose; which is fine.
- if(isPlayback && !result) {
+ if (isPlayback && !result) {
SkDebugf("Error rendering during playback.\n");
}
}
- renderer->end();
+ if (bitmap) {
+ SkAutoTDelete<SkBitmap> bmDeleter(bitmap);
+ if (!compare_picture(path, *bitmap, pic)) {
+ SkDebugf("Error: RTree produced different bitmap\n");
+ }
+ }
}
/**
* Call do_benchmark_work with a tiled renderer using the default tile dimensions.
*/
static void benchmark_playback(
- BenchmarkType benchmarkType, const SkISize& tileSize,
+ const BenchmarkControl& benchControl,
const SkString& path, SkPicture* pic, BenchTimer* timer) {
sk_tools::TiledPictureRenderer renderer;
SkString message("tiled_playback");
- message.appendf("_%dx%d", tileSize.fWidth, tileSize.fHeight);
- do_benchmark_work(&renderer, benchmarkType,
+ message.appendf("_%dx%d", benchControl.fTileSize.fWidth, benchControl.fTileSize.fHeight);
+ do_benchmark_work(&renderer, benchControl.fType,
path, pic, kNumPlaybacks, message.c_str(), timer);
}
@@ -239,11 +277,11 @@ static void benchmark_playback(
* Call do_benchmark_work with a RecordPictureRenderer.
*/
static void benchmark_recording(
- BenchmarkType benchmarkType, const SkISize& tileSize,
+ const BenchmarkControl& benchControl,
const SkString& path, SkPicture* pic, BenchTimer* timer) {
sk_tools::RecordPictureRenderer renderer;
int numRecordings = 0;
- switch(benchmarkType) {
+ switch(benchControl.fType) {
case kRTree_BenchmarkType:
numRecordings = kNumRTreeRecordings;
break;
@@ -251,7 +289,8 @@ static void benchmark_recording(
numRecordings = kNumNormalRecordings;
break;
}
- do_benchmark_work(&renderer, benchmarkType, path, pic, numRecordings, "recording", timer);
+ do_benchmark_work(&renderer, benchControl.fType,
+ path, pic, numRecordings, "recording", timer);
}
/**
@@ -277,8 +316,7 @@ static bool benchmark_loop(
SkDebugf("Couldn't create picture. Ignoring path: %s\n", path.c_str());
continue;
}
- benchControl.fFunction(benchControl.fType, benchControl.fTileSize, path, pic, &timer);
- SkAssertResult(timerData.appendTimes(&timer));
+ benchControl.fFunction(benchControl, path, pic, &timer);
histogram[index - 1].fPath = path;
histogram[index - 1].fCpuTime = SkDoubleToScalar(timer.fCpu);
@@ -293,7 +331,7 @@ static bool benchmark_loop(
const char findStr[] = "= ";
int pos = timerResult.find(findStr);
if (-1 == pos) {
- SkDebugf("Unexpected output from TimerData::getResult(...). Unable to parse.");
+ SkDebugf("Unexpected output from TimerData::getResult(...). Unable to parse.\n");
return false;
}
@@ -325,7 +363,7 @@ int tool_main(int argc, char** argv) {
BenchmarkControl::Make(i),
histograms[i]);
if (!success) {
- SkDebugf("benchmark_loop failed at index %d", i);
+ SkDebugf("benchmark_loop failed at index %d\n", i);
}
}
@@ -338,24 +376,30 @@ int tool_main(int argc, char** argv) {
playbackOut.writeText("# ");
for (size_t i = 0; i < kNumBenchmarks; ++i) {
SkString out;
- out.printf("%s ", BenchmarkControl::getBenchmarkName(i).c_str());
- if (BenchmarkControl::getBenchmarkFunc(i) == &benchmark_recording) {
+ out.printf("%s ", BenchmarkControl::GetBenchmarkName(i).c_str());
+ if (BenchmarkControl::GetBenchmarkFunc(i) == &benchmark_recording) {
recordOut.writeText(out.c_str());
}
- if (BenchmarkControl::getBenchmarkFunc(i) == &benchmark_playback) {
+ if (BenchmarkControl::GetBenchmarkFunc(i) == &benchmark_playback) {
playbackOut.writeText(out.c_str());
}
}
recordOut.writeText("\n");
playbackOut.writeText("\n");
-
+ // Write to file, and save recording averages.
+ SkScalar avgRecord = SkIntToScalar(0);
+ SkScalar avgRecordRTree = SkIntToScalar(0);
for (int i = 0; i < argc - 1; ++i) {
SkString pbLine;
SkString recLine;
// ==== Write record info
recLine.printf("%d ", i);
- recLine.appendf("%f ", histograms[0][i].fCpuTime); // Append normal_record time
- recLine.appendf("%f", histograms[1][i].fCpuTime); // Append rtree_record time
+ SkScalar cpuTime = histograms[BenchmarkControl::kNormalRecord][i].fCpuTime;
+ recLine.appendf("%f ", cpuTime);
+ avgRecord += cpuTime;
+ cpuTime = histograms[BenchmarkControl::kRTreeRecord][i].fCpuTime;
+ recLine.appendf("%f", cpuTime);
+ avgRecordRTree += cpuTime;
// ==== Write playback info
pbLine.printf("%d ", i);
@@ -370,6 +414,10 @@ int tool_main(int argc, char** argv) {
playbackOut.writeText(pbLine.c_str());
recordOut.writeText(recLine.c_str());
}
+ avgRecord /= argc - 1;
+ avgRecordRTree /= argc - 1;
+ SkDebugf("Average base recording time: %.3fms\n", avgRecord);
+ SkDebugf("Average recording time with rtree: %.3fms\n", avgRecordRTree);
SkDebugf("\nWrote data to gnuplot-readable files: %s %s\n", pbTitle, recTitle);
return 0;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698