1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.openglperf.cts;
18 
19 import android.app.Instrumentation;
20 import android.content.Intent;
21 import android.test.ActivityInstrumentationTestCase2;
22 import android.util.Log;
23 
24 public class GlVboPerfTest extends
25         ActivityInstrumentationTestCase2<GlPlanetsActivity> {
26     private static final String TAG = "GlVboPerfTest";
27     private static final int NUM_FRAMES_TO_RENDER = 100;
28     private static final long RENDERING_TIMEOUT = 5 * 60;
29     // 30% of fps_no_vbo is allowed to compensate variations in measurement
30     private static final float FPS_COMPARISON_MARGIN = 0.3f;
31     // the worst case should be above 70% of the best case
32     private static final float FPS_MIN_MAX_COMPARISON_PERCENTILE = 0.7f;
33 
34     private float mFps;
35     private int mNumTriangles;
36 
GlVboPerfTest()37     public GlVboPerfTest() {
38         super(GlPlanetsActivity.class);
39     }
40 
testVboWithVaryingIndexBufferNumbers()41     public void testVboWithVaryingIndexBufferNumbers() throws Exception {
42         final int[] numIndexBuffers = {1, 10, 100, 200, 400}; // per vertex buffer
43         float[] fpsVbo = new float[numIndexBuffers.length];
44         float[] fpsNonVbo = new float[numIndexBuffers.length];
45 
46         for (int i = 0; i < numIndexBuffers.length; i++) {
47             runRendering(0, true, true, numIndexBuffers[i]);
48             fpsVbo[i] = mFps;
49             runRendering(0, true, false, numIndexBuffers[i]);
50             fpsNonVbo[i] = mFps;
51         }
52         StringBuilder msgIndex = new StringBuilder();
53         StringBuilder msgVbo = new StringBuilder();
54         StringBuilder msgNonVbo = new StringBuilder();
55         msgIndex.append("index buffer ");
56         msgVbo.append("Vbo ");
57         msgNonVbo.append("Non-Vbo ");
58         for (int i = 0; i < numIndexBuffers.length; i++) {
59             msgIndex.append(numIndexBuffers[i]).append(" ");
60             msgVbo.append(fpsVbo[i]).append(" ");
61             msgNonVbo.append(fpsNonVbo[i]).append(" ");
62         }
63         Log.i(TAG, msgIndex.toString());
64         Log.i(TAG, msgVbo.toString());
65         Log.i(TAG, msgNonVbo.toString());
66 
67         float[] minMaxVbo = findMinMax(fpsVbo);
68         float[] minMaxNonVbo = findMinMax(fpsNonVbo);
69 
70         float delta = minMaxVbo[1] - (1f - FPS_COMPARISON_MARGIN)
71                 * minMaxNonVbo[1];
72         assertTrue("VBO performance worse than non-VBO " + msgVbo + msgNonVbo, delta > 0f);
73         assertTrue(
74                 "Too much FPS drop for VBO case " + msgVbo,
75                 minMaxVbo[0] > (FPS_MIN_MAX_COMPARISON_PERCENTILE * minMaxVbo[1]));
76         assertTrue(
77                 "Too much FPS drop for No VBO case " + msgNonVbo,
78                 minMaxNonVbo[0] > (FPS_MIN_MAX_COMPARISON_PERCENTILE * minMaxNonVbo[1]));
79     }
80 
testVboVsNonVboPerfGeometry0()81     public void testVboVsNonVboPerfGeometry0() throws Exception {
82         doRunVboVsNonVboPerfTest(0);
83     }
84 
testVboVsNonVboPerfGeometry1()85     public void testVboVsNonVboPerfGeometry1() throws Exception {
86         doRunVboVsNonVboPerfTest(4);
87     }
88 
runRendering(int numPlanets, boolean useVboVertex, boolean useVboIndex, int numIndexBuffers)89     private void runRendering(int numPlanets, boolean useVboVertex, boolean useVboIndex,
90             int numIndexBuffers) throws Exception {
91         Intent intent = new Intent();
92         intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_NUM_FRAMES,
93                 NUM_FRAMES_TO_RENDER);
94         intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_NUM_PLANETS, numPlanets);
95         intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_USE_VBO_VERTICES, useVboVertex);
96         intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_USE_VBO_INDICES, useVboIndex);
97         intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_NUM_INDEX_BUFFERS, numIndexBuffers);
98 
99         setActivityIntent(intent);
100         final GlPlanetsActivity activity = getActivity();
101         boolean waitResult = activity
102                 .waitForGlPlanetsCompletionWithTimeout(RENDERING_TIMEOUT);
103         assertTrue("timeout while waiting for rendering completion", waitResult);
104 
105         mFps = activity.getAverageFps();
106         mNumTriangles = activity.getNumTriangles();
107 
108         cleanUpActivity();
109     }
110 
cleanUpActivity()111     private void cleanUpActivity()  throws Exception {
112         // finish the current activity and do clean-up so that a new activity
113         // can be launched in the same test run
114         super.tearDown();
115         super.setUp();
116         // wait until clean-up / set-up finishes
117         getInstrumentation().waitForIdleSync();
118     }
119 
doRunVboVsNonVboPerfTest(int numPlanets)120     private void doRunVboVsNonVboPerfTest(int numPlanets) throws Exception {
121         runRendering(numPlanets, true, true, 1); // VBO
122         int numTrianglesVbo = mNumTriangles;
123         float fpsVbo = mFps;
124         runRendering(numPlanets, false, false, 1); // non-VBO
125 
126         assertTrue("Number of triangles mismatch",
127                 numTrianglesVbo == mNumTriangles);
128 
129         // Margin amount of error is allowed due to measuring irregularity
130         float delta = fpsVbo - (1f - FPS_COMPARISON_MARGIN) * mFps;
131         StringBuilder testMsg = new StringBuilder();
132         testMsg.append("VBO performance worse than non-VBO ").append(fpsVbo).append(" ");
133         testMsg.append(mFps);
134         assertTrue(testMsg.toString(), delta > 0f);
135     }
136 
findMinMax(float[] data)137     private float[] findMinMax(float[] data) {
138         float min = data[0];
139         float max = data[0];
140 
141         for (int i = 1; i < data.length; i++) {
142             if (data[i] > max) max = data[i];
143             if (data[i] < min) min = data[i];
144         }
145         float[] result = {min, max};
146         return result;
147     }
148 }
149