ClearBench.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Copyright 2018 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. // This benchmark attempts to measure the time to do a fullscreen clear, an axis-aligned partial
  8. // clear, and a clear restricted to an axis-aligned rounded rect. The fullscreen and axis-aligned
  9. // partial clears on the GPU should follow a fast path that maps to backend-specialized clear
  10. // operations, whereas the rounded-rect clear cannot be.
  11. #include "bench/Benchmark.h"
  12. #include "include/core/SkCanvas.h"
  13. #include "include/core/SkPaint.h"
  14. #include "include/core/SkRRect.h"
  15. #include "include/core/SkRect.h"
  16. #include "include/effects/SkGradientShader.h"
  17. #include "src/gpu/GrRenderTargetContext.h"
  18. static sk_sp<SkShader> make_shader() {
  19. static const SkPoint kPts[] = {{0, 0}, {10, 10}};
  20. static const SkColor kColors[] = {SK_ColorBLUE, SK_ColorWHITE};
  21. return SkGradientShader::MakeLinear(kPts, kColors, nullptr, 2, SkTileMode::kClamp);
  22. }
  23. class ClearBench : public Benchmark {
  24. public:
  25. enum ClearType {
  26. kFull_ClearType,
  27. kPartial_ClearType,
  28. kComplex_ClearType
  29. };
  30. ClearBench(ClearType type) : fType(type) {}
  31. protected:
  32. const char* onGetName() override {
  33. switch(fType) {
  34. case kFull_ClearType:
  35. return "Clear-Full";
  36. case kPartial_ClearType:
  37. return "Clear-Partial";
  38. case kComplex_ClearType:
  39. return "Clear-Complex";
  40. }
  41. SkASSERT(false);
  42. return "Unreachable";
  43. }
  44. void onDraw(int loops, SkCanvas* canvas) override {
  45. static const SkRect kPartialClip = SkRect::MakeLTRB(50, 50, 400, 400);
  46. static const SkRRect kComplexClip = SkRRect::MakeRectXY(kPartialClip, 15, 15);
  47. // Small to limit fill cost, but intersects the clips to confound batching
  48. static const SkRect kInterruptRect = SkRect::MakeXYWH(200, 200, 3, 3);
  49. // For the draw that sits between consecutive clears, use a shader that is simple but
  50. // requires local coordinates so that Ganesh does not convert it into a solid color rect,
  51. // which could then turn into a scissored-clear behind the scenes.
  52. SkPaint interruptPaint;
  53. interruptPaint.setShader(make_shader());
  54. GrRenderTargetContext* rtc = canvas->internal_private_accessTopLayerRenderTargetContext();
  55. if (rtc) {
  56. // Tell the GrRenderTargetContext to not reset its draw op list on a fullscreen clear.
  57. // If we don't do this, fullscreen clear ops would be created and constantly discard the
  58. // previous iteration's op so execution would only invoke one actual clear on the GPU
  59. // (not what we want to measure).
  60. rtc->testingOnly_SetPreserveOpsOnFullClear();
  61. }
  62. for (int i = 0; i < loops; i++) {
  63. canvas->save();
  64. switch(fType) {
  65. case kPartial_ClearType:
  66. canvas->clipRect(kPartialClip);
  67. break;
  68. case kComplex_ClearType:
  69. canvas->clipRRect(kComplexClip);
  70. break;
  71. case kFull_ClearType:
  72. // Don't add any extra clipping, since it defaults to the entire "device"
  73. break;
  74. }
  75. // The clear we care about measuring
  76. canvas->clear(SK_ColorBLUE);
  77. canvas->restore();
  78. // Perform as minimal a draw as possible that intersects with the clear region in
  79. // order to prevent the clear ops from being batched together.
  80. canvas->drawRect(kInterruptRect, interruptPaint);
  81. }
  82. }
  83. private:
  84. ClearType fType;
  85. };
  86. DEF_BENCH( return new ClearBench(ClearBench::kFull_ClearType); )
  87. DEF_BENCH( return new ClearBench(ClearBench::kPartial_ClearType); )
  88. DEF_BENCH( return new ClearBench(ClearBench::kComplex_ClearType); )