Use new LOD approximation rules for OpenGL ES
[platform/upstream/VK-GL-CTS.git] / framework / common / tcuCPUWarmup.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
3  * ----------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief CPU warm-up utility, used to counteract CPU throttling.
22  *//*--------------------------------------------------------------------*/
23
24 #include "tcuCPUWarmup.hpp"
25 #include "deDefs.hpp"
26 #include "deMath.h"
27 #include "deClock.h"
28
29 #include <algorithm>
30
31 namespace tcu
32 {
33
34 namespace warmupCPUInternal
35 {
36
37 volatile Dummy g_dummy;
38
39 };
40
41 template <typename T, int Size>
42 static inline float floatMedian (const T (&v)[Size])
43 {
44         T temp[Size];
45         for (int i = 0; i < Size; i++)
46                 temp[i] = v[i];
47
48         std::sort(DE_ARRAY_BEGIN(temp), DE_ARRAY_END(temp));
49
50         return Size % 2 == 0
51                    ? 0.5f * ((float)temp[Size/2-1] + (float)temp[Size/2])
52                    : (float)temp[Size/2];
53 }
54
55 template <typename T, int Size>
56 static inline float floatRelativeMedianAbsoluteDeviation (const T (&v)[Size])
57 {
58         const float             median = floatMedian(v);
59         float                   absoluteDeviations[Size];
60
61         for (int i = 0; i < Size; i++)
62                 absoluteDeviations[i] = deFloatAbs((float)v[i] - median);
63
64         return floatMedian(absoluteDeviations) / median;
65 }
66
67 static inline float dummyComputation (float initial, int numIterations)
68 {
69         float   a = initial;
70         int             b = 123;
71
72         for (int i = 0; i < numIterations; i++)
73         {
74                 // Arbitrary computations.
75                 for (int j = 0; j < 4; j++)
76                 {
77                         a = deFloatCos(a + (float)b);
78                         b = (b + 63) % 107 + de::abs((int)(a*10.0f));
79                 }
80         }
81
82         return a + (float)b;
83 }
84
85 void warmupCPU (void)
86 {
87         float   dummy                           = *warmupCPUInternal::g_dummy.m_v;
88         int             computationSize         = 1;
89
90         // Do a rough calibration for computationSize to get dummyComputation's running time above a certain threshold.
91         while (computationSize < 1<<30) // \note This condition is unlikely to be met. The "real" loop exit is the break below.
92         {
93                 const float             singleMeasurementThreshold      = 10000.0f;
94                 const int               numMeasurements                         = 3;
95                 deInt64                 times[numMeasurements];
96
97                 for (int i = 0; i < numMeasurements; i++)
98                 {
99                         const deUint64 startTime = deGetMicroseconds();
100                         dummy = dummyComputation(dummy, computationSize);
101                         times[i] = (deInt64)(deGetMicroseconds() - startTime);
102                 }
103
104                 if (floatMedian(times) >= singleMeasurementThreshold)
105                         break;
106
107                 computationSize *= 2;
108         }
109
110         // Do dummyComputations until running time seems stable enough.
111         {
112                 const int                       maxNumMeasurements                                                      = 50;
113                 const int                       numConsecutiveMeasurementsRequired                      = 5;
114                 const float                     relativeMedianAbsoluteDeviationThreshold        = 0.05f;
115                 deInt64                         latestTimes[numConsecutiveMeasurementsRequired];
116
117                 for (int measurementNdx = 0;
118
119                          measurementNdx < maxNumMeasurements &&
120                          (measurementNdx < numConsecutiveMeasurementsRequired ||
121                           floatRelativeMedianAbsoluteDeviation(latestTimes) > relativeMedianAbsoluteDeviationThreshold);
122
123                          measurementNdx++)
124                 {
125                         const deUint64 startTime = deGetMicroseconds();
126                         dummy = dummyComputation(dummy, computationSize);
127                         latestTimes[measurementNdx % numConsecutiveMeasurementsRequired] = (deInt64)(deGetMicroseconds() - startTime);
128                 }
129         }
130
131         *warmupCPUInternal::g_dummy.m_v = dummy;
132 }
133
134 } // tcu