diff --git a/bench/BenchTimer.cpp b/bench/BenchTimer.cpp index ab9dfdaf18..3617f9de58 100644 --- a/bench/BenchTimer.cpp +++ b/bench/BenchTimer.cpp @@ -46,7 +46,9 @@ BenchTimer::~BenchTimer() { #endif } -void BenchTimer::start() { +void BenchTimer::start(double durationScale) { + fDurationScale = durationScale; + fSysTimer->startWall(); fTruncatedSysTimer->startWall(); #if SK_SUPPORT_GPU @@ -59,18 +61,18 @@ void BenchTimer::start() { } void BenchTimer::end() { - fCpu = fSysTimer->endCpu(); + fCpu = fSysTimer->endCpu() * fDurationScale; #if SK_SUPPORT_GPU //It is important to stop the cpu clocks first, //as the following will cpu wait for the gpu to finish. if (fGpuTimer) { - fGpu = fGpuTimer->endGpu(); + fGpu = fGpuTimer->endGpu() * fDurationScale; } #endif - fWall = fSysTimer->endWall(); + fWall = fSysTimer->endWall() * fDurationScale; } void BenchTimer::truncatedEnd() { - fTruncatedCpu = fTruncatedSysTimer->endCpu(); - fTruncatedWall = fTruncatedSysTimer->endWall(); + fTruncatedCpu = fTruncatedSysTimer->endCpu() * fDurationScale; + fTruncatedWall = fTruncatedSysTimer->endWall() * fDurationScale; } diff --git a/bench/BenchTimer.h b/bench/BenchTimer.h index 79e1036c52..09950a734b 100644 --- a/bench/BenchTimer.h +++ b/bench/BenchTimer.h @@ -29,7 +29,7 @@ class BenchTimer { public: BenchTimer(SkGLContextHelper* gl = NULL); ~BenchTimer(); - void start(); + void start(double durationScale = 1); void end(); void truncatedEnd(); double fCpu; @@ -44,6 +44,7 @@ private: #if SK_SUPPORT_GPU BenchGpuTimer *fGpuTimer; #endif + double fDurationScale; // for this start/end session }; #endif diff --git a/bench/BitmapBench.cpp b/bench/BitmapBench.cpp index eba55f50da..a6d20966ea 100644 --- a/bench/BitmapBench.cpp +++ b/bench/BitmapBench.cpp @@ -13,10 +13,6 @@ #include "SkRandom.h" #include "SkString.h" -static const char* gTileName[] = { - "clamp", "repeat", "mirror" -}; - static const char* gConfigName[] = { "ERROR", "a1", "a8", "index8", "565", "4444", "8888" }; @@ -82,22 +78,19 @@ class BitmapBench : public SkBenchmark { SkPaint fPaint; bool fIsOpaque; bool fForceUpdate; //bitmap marked as dirty before each draw. forces bitmap to be updated on device cache - int fTileX, fTileY; // -1 means don't use shader bool fIsVolatile; SkBitmap::Config fConfig; SkString fName; - enum { N = SkBENCHLOOP(300) }; + enum { BICUBIC_DUR_SCALE = 20 }; + enum { N = SkBENCHLOOP(15 * BICUBIC_DUR_SCALE) }; enum { W = 128 }; enum { H = 128 }; public: BitmapBench(void* param, bool isOpaque, SkBitmap::Config c, - bool forceUpdate = false, bool bitmapVolatile = false, - int tx = -1, int ty = -1) + bool forceUpdate = false, bool bitmapVolatile = false) : INHERITED(param) , fIsOpaque(isOpaque) , fForceUpdate(forceUpdate) - , fTileX(tx) - , fTileY(ty) , fIsVolatile(bitmapVolatile) , fConfig(c) { } @@ -105,12 +98,6 @@ public: protected: virtual const char* onGetName() { fName.set("bitmap"); - if (fTileX >= 0) { - fName.appendf("_%s", gTileName[fTileX]); - if (fTileY != fTileX) { - fName.appendf("_%s", gTileName[fTileY]); - } - } fName.appendf("_%s%s", gConfigName[fConfig], fIsOpaque ? "" : "_A"); if (fForceUpdate) @@ -159,7 +146,14 @@ protected: const SkScalar x0 = SkIntToScalar(-bitmap.width() / 2); const SkScalar y0 = SkIntToScalar(-bitmap.height() / 2); - for (int i = 0; i < N; i++) { + int count = N; +#ifdef SK_RELEASE + // in DEBUG, N is always 1 + if (paint.getFlags() & SkPaint::kBicubicFilterBitmap_Flag) { + count /= BICUBIC_DUR_SCALE; + } +#endif + for (int i = 0; i < count; i++) { SkScalar x = x0 + rand.nextUScalar1() * dim.fX; SkScalar y = y0 + rand.nextUScalar1() * dim.fY; @@ -170,6 +164,17 @@ protected: } } + virtual float onGetDurationScale() SK_OVERRIDE { + SkPaint paint; + this->setupPaint(&paint); +#ifdef SK_DEBUG + return 1; +#else + return (paint.getFlags() & SkPaint::kBicubicFilterBitmap_Flag) ? + BICUBIC_DUR_SCALE : 1; +#endif + } + virtual void onDrawIntoBitmap(const SkBitmap& bm) { const int w = bm.width(); const int h = bm.height(); @@ -196,38 +201,53 @@ private: /** Explicitly invoke some filter types to improve coverage of acceleration procs. */ +enum Flags { + kScale_Flag = 1 << 0, + kRotate_Flag = 1 << 1, + kBilerp_Flag = 1 << 2, + kBicubic_Flag = 1 << 3, +}; + +static bool isBilerp(uint32_t flags) { + return (flags & (kBilerp_Flag | kBicubic_Flag)) == (kBilerp_Flag); +} + +static bool isBicubic(uint32_t flags) { + return (flags & (kBilerp_Flag | kBicubic_Flag)) == (kBilerp_Flag | kBicubic_Flag); +} + class FilterBitmapBench : public BitmapBench { - bool fScale; - bool fRotate; - bool fFilter; + uint32_t fFlags; SkString fFullName; enum { N = SkBENCHLOOP(300) }; public: FilterBitmapBench(void* param, bool isOpaque, SkBitmap::Config c, - bool forceUpdate = false, bool bitmapVolatile = false, - int tx = -1, int ty = -1, bool addScale = false, - bool addRotate = false, bool addFilter = false) - : INHERITED(param, isOpaque, c, forceUpdate, bitmapVolatile, tx, ty) - , fScale(addScale), fRotate(addRotate), fFilter(addFilter) { - + bool forceUpdate, bool isVolitile, uint32_t flags) + : INHERITED(param, isOpaque, c, forceUpdate, isVolitile) + , fFlags(flags) { } protected: virtual const char* onGetName() { fFullName.set(INHERITED::onGetName()); - if (fScale) + if (fFlags & kScale_Flag) { fFullName.append("_scale"); - if (fRotate) + } + if (fFlags & kRotate_Flag) { fFullName.append("_rotate"); - if (fFilter) - fFullName.append("_filter"); + } + if (isBilerp(fFlags)) { + fFullName.append("_bilerp"); + } else if (isBicubic(fFlags)) { + fFullName.append("_bicubic"); + } return fFullName.c_str(); } virtual void onDraw(SkCanvas* canvas) { SkISize dim = canvas->getDeviceSize(); - if (fScale) { + if (fFlags & kScale_Flag) { const SkScalar x = SkIntToScalar(dim.fWidth) / 2; const SkScalar y = SkIntToScalar(dim.fHeight) / 2; @@ -236,7 +256,7 @@ protected: canvas->scale(SK_Scalar1 * 99/100, SK_Scalar1 * 99/100); canvas->translate(-x, -y); } - if (fRotate) { + if (fFlags & kRotate_Flag) { const SkScalar x = SkIntToScalar(dim.fWidth) / 2; const SkScalar y = SkIntToScalar(dim.fHeight) / 2; @@ -245,7 +265,16 @@ protected: canvas->translate(-x, -y); } - this->setForceFilter(fFilter); + uint32_t orMask = 0; + uint32_t clearMask = SkPaint::kFilterBitmap_Flag | SkPaint::kBicubicFilterBitmap_Flag; + if (fFlags & kBilerp_Flag) { + orMask |= SkPaint::kFilterBitmap_Flag; + } + if (fFlags & kBicubic_Flag) { + orMask |= SkPaint::kBicubicFilterBitmap_Flag; + } + this->setPaintMasks(orMask, clearMask); + INHERITED::onDraw(canvas); } @@ -264,9 +293,8 @@ private: SourceAlpha fSourceAlpha; public: SourceAlphaBitmapBench(void* param, SourceAlpha alpha, SkBitmap::Config c, - bool forceUpdate = false, bool bitmapVolatile = false, - int tx = -1, int ty = -1) - : INHERITED(param, false, c, forceUpdate, bitmapVolatile, tx, ty) + bool forceUpdate = false, bool bitmapVolatile = false) + : INHERITED(param, false, c, forceUpdate, bitmapVolatile) , fSourceAlpha(alpha) { } @@ -354,16 +382,19 @@ DEF_BENCH( return new BitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, tr DEF_BENCH( return new BitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, false); ) // scale filter -> S32_opaque_D32_filter_DX_{SSE2,SSSE3} and Fact9 is also for S32_D16_filter_DX_SSE2 -DEF_BENCH( return new FilterBitmapBench(p, false, SkBitmap::kARGB_8888_Config, false, false, -1, -1, true, false, true); ) -DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, false, false, -1, -1, true, false, true); ) -DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, true, -1, -1, true, false, true); ) -DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, false, -1, -1, true, false, true); ) +DEF_BENCH( return new FilterBitmapBench(p, false, SkBitmap::kARGB_8888_Config, false, false, kScale_Flag | kBilerp_Flag); ) +DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, false, false, kScale_Flag | kBilerp_Flag); ) +DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, true, kScale_Flag | kBilerp_Flag); ) +DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, false, kScale_Flag | kBilerp_Flag); ) // scale rotate filter -> S32_opaque_D32_filter_DXDY_{SSE2,SSSE3} -DEF_BENCH( return new FilterBitmapBench(p, false, SkBitmap::kARGB_8888_Config, false, false, -1, -1, true, true, true); ) -DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, false, false, -1, -1, true, true, true); ) -DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, true, -1, -1, true, true, true); ) -DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, false, -1, -1, true, true, true); ) +DEF_BENCH( return new FilterBitmapBench(p, false, SkBitmap::kARGB_8888_Config, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); ) +DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); ) +DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, true, kScale_Flag | kRotate_Flag | kBilerp_Flag); ) +DEF_BENCH( return new FilterBitmapBench(p, true, SkBitmap::kARGB_8888_Config, true, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); ) + +DEF_BENCH( return new FilterBitmapBench(p, false, SkBitmap::kARGB_8888_Config, false, false, kScale_Flag | kBilerp_Flag | kBicubic_Flag); ) +DEF_BENCH( return new FilterBitmapBench(p, false, SkBitmap::kARGB_8888_Config, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag | kBicubic_Flag); ) // source alpha tests -> S32A_Opaque_BlitRow32_{arm,neon} DEF_BENCH( return new SourceAlphaBitmapBench(p, SourceAlphaBitmapBench::kOpaque_SourceAlpha, SkBitmap::kARGB_8888_Config); ) diff --git a/bench/SkBenchmark.cpp b/bench/SkBenchmark.cpp index 6afcd8e9f3..43f78b0f2d 100644 --- a/bench/SkBenchmark.cpp +++ b/bench/SkBenchmark.cpp @@ -20,6 +20,7 @@ SkBenchmark::SkBenchmark(void* defineDict) { fDither = SkTriState::kDefault; fHasStrokeWidth = false; fIsRendering = true; + fOrMask = fClearMask = 0; } const char* SkBenchmark::getName() { @@ -47,6 +48,8 @@ void SkBenchmark::setupPaint(SkPaint* paint) { paint->setAntiAlias(fForceAA); paint->setFilterBitmap(fForceFilter); + paint->setFlags((paint->getFlags() & ~fClearMask) | fOrMask); + if (SkTriState::kDefault != fDither) { paint->setDither(SkTriState::kTrue == fDither); } diff --git a/bench/SkBenchmark.h b/bench/SkBenchmark.h index 001b3ab679..404d4c3e7e 100644 --- a/bench/SkBenchmark.h +++ b/bench/SkBenchmark.h @@ -106,6 +106,22 @@ public: bool findDefine32(const char* key, int32_t* value) const; bool findDefineScalar(const char* key, SkScalar* value) const; + /** Assign masks for paint-flags. These will be applied when setupPaint() + * is called. + * + * Performs the following on the paint: + * uint32_t flags = paint.getFlags(); + * flags &= ~clearMask; + * flags |= orMask; + * paint.setFlags(flags); + */ + void setPaintMasks(uint32_t orMask, uint32_t clearMask) { + fOrMask = orMask; + fClearMask = clearMask; + } + + float getDurationScale() { return this->onGetDurationScale(); } + protected: virtual void setupPaint(SkPaint* paint); @@ -113,6 +129,13 @@ protected: virtual void onPreDraw() {} virtual void onDraw(SkCanvas*) = 0; virtual void onPostDraw() {} + // the caller will scale the computed duration by this value. It allows a + // slow bench to run fewer inner loops, but return the corresponding scale + // so that its reported duration can be compared against other benches. + // e.g. + // if I run 10x slower, I can run 1/10 the number of inner-loops, but + // return 10.0 for my durationScale, so I "report" the honest duration. + virtual float onGetDurationScale() { return 1; } virtual SkIPoint onGetSize(); /// Defaults to true. @@ -126,6 +149,7 @@ private: SkTriState::State fDither; bool fHasStrokeWidth; SkScalar strokeWidth; + uint32_t fOrMask, fClearMask; typedef SkRefCnt INHERITED; }; diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp index 865b771cfd..7aeeba63e8 100644 --- a/bench/benchmain.cpp +++ b/bench/benchmain.cpp @@ -915,7 +915,7 @@ int tool_main(int argc, char** argv) { SkPicture::kUsePathBoundsForClip_RecordingFlag); } - timer->start(); + timer->start(bench->getDurationScale()); if (NULL != canvas) { canvas->save(); }