1 /*
2  * Copyright (C) 2010-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 com.android.perftest;
18 
19 import java.io.Writer;
20 import java.io.BufferedWriter;
21 import java.io.FileWriter;
22 import java.io.IOException;
23 import java.io.File;
24 import java.io.FileOutputStream;
25 import java.io.OutputStream;
26 
27 import android.os.Environment;
28 import android.content.res.Resources;
29 import android.renderscript.*;
30 import android.renderscript.Element.DataKind;
31 import android.renderscript.Element.DataType;
32 import android.renderscript.Allocation.MipmapControl;
33 import android.renderscript.Program.TextureType;
34 import android.renderscript.RenderScript.RSMessageHandler;
35 import android.renderscript.Sampler.Value;
36 import android.renderscript.Mesh.Primitive;
37 import android.renderscript.Matrix4f;
38 import android.renderscript.ProgramVertexFixedFunction;
39 
40 import android.util.Log;
41 
42 
43 public class RsBenchRS {
44 
45     private static final String TAG = "RsBenchRS";
46     int mWidth;
47     int mHeight;
48     int mLoops;
49     int mCurrentLoop;
50 
51     int mBenchmarkDimX;
52     int mBenchmarkDimY;
53 
RsBenchRS()54     public RsBenchRS() {
55     }
56 
init(RenderScriptGL rs, Resources res, int width, int height, int loops)57     public void init(RenderScriptGL rs, Resources res, int width, int height, int loops) {
58         mRS = rs;
59         mRes = res;
60         mWidth = width;
61         mHeight = height;
62         mMode = 0;
63         mLoops = loops;
64         mCurrentLoop = 0;
65         mBenchmarkDimX = 1280;
66         mBenchmarkDimY = 720;
67         initRS();
68     }
69 
70     private boolean stopTest = false;
71 
72     private Resources mRes;
73     private RenderScriptGL mRS;
74 
75     private ProgramStore mProgStoreBlendNone;
76     private ProgramStore mProgStoreBlendAlpha;
77 
78     private ProgramFragment mProgFragmentTexture;
79     private ProgramFragment mProgFragmentColor;
80 
81     private ProgramVertex mProgVertex;
82     private ProgramVertexFixedFunction.Constants mPVA;
83     private ProgramVertexFixedFunction.Constants mPvProjectionAlloc;
84 
85     private ScriptC_rsbench mScript;
86 
87     ScriptField_TestScripts_s.Item[] mIndividualTests;
88 
89     int mMode;
90 
91     String[] mTestNames;
92     float[] mLocalTestResults;
93 
createZeroTerminatedAlloc(RenderScript rs, String str, int usage)94     static Allocation createZeroTerminatedAlloc(RenderScript rs,
95                                                 String str,
96                                                 int usage) {
97         byte[] allocArray = null;
98         try {
99             allocArray = str.getBytes("UTF-8");
100             byte[] allocArrayZero = new byte[allocArray.length + 1];
101             System.arraycopy(allocArray, 0, allocArrayZero, 0, allocArray.length);
102             allocArrayZero[allocArrayZero.length - 1] = '\0';
103             Allocation alloc = Allocation.createSized(rs, Element.U8(rs),
104                                                       allocArrayZero.length, usage);
105             alloc.copyFrom(allocArrayZero);
106             return alloc;
107         }
108         catch (Exception e) {
109             throw new RSRuntimeException("Could not convert string to utf-8.");
110         }
111 
112     }
113 
appendTests(RsBenchBaseTest testSet)114     void appendTests(RsBenchBaseTest testSet) {
115         ScriptField_TestScripts_s.Item[] newTests = testSet.getTests();
116         if (mIndividualTests != null) {
117             ScriptField_TestScripts_s.Item[] combined;
118             combined = new ScriptField_TestScripts_s.Item[newTests.length + mIndividualTests.length];
119             System.arraycopy(mIndividualTests, 0, combined, 0, mIndividualTests.length);
120             System.arraycopy(newTests, 0, combined, mIndividualTests.length, newTests.length);
121             mIndividualTests = combined;
122         } else {
123             mIndividualTests = newTests;
124         }
125 
126         String[] newNames = testSet.getTestNames();
127         if (mTestNames != null) {
128             String[] combinedNames;
129             combinedNames = new String[newNames.length + mTestNames.length];
130             System.arraycopy(mTestNames, 0, combinedNames, 0, mTestNames.length);
131             System.arraycopy(newNames, 0, combinedNames, mTestNames.length, newNames.length);
132             mTestNames = combinedNames;
133         } else {
134             mTestNames = newNames;
135         }
136     }
137 
createTestAllocation()138     void createTestAllocation() {
139         int numTests = mIndividualTests.length;
140         mLocalTestResults = new float[numTests];
141         ScriptField_TestScripts_s allTests;
142         allTests = new ScriptField_TestScripts_s(mRS, numTests);
143         for (int i = 0; i < numTests; i ++) {
144             allTests.set(mIndividualTests[i], i, false);
145         }
146         allTests.copyAll();
147         mScript.bind_gTestScripts(allTests);
148     }
149 
saveTestResults()150     private void saveTestResults() {
151         String state = Environment.getExternalStorageState();
152         if (!Environment.MEDIA_MOUNTED.equals(state)) {
153             Log.v(TAG, "sdcard is read only");
154             return;
155         }
156         File sdCard = Environment.getExternalStorageDirectory();
157         if (!sdCard.canWrite()) {
158             Log.v(TAG, "ssdcard is read only");
159             return;
160         }
161 
162         File resultFile = new File(sdCard, "rsbench_result" + mCurrentLoop + ".csv");
163         resultFile.setWritable(true, false);
164 
165         try {
166             BufferedWriter results = new BufferedWriter(new FileWriter(resultFile));
167             for (int i = 0; i < mLocalTestResults.length; i ++) {
168                 results.write(mTestNames[i] + ", " + mLocalTestResults[i] + ",\n");
169             }
170             results.close();
171             Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
172         } catch (IOException e) {
173             Log.v(TAG, "Unable to write result file " + e.getMessage());
174         }
175     }
176 
177     /**
178      * Create a message handler to handle message sent from the script
179      */
180     protected RSMessageHandler mRsMessage = new RSMessageHandler() {
181         public void run() {
182             if (mID == mScript.get_RS_MSG_RESULTS_READY()) {
183                 for (int i = 0; i < mLocalTestResults.length; i ++) {
184                     mLocalTestResults[i] = Float.intBitsToFloat(mData[i]);
185                 }
186                 saveTestResults();
187                 if (mLoops > 0) {
188                     mCurrentLoop ++;
189                     mCurrentLoop = mCurrentLoop % mLoops;
190                 }
191                 return;
192 
193             } else if (mID == mScript.get_RS_MSG_TEST_DONE()) {
194                 synchronized(this) {
195                     stopTest = true;
196                     this.notifyAll();
197                 }
198                 return;
199             } else {
200                 Log.v(TAG, "Perf test got unexpected message");
201                 return;
202             }
203         }
204     };
205 
206     /**
207      * Wait for message from the script
208      */
testIsFinished()209     public boolean testIsFinished() {
210         synchronized(this) {
211             while (true) {
212                 if (stopTest) {
213                     return true;
214                 } else {
215                     try {
216                         this.wait(60*1000);
217                     } catch (InterruptedException e) {
218                         e.printStackTrace();
219                     }
220                 }
221             }
222         }
223     }
224 
initProgramFragment()225     private void initProgramFragment() {
226 
227         ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
228         texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
229                               ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
230         mProgFragmentTexture = texBuilder.create();
231         mProgFragmentTexture.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
232 
233         ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
234         colBuilder.setVaryingColor(false);
235         mProgFragmentColor = colBuilder.create();
236 
237         mScript.set_gProgFragmentTexture(mProgFragmentTexture);
238     }
239 
initProgramVertex()240     private void initProgramVertex() {
241         ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
242         mProgVertex = pvb.create();
243 
244         mPVA = new ProgramVertexFixedFunction.Constants(mRS);
245         ((ProgramVertexFixedFunction)mProgVertex).bindConstants(mPVA);
246         Matrix4f proj = new Matrix4f();
247         proj.loadOrthoWindow(mBenchmarkDimX, mBenchmarkDimY);
248         mPVA.setProjection(proj);
249 
250         mScript.set_gProgVertex(mProgVertex);
251     }
252 
strlen(byte[] array)253     private int strlen(byte[] array) {
254         int count = 0;
255         while(count < array.length && array[count] != 0) {
256             count ++;
257         }
258         return count;
259     }
260 
setDebugMode(int num)261     public void setDebugMode(int num) {
262         mScript.invoke_setDebugMode(num);
263     }
264 
setBenchmarkMode(int benchNum)265     public void setBenchmarkMode(int benchNum) {
266         mScript.invoke_setBenchmarkMode(benchNum);
267     }
268 
pause(boolean pause)269     public void pause(boolean pause) {
270         mScript.set_gPauseRendering(pause);
271     }
272 
initRS()273     private void initRS() {
274 
275         mScript = new ScriptC_rsbench(mRS, mRes, R.raw.rsbench);
276         mRS.bindRootScript(mScript);
277 
278         mRS.setMessageHandler(mRsMessage);
279 
280         mScript.set_gMaxLoops(mLoops);
281 
282         initProgramVertex();
283         initProgramFragment();
284         mScript.set_gFontSerif(Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8));
285 
286         Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS));
287         b.setX(mBenchmarkDimX).setY(mBenchmarkDimY);
288         Allocation offscreen = Allocation.createTyped(mRS,
289                                                       b.create(),
290                                                       Allocation.USAGE_GRAPHICS_TEXTURE |
291                                                       Allocation.USAGE_GRAPHICS_RENDER_TARGET);
292         mScript.set_gRenderBufferColor(offscreen);
293 
294         b = new Type.Builder(mRS,
295                              Element.createPixel(mRS, DataType.UNSIGNED_16,
296                              DataKind.PIXEL_DEPTH));
297         b.setX(mBenchmarkDimX).setY(mBenchmarkDimY);
298         offscreen = Allocation.createTyped(mRS,
299                                            b.create(),
300                                            Allocation.USAGE_GRAPHICS_RENDER_TARGET);
301         mScript.set_gRenderBufferDepth(offscreen);
302         mScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
303 
304         RsBenchBaseTest test = new TextTest();
305         if (test.init(mRS, mRes)) {
306             appendTests(test);
307         }
308         test = new FillTest();
309         if (test.init(mRS, mRes)) {
310             appendTests(test);
311         }
312         test = new MeshTest();
313         if (test.init(mRS, mRes)) {
314             appendTests(test);
315         }
316         test = new TorusTest();
317         if (test.init(mRS, mRes)) {
318             appendTests(test);
319         }
320         test = new UiTest();
321         if (test.init(mRS, mRes)) {
322             appendTests(test);
323         }
324         createTestAllocation();
325 
326         mScript.set_gLoadComplete(true);
327     }
328 }
329