OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2015 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 */ | |
8 | |
9 #include "VisualInteractiveModule.h" | |
10 | |
11 #include "ProcStats.h" | |
12 #include "SkApplication.h" | |
13 #include "SkCanvas.h" | |
14 #include "SkCommandLineFlags.h" | |
15 #include "SkForceLinking.h" | |
16 #include "SkGraphics.h" | |
17 #include "SkGr.h" | |
18 #include "SkImageDecoder.h" | |
19 #include "SkOSFile.h" | |
20 #include "SkStream.h" | |
21 #include "Stats.h" | |
22 #include "gl/GrGLInterface.h" | |
23 | |
24 __SK_FORCE_IMAGE_DECODER_LINKING; | |
25 | |
26 static const int kGpuFrameLag = 5; | |
27 static const int kFrames = 5; | |
28 static const double kLoopMs = 5; | |
29 | |
30 VisualInteractiveModule::VisualInteractiveModule(VisualBench* owner) | |
31 : fCurrentFrame(0) | |
32 , fLoops(1) | |
33 , fState(kPreWarmLoops_State) | |
34 , fCurrentMeasurement(0) | |
35 , fBenchmark(nullptr) | |
36 , fOwner(SkRef(owner)) { | |
37 fBenchmarkStream.reset(new VisualBenchmarkStream); | |
38 | |
39 memset(fMeasurements, 0, sizeof(fMeasurements)); | |
40 } | |
41 | |
42 inline void VisualInteractiveModule::renderFrame(SkCanvas* canvas) { | |
43 fBenchmark->draw(fLoops, canvas); | |
44 this->drawStats(canvas); | |
45 canvas->flush(); | |
46 fOwner->present(); | |
47 } | |
48 | |
49 void VisualInteractiveModule::drawStats(SkCanvas* canvas) { | |
50 const float kPixelPerMs = 2.0f; | |
51 const int kDisplayWidth = 130; | |
52 const int kDisplayHeight = 100; | |
53 const int kPadding = 10; | |
54 | |
55 SkISize canvasSize = canvas->getDeviceSize(); | |
56 SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth - kDisplayWid th - kPadding), | |
57 SkIntToScalar(kPadding), | |
58 SkIntToScalar(kDisplayWidth), SkIntToScalar(k DisplayHeight)); | |
59 SkPaint paint; | |
60 canvas->clipRect(rect); | |
61 paint.setColor(SK_ColorBLACK); | |
62 canvas->drawRect(rect, paint); | |
63 // draw the 16ms line | |
64 paint.setColor(SK_ColorLTGRAY); | |
65 canvas->drawLine(rect.fLeft, rect.fBottom - 16.f*kPixelPerMs, | |
joshualitt
2015/09/14 14:07:45
I wonder if we want to make this 1000/60 'exactly.
jvanverth1
2015/09/14 16:21:38
Done.
| |
66 rect.fRight, rect.fBottom - 16.f*kPixelPerMs, paint); | |
67 paint.setColor(SK_ColorRED); | |
68 paint.setStyle(SkPaint::kStroke_Style); | |
69 canvas->drawRect(rect, paint); | |
70 | |
71 int x = SkScalarTruncToInt(rect.fLeft) + 3; | |
joshualitt
2015/09/14 14:07:45
Is this some kind of padding?
jvanverth1
2015/09/14 16:21:38
Done.
| |
72 const int xStep = 2; | |
73 const int startY = SkScalarTruncToInt(rect.fBottom); | |
74 int i = fCurrentMeasurement; | |
75 do { | |
76 int endY = startY - (int)(fMeasurements[i] * kPixelPerMs + 0.5); | |
joshualitt
2015/09/14 14:07:45
0.5?
jvanverth1
2015/09/14 16:21:38
Added comment
| |
77 canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY), | |
78 SkIntToScalar(x), SkIntToScalar(endY), paint); | |
79 i++; | |
80 i &= (kMeasurementCount - 1); // fast mod | |
81 x += xStep; | |
82 } while (i != fCurrentMeasurement); | |
83 | |
84 } | |
85 | |
86 bool VisualInteractiveModule::advanceRecordIfNecessary(SkCanvas* canvas) { | |
87 if (fBenchmark) { | |
88 return true; | |
89 } | |
90 | |
91 fBenchmark.reset(fBenchmarkStream->next()); | |
92 if (!fBenchmark) { | |
93 return false; | |
94 } | |
95 | |
96 // clear both buffers | |
97 canvas->clear(0xffffffff); | |
98 canvas->flush(); | |
99 fOwner->present(); | |
100 canvas->clear(0xffffffff); | |
joshualitt
2015/09/14 14:07:45
Hmm, might be nice to have a static function on Vi
jvanverth1
2015/09/14 16:21:38
How do I know what the buffer setup is?
| |
101 | |
102 fBenchmark->preDraw(); | |
103 | |
104 return true; | |
105 } | |
106 | |
107 void VisualInteractiveModule::draw(SkCanvas* canvas) { | |
108 if (!this->advanceRecordIfNecessary(canvas)) { | |
109 SkDebugf("Exiting VisualBench successfully\n"); | |
110 fOwner->closeWindow(); | |
111 return; | |
112 } | |
113 this->renderFrame(canvas); | |
114 switch (fState) { | |
115 case kPreWarmLoopsPerCanvasPreDraw_State: { | |
116 this->perCanvasPreDraw(canvas, kPreWarmLoops_State); | |
117 break; | |
118 } | |
119 case kPreWarmLoops_State: { | |
120 this->preWarm(kTuneLoops_State); | |
121 break; | |
122 } | |
123 case kTuneLoops_State: { | |
124 this->tuneLoops(canvas); | |
125 break; | |
126 } | |
127 case kPreTiming_State: { | |
128 fBenchmark->perCanvasPreDraw(canvas); | |
129 fCurrentFrame = 0; | |
130 fTimer.start(); | |
131 fState = kTiming_State; | |
132 // fall to next state | |
133 } | |
134 case kTiming_State: { | |
135 this->timing(canvas); | |
136 break; | |
137 } | |
138 case kAdvance_State: { | |
139 this->postDraw(canvas); | |
140 this->nextState(kPreWarmLoopsPerCanvasPreDraw_State); | |
141 break; | |
142 } | |
143 } | |
144 } | |
145 | |
146 inline void VisualInteractiveModule::nextState(State nextState) { | |
147 fState = nextState; | |
148 } | |
149 | |
150 void VisualInteractiveModule::perCanvasPreDraw(SkCanvas* canvas, State nextState ) { | |
151 fBenchmark->perCanvasPreDraw(canvas); | |
152 fCurrentFrame = 0; | |
153 this->nextState(nextState); | |
154 } | |
155 | |
156 void VisualInteractiveModule::preWarm(State nextState) { | |
157 if (fCurrentFrame >= kGpuFrameLag) { | |
158 // we currently time across all frames to make sure we capture all GPU w ork | |
159 this->nextState(nextState); | |
160 fCurrentFrame = 0; | |
161 fTimer.start(); | |
162 } else { | |
163 fCurrentFrame++; | |
164 } | |
165 } | |
166 | |
167 inline double VisualInteractiveModule::elapsed() { | |
168 fTimer.end(); | |
169 return fTimer.fWall; | |
170 } | |
171 | |
172 void VisualInteractiveModule::resetTimingState() { | |
173 fCurrentFrame = 0; | |
174 fTimer = WallTimer(); | |
175 fOwner->reset(); | |
176 } | |
177 | |
178 void VisualInteractiveModule::scaleLoops(double elapsedMs) { | |
179 // Scale back the number of loops | |
180 fLoops = (int)ceil(fLoops * kLoopMs / elapsedMs); | |
181 } | |
182 | |
183 inline void VisualInteractiveModule::tuneLoops(SkCanvas* canvas) { | |
joshualitt
2015/09/14 14:07:45
it'd be nice to figure out how to share this code,
jvanverth1
2015/09/14 16:21:38
Acknowledged.
| |
184 if (1 << 30 == fLoops) { | |
185 // We're about to wrap. Something's wrong with the bench. | |
186 SkDebugf("InnerLoops wrapped\n"); | |
187 fLoops = 0; | |
188 } else { | |
189 double elapsedMs = this->elapsed(); | |
190 if (elapsedMs > kLoopMs) { | |
191 this->scaleLoops(elapsedMs); | |
192 fBenchmark->perCanvasPostDraw(canvas); | |
193 this->nextState(kPreTiming_State); | |
194 } else { | |
195 fLoops *= 2; | |
196 this->nextState(kPreWarmLoops_State); | |
197 } | |
198 this->resetTimingState(); | |
199 } | |
200 } | |
201 | |
202 void VisualInteractiveModule::recordMeasurement() { | |
203 double measurement = this->elapsed() / (kFrames * fLoops); | |
204 fMeasurements[fCurrentMeasurement++] = measurement; | |
205 fCurrentMeasurement &= (kMeasurementCount-1); // fast mod | |
206 SkASSERT(fCurrentMeasurement < kMeasurementCount); | |
207 } | |
208 | |
209 void VisualInteractiveModule::postDraw(SkCanvas* canvas) { | |
210 fBenchmark->perCanvasPostDraw(canvas); | |
211 fBenchmark.reset(nullptr); | |
212 fLoops = 1; | |
213 } | |
214 | |
215 inline void VisualInteractiveModule::timing(SkCanvas* canvas) { | |
216 if (fCurrentFrame >= kFrames) { | |
217 this->recordMeasurement(); | |
218 fTimer.start(); | |
219 fCurrentFrame = 0; | |
220 } else { | |
221 fCurrentFrame++; | |
222 } | |
223 } | |
224 | |
225 bool VisualInteractiveModule::onHandleChar(SkUnichar c) { | |
226 if (' ' == c) { | |
227 this->nextState(kAdvance_State); | |
228 } | |
229 | |
230 return true; | |
231 } | |
OLD | NEW |