Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c8e60ab

Browse files
author
George Wright
committed
Add a new flow_benchmarks test suite that will allow us to microbenchmark all the rasterops defined in
our DisplayList format on both CPU and GPU canvases.
1 parent 98e3216 commit c8e60ab

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed

BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ group("flutter") {
106106
# Compile all benchmark targets if enabled.
107107
if (enable_unittests && !is_win) {
108108
public_deps += [
109+
"//flutter/flow:flow_benchmarks",
109110
"//flutter/fml:fml_benchmarks",
110111
"//flutter/lib/ui:ui_benchmarks",
111112
"//flutter/shell/common:shell_benchmarks",

flow/BUILD.gn

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,31 @@ if (enable_unittests) {
192192
defines += [ "_USE_MATH_DEFINES" ]
193193
}
194194
}
195+
196+
fixtures_location("flow_benchmarks_fixtures") {
197+
assets_dir = "$target_gen_dir/"
198+
}
199+
200+
executable("flow_benchmarks") {
201+
testonly = true
202+
203+
sources = [ "display_list_benchmarks.cc" ]
204+
205+
deps = [
206+
":flow",
207+
":flow_benchmarks_fixtures",
208+
":flow_testing",
209+
"//flutter/benchmarking",
210+
"//flutter/common/graphics",
211+
"//flutter/fml",
212+
"//flutter/testing:skia",
213+
"//flutter/testing:testing_lib",
214+
"//third_party/dart/runtime:libdart_jit", # for tracing
215+
"//third_party/skia",
216+
]
217+
218+
if (is_mac) {
219+
deps += [ "//flutter/testing:metal" ]
220+
}
221+
}
195222
}

flow/display_list_benchmarks.cc

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/benchmarking/benchmarking.h"
6+
#include "flutter/flow/display_list.h"
7+
#include "flutter/fml/mapping.h"
8+
#include "flutter/testing/test_metal_context.h"
9+
#include "flutter/testing/test_metal_surface.h"
10+
#include "flutter/testing/testing.h"
11+
12+
#include "third_party/skia/include/core/SkPoint.h"
13+
#include "third_party/skia/include/core/SkSurface.h"
14+
15+
namespace flutter {
16+
17+
namespace testing {
18+
19+
class CanvasProvider {
20+
public:
21+
virtual const std::string BackendName() = 0;
22+
virtual sk_sp<SkSurface> GetSurface() = 0;
23+
24+
virtual bool Snapshot(std::string filename) {
25+
auto image = GetSurface()->makeImageSnapshot();
26+
if (!image) {
27+
return false;
28+
}
29+
auto raster = image->makeRasterImage();
30+
if (!raster) {
31+
return false;
32+
}
33+
auto data = raster->encodeToData();
34+
if (!data) {
35+
return false;
36+
}
37+
fml::NonOwnedMapping mapping(static_cast<const uint8_t*>(data->data()),
38+
data->size());
39+
return WriteAtomically(OpenFixturesDirectory(), filename.c_str(), mapping);
40+
}
41+
};
42+
43+
class SoftwareCanvasProvider : public CanvasProvider {
44+
public:
45+
SoftwareCanvasProvider(const size_t width, const size_t height) {
46+
surface_ = SkSurface::MakeRasterN32Premul(width, height);
47+
surface_->getCanvas()->clear(SK_ColorTRANSPARENT);
48+
}
49+
50+
sk_sp<SkSurface> GetSurface() override { return surface_; }
51+
52+
const std::string BackendName() override { return "Software"; }
53+
54+
private:
55+
sk_sp<SkSurface> surface_;
56+
};
57+
58+
class MetalCanvasProvider : public CanvasProvider {
59+
public:
60+
MetalCanvasProvider(const size_t width, const size_t height) {
61+
metal_context_ = std::make_unique<TestMetalContext>();
62+
metal_surface_ =
63+
TestMetalSurface::Create(*metal_context_, SkISize::Make(width, height));
64+
metal_surface_->GetSurface()->getCanvas()->clear(SK_ColorTRANSPARENT);
65+
}
66+
67+
sk_sp<SkSurface> GetSurface() override {
68+
return metal_surface_->GetSurface();
69+
}
70+
71+
const std::string BackendName() override { return "Metal"; }
72+
73+
private:
74+
std::unique_ptr<TestMetalContext> metal_context_;
75+
std::unique_ptr<TestMetalSurface> metal_surface_;
76+
};
77+
78+
template <class T>
79+
void DrawLine(benchmark::State& state) {
80+
DisplayListBuilder builder;
81+
T canvas_provider(state.range(0), state.range(0));
82+
83+
auto canvas = canvas_provider.GetSurface()->getCanvas();
84+
85+
// Always draw 10k lines regardless of the line length requested
86+
size_t length = state.range(0);
87+
for (size_t i = 0; i < 10000; i++) {
88+
// The (approximate) line lengths are passed to us via the benchmark state
89+
// object, so that we can benchmark the performance of drawLine and how it
90+
// differs based on line length
91+
builder.drawLine(SkPoint::Make(i % length, 0),
92+
SkPoint::Make(length - i % length, length));
93+
}
94+
95+
auto displaylist = builder.Build();
96+
97+
// We only want to time the actual rasterization.
98+
while (state.KeepRunning()) {
99+
displaylist->RenderTo(canvas);
100+
canvas->flush();
101+
}
102+
103+
auto filename = canvas_provider.BackendName() + "-DrawLine-" +
104+
std::to_string(state.range(0)) + ".png";
105+
canvas_provider.Snapshot(filename);
106+
}
107+
108+
BENCHMARK_TEMPLATE(DrawLine, SoftwareCanvasProvider)
109+
->RangeMultiplier(2)
110+
->Range(16, 2048)
111+
->Unit(benchmark::kMillisecond);
112+
113+
BENCHMARK_TEMPLATE(DrawLine, MetalCanvasProvider)
114+
->RangeMultiplier(2)
115+
->Range(16, 2048)
116+
->UseRealTime()
117+
->Unit(benchmark::kMillisecond);
118+
119+
} // namespace testing
120+
} // namespace flutter

0 commit comments

Comments
 (0)