1 // Copyright (C) 2010-2011 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #pragma version(1) 16 17 #pragma rs java_package_name(com.android.perftest) 18 19 #include "rs_graphics.rsh" 20 #include "shader_def.rsh" 21 #include "subtest_def.rsh" 22 23 /* Message sent from script to renderscript */ 24 const int RS_MSG_TEST_DONE = 100; 25 const int RS_MSG_RESULTS_READY = 101; 26 27 static const int gMaxModes = 64; 28 int gMaxLoops = 1; 29 int gDisplayMode = 1; 30 31 // Allocation to write the results into 32 static float gResultBuffer[gMaxModes]; 33 34 rs_font gFontSerif; 35 rs_sampler gLinearClamp; 36 37 rs_program_vertex gProgVertex; 38 rs_program_fragment gProgFragmentTexture; 39 40 rs_allocation gRenderBufferColor; 41 rs_allocation gRenderBufferDepth; 42 43 VertexShaderInputs *gVSInputs; 44 45 typedef struct TestScripts_s { 46 rs_allocation testData; 47 rs_allocation testName; 48 rs_allocation debugName; 49 rs_script testScript; 50 } TestScripts; 51 TestScripts *gTestScripts; 52 53 bool gLoadComplete = false; 54 bool gPauseRendering = false; 55 56 static float gDt = 0; 57 58 void init() { 59 } 60 61 static int gRenderSurfaceW; 62 static int gRenderSurfaceH; 63 64 static void fillSurfaceParams(TestData *testData) { 65 testData->renderSurfaceW = gRenderSurfaceW; 66 testData->renderSurfaceH = gRenderSurfaceH; 67 testData->dt = gDt; 68 } 69 70 static void setupOffscreenTarget() { 71 rsgBindColorTarget(gRenderBufferColor, 0); 72 rsgBindDepthTarget(gRenderBufferDepth); 73 } 74 75 static void bindProgramVertexOrtho() { 76 // Default vertex shader 77 rsgBindProgramVertex(gProgVertex); 78 // Setup the projection matrix 79 rs_matrix4x4 proj; 80 rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500); 81 rsgProgramVertexLoadProjectionMatrix(&proj); 82 } 83 84 static void runSubTest(int index) { 85 TestData testData; 86 fillSurfaceParams(&testData); 87 88 rs_allocation null_alloc = {0}; 89 rsForEach(gTestScripts[index].testScript, 90 gTestScripts[index].testData, 91 null_alloc, 92 &testData, 93 sizeof(testData)); 94 } 95 96 97 static bool checkInit() { 98 99 static int countdown = 3; 100 101 // Perform all the uploads so we only measure rendered time 102 if(countdown > 1) { 103 int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts)); 104 for(int i = 0; i < testCount; i ++) { 105 rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f); 106 runSubTest(i); 107 rsgFinish(); 108 } 109 countdown --; 110 rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f); 111 112 rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); 113 rsgBindFont(gFontSerif); 114 if (countdown == 1) { 115 rsgDrawText("Rendering", 50, 50); 116 } else { 117 rsgDrawText("Initializing", 50, 50); 118 } 119 120 return false; 121 } 122 123 return true; 124 } 125 126 static int benchMode = 0; 127 static bool benchmarkSingleTest = false; 128 static int runningLoops = 0; 129 static bool sendMsgFlag = false; 130 131 static bool gIsDebugMode = false; 132 void setDebugMode(int testNumber) { 133 gIsDebugMode = true; 134 benchMode = testNumber; 135 rsgClearAllRenderTargets(); 136 } 137 138 void setBenchmarkMode(int testNumber) { 139 gIsDebugMode = false; 140 if (testNumber == -1) { 141 benchmarkSingleTest = false; 142 benchMode = 0; 143 } else { 144 benchmarkSingleTest = true; 145 benchMode = testNumber; 146 } 147 148 runningLoops = 0; 149 } 150 151 static void drawOffscreenResult(int posX, int posY, int width, int height) { 152 bindProgramVertexOrtho(); 153 154 rs_matrix4x4 matrix; 155 rsMatrixLoadIdentity(&matrix); 156 rsgProgramVertexLoadModelMatrix(&matrix); 157 158 rsgBindProgramFragment(gProgFragmentTexture); 159 160 rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); 161 rsgBindTexture(gProgFragmentTexture, 0, gRenderBufferColor); 162 163 float startX = posX, startY = posY; 164 rsgDrawQuadTexCoords(startX, startY, 0, 0, 1, 165 startX, startY + height, 0, 0, 0, 166 startX + width, startY + height, 0, 1, 0, 167 startX + width, startY, 0, 1, 1); 168 } 169 170 static void benchmark() { 171 172 gDt = 1.0f / 60.0f; 173 174 rsgFinish(); 175 int64_t start = rsUptimeMillis(); 176 177 int drawPos = 0; 178 int frameCount = 100; 179 for(int i = 0; i < frameCount; i ++) { 180 setupOffscreenTarget(); 181 gRenderSurfaceW = rsAllocationGetDimX(gRenderBufferColor); 182 gRenderSurfaceH = rsAllocationGetDimY(gRenderBufferColor); 183 rsgClearColor(0.1f, 0.1f, 0.1f, 1.0f); 184 rsgClearDepth(1.0f); 185 186 runSubTest(benchMode); 187 rsgClearAllRenderTargets(); 188 gRenderSurfaceW = rsgGetWidth(); 189 gRenderSurfaceH = rsgGetHeight(); 190 int size = 8; 191 // draw each frame at (8, 3/4 gRenderSurfaceH) with size 192 drawOffscreenResult((drawPos+=size)%gRenderSurfaceW, (gRenderSurfaceH * 3) / 4, size, size); 193 } 194 195 rsgFinish(); 196 197 int64_t end = rsUptimeMillis(); 198 float fps = (float)(frameCount) / ((float)(end - start)*0.001f); 199 const char *testName = rsGetElementAt(gTestScripts[benchMode].debugName, 0); 200 rsDebug(testName, fps); 201 202 gResultBuffer[benchMode] = fps; 203 int bufferW = rsAllocationGetDimX(gRenderBufferColor); 204 int bufferH = rsAllocationGetDimY(gRenderBufferColor); 205 206 int quadW = gRenderSurfaceW / 2; 207 int quadH = (quadW * bufferH) / bufferW; 208 drawOffscreenResult(0, 0, quadW, quadH); 209 210 int left = 0, right = 0, top = 0, bottom = 0; 211 uint height = rsgGetHeight(); 212 rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); 213 rsgBindFont(gFontSerif); 214 rsgMeasureText(gTestScripts[benchMode].testName, &left, &right, &top, &bottom); 215 rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); 216 rsgDrawText(gTestScripts[benchMode].testName, 2 -left, height - 2 + bottom); 217 218 if (benchmarkSingleTest) { 219 return; 220 } 221 222 benchMode ++; 223 int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts)); 224 if (benchMode == testCount) { 225 rsSendToClientBlocking(RS_MSG_RESULTS_READY, gResultBuffer, testCount*sizeof(float)); 226 benchMode = 0; 227 runningLoops++; 228 if ((gMaxLoops > 0) && (runningLoops > gMaxLoops) && !sendMsgFlag) { 229 //Notifiy the test to stop and get results 230 rsDebug("gMaxLoops and runningLoops: ", gMaxLoops, runningLoops); 231 rsSendToClientBlocking(RS_MSG_TEST_DONE); 232 sendMsgFlag = true; 233 } 234 } 235 } 236 237 static void debug() { 238 gDt = rsGetDt(); 239 runSubTest(benchMode); 240 } 241 242 int root(void) { 243 gRenderSurfaceW = rsgGetWidth(); 244 gRenderSurfaceH = rsgGetHeight(); 245 rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f); 246 rsgClearDepth(1.0f); 247 248 if (!gLoadComplete) { 249 rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); 250 rsgBindFont(gFontSerif); 251 rsgDrawText("Loading", 50, 50); 252 return 0; 253 } 254 255 if(!checkInit()) { 256 return 1; 257 } 258 259 if (gPauseRendering) { 260 rsgDrawText("Paused", 50, 50); 261 return 30; 262 } 263 if (gIsDebugMode) { 264 debug(); 265 } else { 266 benchmark(); 267 } 268 269 return 1; 270 } 271