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 #include "TimingStateMachine.h" 9 10 #include "SkCanvas.h" 11 #include "SkCommandLineFlags.h" 12 13 DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU is allowed to lag."); 14 DEFINE_int32(frames, 5, "Number of frames of each skp to render per sample."); 15 DEFINE_double(loopMs, 5, "Each benchmark will be tuned until it takes loopsMs millseconds."); 16 17 static double now_ms() { return SkTime::GetNSecs() * 1e-6; } 18 19 TimingStateMachine::TimingStateMachine() 20 : fCurrentFrame(0) 21 , fLoops(1) 22 , fLastMeasurement(0.) 23 , fState(kPreWarm_State) 24 , fInnerState(kTuning_InnerState) { 25 } 26 27 TimingStateMachine::ParentEvents TimingStateMachine::nextFrame(bool preWarmBetweenSamples) { 28 ParentEvents parentEvent = kTiming_ParentEvents; 29 switch (fState) { 30 case kPreWarm_State: { 31 if (fCurrentFrame >= FLAGS_gpuFrameLag) { 32 fCurrentFrame = 0; 33 fStartTime = now_ms(); 34 fState = kTiming_State; 35 } else { 36 fCurrentFrame++; 37 } 38 break; 39 } 40 case kTiming_State: { 41 switch (fInnerState) { 42 case kTuning_InnerState: { 43 if (1 << 30 == fLoops) { 44 // We're about to wrap. Something's wrong with the bench. 45 SkDebugf("InnerLoops wrapped\n"); 46 fLoops = 1; 47 } else { 48 double elapsedMs = now_ms() - fStartTime; 49 if (elapsedMs < FLAGS_loopMs) { 50 fLoops *= 2; 51 } else { 52 fInnerState = kTiming_InnerState; 53 } 54 fState = kPreWarm_State; 55 fCurrentFrame = 0; 56 parentEvent = kReset_ParentEvents; 57 } 58 break; 59 } 60 case kTiming_InnerState: { 61 if (fCurrentFrame >= FLAGS_frames) { 62 double now = now_ms(); 63 fLastMeasurement = (now - fStartTime) / (FLAGS_frames * fLoops); 64 fCurrentFrame = 0; 65 parentEvent = kTimingFinished_ParentEvents; 66 if (preWarmBetweenSamples) { 67 fState = kPreWarm_State; 68 } else { 69 fStartTime = now; 70 } 71 } else { 72 fCurrentFrame++; 73 } 74 break; 75 } 76 } 77 } 78 break; 79 } 80 return parentEvent; 81 } 82 83 void TimingStateMachine::nextBenchmark() { 84 fLoops = 1; 85 fInnerState = kTuning_InnerState; 86 fState = kPreWarm_State; 87 } 88