blob: 85aab42ba9763ef3f3f7e6aeec1fbd61934e0ade [file] [log] [blame]
joshualitt98d2e2f2015-10-05 07:23:30 -07001/*
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#include "TimingStateMachine.h"
9
10#include "SkCanvas.h"
11#include "SkCommandLineFlags.h"
12
13DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU is allowed to lag.");
14DEFINE_int32(frames, 5, "Number of frames of each skp to render per sample.");
15DEFINE_double(loopMs, 5, "Each benchmark will be tuned until it takes loopsMs millseconds.");
16
17TimingStateMachine::TimingStateMachine()
18 : fCurrentFrame(0)
19 , fLoops(1)
20 , fLastMeasurement(0.)
joshualittcb54e8e2015-10-05 13:58:26 -070021 , fState(kPreWarm_State)
22 , fInnerState(kTuning_InnerState) {
joshualitt98d2e2f2015-10-05 07:23:30 -070023}
24
joshualittcb54e8e2015-10-05 13:58:26 -070025TimingStateMachine::ParentEvents TimingStateMachine::nextFrame(bool preWarmBetweenSamples) {
26 ParentEvents parentEvent = kTiming_ParentEvents;
joshualitt98d2e2f2015-10-05 07:23:30 -070027 switch (fState) {
joshualittcb54e8e2015-10-05 13:58:26 -070028 case kPreWarm_State: {
29 if (fCurrentFrame >= FLAGS_gpuFrameLag) {
30 fCurrentFrame = 0;
31 fTimer.start();
32 fState = kTiming_State;
33 } else {
34 fCurrentFrame++;
35 }
36 break;
37 }
38 case kTiming_State: {
39 switch (fInnerState) {
40 case kTuning_InnerState: {
41 if (1 << 30 == fLoops) {
42 // We're about to wrap. Something's wrong with the bench.
43 SkDebugf("InnerLoops wrapped\n");
44 fLoops = 1;
45 } else {
46 double elapsedMs = this->elapsed();
47 if (elapsedMs < FLAGS_loopMs) {
48 fLoops *= 2;
49 } else {
50 fInnerState = kTiming_InnerState;
joshualittcb54e8e2015-10-05 13:58:26 -070051 }
joshualitte1f82962015-10-06 08:25:15 -070052 fState = kPreWarm_State;
joshualittcb54e8e2015-10-05 13:58:26 -070053 this->resetTimingState();
54 parentEvent = kReset_ParentEvents;
55 }
56 break;
57 }
58 case kTiming_InnerState: {
59 if (fCurrentFrame >= FLAGS_frames) {
60 this->recordMeasurement();
61 this->resetTimingState();
62 parentEvent = kTimingFinished_ParentEvents;
63 if (preWarmBetweenSamples) {
64 fState = kPreWarm_State;
65 } else {
66 fTimer.start(); // start timing again, don't change state
67 }
68 } else {
69 fCurrentFrame++;
70 }
71 break;
72 }
73 }
74 }
75 break;
joshualitt98d2e2f2015-10-05 07:23:30 -070076 }
joshualittcb54e8e2015-10-05 13:58:26 -070077 return parentEvent;
joshualitt98d2e2f2015-10-05 07:23:30 -070078}
79
80inline double TimingStateMachine::elapsed() {
81 fTimer.end();
82 return fTimer.fWall;
83}
84
85void TimingStateMachine::resetTimingState() {
86 fCurrentFrame = 0;
87 fTimer = WallTimer();
88}
89
joshualitt98d2e2f2015-10-05 07:23:30 -070090void TimingStateMachine::recordMeasurement() {
91 fLastMeasurement = this->elapsed() / (FLAGS_frames * fLoops);
92}
93
joshualittc603c142015-10-15 07:18:29 -070094void TimingStateMachine::nextBenchmark() {
joshualittdc5db592015-10-05 13:24:55 -070095 fLoops = 1;
joshualittcb54e8e2015-10-05 13:58:26 -070096 fInnerState = kTuning_InnerState;
97 fState = kPreWarm_State;
joshualittdc5db592015-10-05 13:24:55 -070098}