Began logging more gpu stats from nanobench

BUG=skia:

Review URL: https://codereview.chromium.org/1489033004
diff --git a/bench/Benchmark.h b/bench/Benchmark.h
index a403a6e..30c7aa9 100644
--- a/bench/Benchmark.h
+++ b/bench/Benchmark.h
@@ -124,6 +124,8 @@
         this->perCanvasPostDraw(canvas);
     }
 
+    virtual void getGpuStats(SkCanvas*, SkTArray<SkString>* keys, SkTArray<double>* values) {}
+
 protected:
     virtual void setupPaint(SkPaint* paint);
 
diff --git a/bench/ResultsWriter.h b/bench/ResultsWriter.h
index 2906429..bf74d47 100644
--- a/bench/ResultsWriter.h
+++ b/bench/ResultsWriter.h
@@ -87,26 +87,26 @@
     }
 
     // Added under "key".
-    virtual void key(const char name[], const char value[]) {
+    void key(const char name[], const char value[]) override {
         fRoot["key"][name] = value;
     }
     // Inserted directly into the root.
-    virtual void property(const char name[], const char value[]) {
+    void property(const char name[], const char value[]) override {
         fRoot[name] = value;
     }
-    virtual void bench(const char name[], int32_t x, int32_t y) {
+    void bench(const char name[], int32_t x, int32_t y) override {
         SkString id = SkStringPrintf( "%s_%d_%d", name, x, y);
         fResults[id.c_str()] = Json::Value(Json::objectValue);
         fBench = &fResults[id.c_str()];
     }
-    virtual void config(const char name[]) {
+    void config(const char name[]) override {
         SkASSERT(fBench);
         fConfig = &(*fBench)[name];
     }
-    virtual void configOption(const char name[], const char* value) {
+    void configOption(const char name[], const char* value) override {
         (*fConfig)["options"][name] = value;
     }
-    virtual void metric(const char name[], double ms) {
+    void metric(const char name[], double ms) override {
         // Don't record if nan, or -nan.
         if (sk_double_isnan(ms)) {
             return;
@@ -116,7 +116,7 @@
     }
 
     // Flush to storage now please.
-    virtual void flush() {
+    void flush() override {
         SkString dirname = SkOSPath::Dirname(fFilename.c_str());
         if (!sk_exists(dirname.c_str(), kWrite_SkFILE_Flag)) {
             if (!sk_mkdir(dirname.c_str())) {
diff --git a/bench/SKPBench.cpp b/bench/SKPBench.cpp
index 910af6b..c548090 100644
--- a/bench/SKPBench.cpp
+++ b/bench/SKPBench.cpp
@@ -155,3 +155,41 @@
         fSurfaces[j]->getCanvas()->flush();
     }
 }
+
+#if SK_SUPPORT_GPU
+static void draw_pic_for_stats(SkCanvas* canvas, GrContext* context, const SkPicture* picture,
+                               SkTArray<SkString>* keys, SkTArray<double>* values,
+                               const char* tag) {
+    context->resetGpuStats();
+    canvas->drawPicture(picture);
+    canvas->flush();
+
+    int offset = keys->count();
+    context->dumpGpuStatsKeyValuePairs(keys, values);
+
+    // append tag, but only to new tags
+    for (int i = offset; i < keys->count(); i++, offset++) {
+        (*keys)[i].appendf("_%s", tag);
+    }
+}
+#endif
+
+void SKPBench::getGpuStats(SkCanvas* canvas, SkTArray<SkString>* keys, SkTArray<double>* values) {
+#if SK_SUPPORT_GPU
+    // we do a special single draw and then dump the key / value pairs
+    GrContext* context = canvas->getGrContext();
+    if (!context) {
+        return;
+    }
+
+    // TODO refactor this out if we want to test other subclasses of skpbench
+    context->flush();
+    context->freeGpuResources();
+    context->resetContext();
+    draw_pic_for_stats(canvas, context, fPic, keys, values, "first_frame");
+
+    // draw second frame
+    draw_pic_for_stats(canvas, context, fPic, keys, values, "second_frame");
+
+#endif
+}
diff --git a/bench/SKPBench.h b/bench/SKPBench.h
index 89c9a36..1f34a00 100644
--- a/bench/SKPBench.h
+++ b/bench/SKPBench.h
@@ -28,6 +28,8 @@
         return fDoLooping ? defaultLoops : 1;
     }
 
+    void getGpuStats(SkCanvas*, SkTArray<SkString>* keys, SkTArray<double>* values) override;
+
 protected:
     const char* onGetName() override;
     const char* onGetUniqueName() override;
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index 99483eb..602d613 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -107,6 +107,7 @@
 DEFINE_int32(flushEvery, 10, "Flush --outResultsFile every Nth run.");
 DEFINE_bool(resetGpuContext, true, "Reset the GrContext before running each test.");
 DEFINE_bool(gpuStats, false, "Print GPU stats after each gpu benchmark?");
+DEFINE_bool(gpuStatsDump, false, "Dump GPU states after each benchmark to json");
 
 static double now_ms() { return SkTime::GetNSecs() * 1e-6; }
 
@@ -1184,6 +1185,16 @@
                 }
             }
 
+#if SK_SUPPORT_GPU
+            SkTArray<SkString> keys;
+            SkTArray<double> values;
+            bool gpuStatsDump = FLAGS_gpuStatsDump && Benchmark::kGPU_Backend == configs[i].backend;
+            if (gpuStatsDump) {
+                // TODO cache stats
+                bench->getGpuStats(canvas, &keys, &values);
+            }
+#endif
+
             bench->perCanvasPostDraw(canvas);
 
             if (Benchmark::kNonRendering_Backend != target->config.backend &&
@@ -1206,6 +1217,16 @@
             benchStream.fillCurrentOptions(log.get());
             target->fillOptions(log.get());
             log->metric("min_ms",    stats.min);
+#if SK_SUPPORT_GPU
+            if (gpuStatsDump) {
+                // dump to json, only SKPBench currently returns valid keys / values
+                SkASSERT(keys.count() == values.count());
+                for (int i = 0; i < keys.count(); i++) {
+                    log->metric(keys[i].c_str(), values[i]);
+                }
+            }
+#endif
+
             if (runs++ % FLAGS_flushEvery == 0) {
                 log->flush();
             }
@@ -1240,13 +1261,14 @@
                         , bench->getUniqueName()
                         );
             }
+
 #if SK_SUPPORT_GPU
-            if (FLAGS_gpuStats &&
-                Benchmark::kGPU_Backend == configs[i].backend) {
+            if (FLAGS_gpuStats && Benchmark::kGPU_Backend == configs[i].backend) {
                 gGrFactory->get(configs[i].ctxType)->printCacheStats();
                 gGrFactory->get(configs[i].ctxType)->printGpuStats();
             }
 #endif
+
             if (FLAGS_verbose) {
                 SkDebugf("Samples:  ");
                 for (int i = 0; i < samples.count(); i++) {