/* * Copyright (C) 2010-2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.perftest; import java.io.Writer; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import android.os.Environment; import android.content.res.Resources; import android.renderscript.*; import android.renderscript.Element.DataKind; import android.renderscript.Element.DataType; import android.renderscript.Allocation.MipmapControl; import android.renderscript.Program.TextureType; import android.renderscript.RenderScript.RSMessageHandler; import android.renderscript.Sampler.Value; import android.renderscript.Mesh.Primitive; import android.renderscript.Matrix4f; import android.renderscript.ProgramVertexFixedFunction; import android.util.Log; public class RsBenchRS { private static final String TAG = "RsBenchRS"; int mWidth; int mHeight; int mLoops; int mCurrentLoop; int mBenchmarkDimX; int mBenchmarkDimY; public RsBenchRS() { } public void init(RenderScriptGL rs, Resources res, int width, int height, int loops) { mRS = rs; mRes = res; mWidth = width; mHeight = height; mMode = 0; mLoops = loops; mCurrentLoop = 0; mBenchmarkDimX = 1280; mBenchmarkDimY = 720; initRS(); } private boolean stopTest = false; private Resources mRes; private RenderScriptGL mRS; private ProgramStore mProgStoreBlendNone; private ProgramStore mProgStoreBlendAlpha; private ProgramFragment mProgFragmentTexture; private ProgramFragment mProgFragmentColor; private ProgramVertex mProgVertex; private ProgramVertexFixedFunction.Constants mPVA; private ProgramVertexFixedFunction.Constants mPvProjectionAlloc; private ScriptC_rsbench mScript; ScriptField_TestScripts_s.Item[] mIndividualTests; int mMode; String[] mTestNames; float[] mLocalTestResults; static Allocation createZeroTerminatedAlloc(RenderScript rs, String str, int usage) { byte[] allocArray = null; try { allocArray = str.getBytes("UTF-8"); byte[] allocArrayZero = new byte[allocArray.length + 1]; System.arraycopy(allocArray, 0, allocArrayZero, 0, allocArray.length); allocArrayZero[allocArrayZero.length - 1] = '\0'; Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArrayZero.length, usage); alloc.copyFrom(allocArrayZero); return alloc; } catch (Exception e) { throw new RSRuntimeException("Could not convert string to utf-8."); } } void appendTests(RsBenchBaseTest testSet) { ScriptField_TestScripts_s.Item[] newTests = testSet.getTests(); if (mIndividualTests != null) { ScriptField_TestScripts_s.Item[] combined; combined = new ScriptField_TestScripts_s.Item[newTests.length + mIndividualTests.length]; System.arraycopy(mIndividualTests, 0, combined, 0, mIndividualTests.length); System.arraycopy(newTests, 0, combined, mIndividualTests.length, newTests.length); mIndividualTests = combined; } else { mIndividualTests = newTests; } String[] newNames = testSet.getTestNames(); if (mTestNames != null) { String[] combinedNames; combinedNames = new String[newNames.length + mTestNames.length]; System.arraycopy(mTestNames, 0, combinedNames, 0, mTestNames.length); System.arraycopy(newNames, 0, combinedNames, mTestNames.length, newNames.length); mTestNames = combinedNames; } else { mTestNames = newNames; } } void createTestAllocation() { int numTests = mIndividualTests.length; mLocalTestResults = new float[numTests]; ScriptField_TestScripts_s allTests; allTests = new ScriptField_TestScripts_s(mRS, numTests); for (int i = 0; i < numTests; i ++) { allTests.set(mIndividualTests[i], i, false); } allTests.copyAll(); mScript.bind_gTestScripts(allTests); } private void saveTestResults() { String state = Environment.getExternalStorageState(); if (!Environment.MEDIA_MOUNTED.equals(state)) { Log.v(TAG, "sdcard is read only"); return; } File sdCard = Environment.getExternalStorageDirectory(); if (!sdCard.canWrite()) { Log.v(TAG, "ssdcard is read only"); return; } File resultFile = new File(sdCard, "rsbench_result" + mCurrentLoop + ".csv"); resultFile.setWritable(true, false); try { BufferedWriter results = new BufferedWriter(new FileWriter(resultFile)); for (int i = 0; i < mLocalTestResults.length; i ++) { results.write(mTestNames[i] + ", " + mLocalTestResults[i] + ",\n"); } results.close(); Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath()); } catch (IOException e) { Log.v(TAG, "Unable to write result file " + e.getMessage()); } } /** * Create a message handler to handle message sent from the script */ protected RSMessageHandler mRsMessage = new RSMessageHandler() { public void run() { if (mID == mScript.get_RS_MSG_RESULTS_READY()) { for (int i = 0; i < mLocalTestResults.length; i ++) { mLocalTestResults[i] = Float.intBitsToFloat(mData[i]); } saveTestResults(); if (mLoops > 0) { mCurrentLoop ++; mCurrentLoop = mCurrentLoop % mLoops; } return; } else if (mID == mScript.get_RS_MSG_TEST_DONE()) { synchronized(this) { stopTest = true; this.notifyAll(); } return; } else { Log.v(TAG, "Perf test got unexpected message"); return; } } }; /** * Wait for message from the script */ public boolean testIsFinished() { synchronized(this) { while (true) { if (stopTest) { return true; } else { try { this.wait(60*1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } } private void initProgramFragment() { ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS); texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); mProgFragmentTexture = texBuilder.create(); mProgFragmentTexture.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0); ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS); colBuilder.setVaryingColor(false); mProgFragmentColor = colBuilder.create(); mScript.set_gProgFragmentTexture(mProgFragmentTexture); } private void initProgramVertex() { ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS); mProgVertex = pvb.create(); mPVA = new ProgramVertexFixedFunction.Constants(mRS); ((ProgramVertexFixedFunction)mProgVertex).bindConstants(mPVA); Matrix4f proj = new Matrix4f(); proj.loadOrthoWindow(mBenchmarkDimX, mBenchmarkDimY); mPVA.setProjection(proj); mScript.set_gProgVertex(mProgVertex); } private int strlen(byte[] array) { int count = 0; while(count < array.length && array[count] != 0) { count ++; } return count; } public void setDebugMode(int num) { mScript.invoke_setDebugMode(num); } public void setBenchmarkMode(int benchNum) { mScript.invoke_setBenchmarkMode(benchNum); } public void pause(boolean pause) { mScript.set_gPauseRendering(pause); } private void initRS() { mScript = new ScriptC_rsbench(mRS, mRes, R.raw.rsbench); mRS.bindRootScript(mScript); mRS.setMessageHandler(mRsMessage); mScript.set_gMaxLoops(mLoops); initProgramVertex(); initProgramFragment(); mScript.set_gFontSerif(Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8)); Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS)); b.setX(mBenchmarkDimX).setY(mBenchmarkDimY); Allocation offscreen = Allocation.createTyped(mRS, b.create(), Allocation.USAGE_GRAPHICS_TEXTURE | Allocation.USAGE_GRAPHICS_RENDER_TARGET); mScript.set_gRenderBufferColor(offscreen); b = new Type.Builder(mRS, Element.createPixel(mRS, DataType.UNSIGNED_16, DataKind.PIXEL_DEPTH)); b.setX(mBenchmarkDimX).setY(mBenchmarkDimY); offscreen = Allocation.createTyped(mRS, b.create(), Allocation.USAGE_GRAPHICS_RENDER_TARGET); mScript.set_gRenderBufferDepth(offscreen); mScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS)); RsBenchBaseTest test = new TextTest(); if (test.init(mRS, mRes)) { appendTests(test); } test = new FillTest(); if (test.init(mRS, mRes)) { appendTests(test); } test = new MeshTest(); if (test.init(mRS, mRes)) { appendTests(test); } test = new TorusTest(); if (test.init(mRS, mRes)) { appendTests(test); } test = new UiTest(); if (test.init(mRS, mRes)) { appendTests(test); } createTestAllocation(); mScript.set_gLoadComplete(true); } }