summaryrefslogtreecommitdiffstats
path: root/gfx/skia/skia/src/utils/SkBlitterTraceCommon.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/skia/skia/src/utils/SkBlitterTraceCommon.h')
-rw-r--r--gfx/skia/skia/src/utils/SkBlitterTraceCommon.h180
1 files changed, 180 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/utils/SkBlitterTraceCommon.h b/gfx/skia/skia/src/utils/SkBlitterTraceCommon.h
new file mode 100644
index 0000000000..b4adb5ce77
--- /dev/null
+++ b/gfx/skia/skia/src/utils/SkBlitterTraceCommon.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2022 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * This is an experimental (and probably temporary) solution that allows
+ * to compare performance SkVM blitters vs RasterPipeline blitters.
+ * In addition to measuring performance (which is questionable) it also produces
+ * other counts (pixels, scanlines) and more detailed traces that
+ * can explain the current results (SkVM is slower) and help improve it.
+ * The entire code is hidden under build flag skia_compare_vm_vs_rp=true
+ * and will not appear at all without it.
+ */
+
+#ifndef SkBlitterTraceCommon_DEFINED
+#define SkBlitterTraceCommon_DEFINED
+
+#include <inttypes.h>
+#include <unordered_map>
+
+#define SK_BLITTER_TRACE_NO_CODE do {} while (0)
+
+#ifdef SKIA_COMPARE_VM_VS_RP
+
+#include "src/utils/SkCycles.h"
+
+class SkBlitterTrace {
+/*
+ * This class collects information for RasterPipeLine vs SkVM
+ * performance comparison.
+ * How to get the comparison table:
+ * 1. Add to your Release/args.gn an argument: skia_compare_vm_vs_rp=true
+ * Build nanobench.
+ * 2. Run nanobench for SkVM:
+ * []/Release/nanobench
+ * --csv --config 8888 --skvm --loops 100 --samples 1
+ * --match $(ls skps | grep --invert-match svg ) 2>&1 | tee VM.data
+ * 3. Run nanobench for RasterPipeLine:
+ * []/Release/nanobench
+ * --csv --config 8888 --forceRasterPipeline --loops 100
+ * --samples 1 --match $(ls skps | grep --invert-match svg )
+ * 2>&1 | tee RP.data
+ * 4. Extract the information side-by-side:
+ * awk 'BEGIN {OFS=","; fileNum = 0} ($2 ~ /MB/) && fileNum == 0
+ * {vmvmcycles[$3] = $6; vmvmscan[$3] = $8; vmvmpixels[$3] = $10;
+ * vmvminterp[$3] = $11; vmrpcycle[$3] = $14; vmrpscan[$3] = $16;
+ * vmrppixels[$3] = $18} ($2 ~ /MB/) && fileNum == 1 {print $3,
+ * vmvmcycles[$3], vmvmscan[$3], vmvmpixels[$3], vmvminterp[$3], $6, $8,
+ * $10, $11, $14, $16, $18} ENDFILE {fileNum += 1}'
+ * VM.data RP.data > compare.csv
+ * 5. Open the compare.csv table in Google Spreadsheets.
+ * You will get columns [A:P]. Add 4 more columns with formulas:
+ * Q: =B/M-1
+ * R: =N-C
+ * S: =O-D
+ * T: =2*(S<>0)+(R<>0)
+ * To be honest R, S, T columns are here for checking only (they all
+ * supposed to have zero values in them)
+ * Column Q shows the actual performance difference. Negative value means
+ * that wins SkVM, positive - RasterPipeLine.
+ */
+public:
+ SkBlitterTrace(const char* header, bool traceSteps = false)
+ : fHeader(header), fTraceSteps(traceSteps) { }
+
+ SkBlitterTrace& operator= (const SkBlitterTrace&) = default;
+
+ void addTrace(const char* name, uint64_t cycles, uint64_t scanLines, uint64_t pixels) {
+ fCycles += cycles;
+ fScanlines += scanLines;
+ fPixels += pixels;
+ if (fTraceSteps) {
+ printIncrements(name, cycles, scanLines, pixels);
+ }
+ }
+
+ void reset() {
+ fCycles = 0ul;
+ fScanlines = 0ul;
+ fPixels = 0ul;
+ }
+
+ void printIncrements(const char* name,
+ uint64_t cycles,
+ uint64_t scanLines,
+ uint64_t pixels) const {
+ SkDebugf("%s %s: cycles=%" PRIu64 "+%" PRIu64
+ " scanlines=%" PRIu64 "+%" PRIu64 " pixels=%" PRIu64,
+ fHeader, name,
+ fCycles - cycles, cycles,
+ fScanlines - scanLines, scanLines,
+ fPixels);
+ SkDebugf("\n");
+ }
+
+ void printCounts(const char* name) const {
+ SkDebugf("%s cycles: %" PRIu64 " "
+ " scanlines: %" PRIu64 " pixels: %" PRIu64,
+ fHeader,
+ fCycles,
+ fScanlines,
+ fPixels);
+ SkDebugf(" ");
+ }
+
+ uint64_t getCycles() const { return fCycles; }
+ uint64_t getScanlines() const { return fScanlines; }
+ uint64_t getPixels() const { return fPixels; }
+
+ class Step {
+ public:
+ Step(SkBlitterTrace* trace,
+ const char* name,
+ uint64_t scanlines,
+ uint64_t pixels)
+ : fTrace(trace)
+ , fName(name)
+ , fScanlines(scanlines)
+ , fPixels(pixels) {
+ fStartTime = SkCycles::Now();
+ }
+ void add(uint64_t scanlines, uint64_t pixels) {
+ fScanlines += scanlines;
+ fPixels += pixels;
+ }
+ ~Step() {
+ if (fTrace == nullptr) {
+ return;
+ }
+ auto endTime = SkCycles::Now() - fStartTime;
+ fTrace->addTrace(/*name=*/fName,
+ /*cycles=*/endTime,
+ /*scanlines=*/fScanlines,
+ /*pixels=*/fPixels);
+ }
+ private:
+ SkBlitterTrace* fTrace = nullptr;
+ const char* fName = "";
+ uint64_t fStartTime = 0ul;
+ uint64_t fScanlines = 0ul;
+ uint64_t fPixels = 0ul;
+ };
+
+private:
+ const char* fHeader = "";
+ bool fTraceSteps = false;
+ uint64_t fCycles = 0ul;
+ uint64_t fScanlines = 0ul;
+ uint64_t fPixels = 0ul;
+};
+
+#define SK_BLITTER_TRACE_INIT \
+extern SkBlitterTrace gSkVMBlitterTrace; \
+extern SkBlitterTrace gSkRPBlitterTrace; \
+ \
+static SkBlitterTrace gSkVMBlitterTraceCapture("VM", false); \
+static SkBlitterTrace gSkRPBlitterTraceCapture("RP", false);
+
+#define SK_BLITTER_TRACE_LOCAL_SETUP \
+ gSkVMBlitterTrace.reset(); \
+ gSkRPBlitterTrace.reset()
+
+#define SK_BLITTER_TRACE_LOCAL_TEARDOWN \
+ gSkVMBlitterTraceCapture = gSkVMBlitterTrace; \
+ gSkRPBlitterTraceCapture = gSkRPBlitterTrace
+
+#define SK_BLITTER_TRACE_PRINT \
+ gSkVMBlitterTraceCapture.printCounts("Total"); \
+ SkDebugf("0 "); \
+ gSkRPBlitterTraceCapture.printCounts("Total")
+
+#else
+#define SK_BLITTER_TRACE_INIT
+#define SK_BLITTER_TRACE_LOCAL_SETUP SK_BLITTER_TRACE_NO_CODE
+#define SK_BLITTER_TRACE_LOCAL_TEARDOWN SK_BLITTER_TRACE_NO_CODE
+#define SK_BLITTER_TRACE_PRINT SK_BLITTER_TRACE_NO_CODE
+#endif // SKIA_COMPARE_VM_VS_RP
+
+#endif // SkBlitterTraceCommon_DEFINED