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 54 public RsBenchRS() { 55 } 56 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 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 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 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 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 */ 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 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 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 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 261 public void setDebugMode(int num) { 262 mScript.invoke_setDebugMode(num); 263 } 264 265 public void setBenchmarkMode(int benchNum) { 266 mScript.invoke_setBenchmarkMode(benchNum); 267 } 268 269 public void pause(boolean pause) { 270 mScript.set_gPauseRendering(pause); 271 } 272 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