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; 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 benchSubMode = 0; 129 static int runningLoops = 0; 130 static bool sendMsgFlag = false; 131 132 static bool gIsDebugMode = false; 133 void setDebugMode(int testNumber) { 134 gIsDebugMode = true; 135 benchMode = testNumber; 136 rsgClearAllRenderTargets(); 137 } 138 139 void setBenchmarkMode(int testNumber) { 140 gIsDebugMode = false; 141 if (testNumber == -1) { 142 benchmarkSingleTest = false; 143 benchMode = 0; 144 } else { 145 benchmarkSingleTest = true; 146 benchMode = testNumber; 147 } 148 149 runningLoops = 0; 150 } 151 152 static void drawOffscreenResult(int posX, int posY, int width, int height) { 153 bindProgramVertexOrtho(); 154 155 rs_matrix4x4 matrix; 156 rsMatrixLoadIdentity(&matrix); 157 rsgProgramVertexLoadModelMatrix(&matrix); 158 159 rsgBindProgramFragment(gProgFragmentTexture); 160 161 rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); 162 rsgBindTexture(gProgFragmentTexture, 0, gRenderBufferColor); 163 164 float startX = posX, startY = posY; 165 rsgDrawQuadTexCoords(startX, startY, 0, 0, 1, 166 startX, startY + height, 0, 0, 0, 167 startX + width, startY + height, 0, 1, 0, 168 startX + width, startY, 0, 1, 1); 169 } 170 171 static void benchmark() { 172 173 gDt = 1.0f / 60.0f; 174 175 rsgFinish(); 176 int64_t start = rsUptimeMillis(); 177 178 int drawPos = 0; 179 int frameCount = 100; 180 for(int i = 0; i < frameCount; i ++) { 181 setupOffscreenTarget(); 182 gRenderSurfaceW = rsAllocationGetDimX(gRenderBufferColor); 183 gRenderSurfaceH = rsAllocationGetDimY(gRenderBufferColor); 184 rsgClearColor(0.1f, 0.1f, 0.1f, 1.0f); 185 rsgClearDepth(1.0f); 186 187 runSubTest(benchMode); 188 rsgClearAllRenderTargets(); 189 gRenderSurfaceW = rsgGetWidth(); 190 gRenderSurfaceH = rsgGetHeight(); 191 int size = 8; 192 // draw each frame at (8, 3/4 gRenderSurfaceH) with size 193 drawOffscreenResult((drawPos+=size)%gRenderSurfaceW, (gRenderSurfaceH * 3) / 4, size, size); 194 } 195 196 rsgFinish(); 197 198 int64_t end = rsUptimeMillis(); 199 float fps = (float)(frameCount) / ((float)(end - start)*0.001f); 200 const char *testName = rsGetElementAt(gTestScripts[benchMode].debugName, 0); 201 rsDebug(testName, fps); 202 203 gResultBuffer[benchMode] = fps; 204 int bufferW = rsAllocationGetDimX(gRenderBufferColor); 205 int bufferH = rsAllocationGetDimY(gRenderBufferColor); 206 207 int quadW = gRenderSurfaceW / 2; 208 int quadH = (quadW * bufferH) / bufferW; 209 drawOffscreenResult(0, 0, quadW, quadH); 210 211 int left = 0, right = 0, top = 0, bottom = 0; 212 uint width = rsgGetWidth(); 213 uint height = rsgGetHeight(); 214 rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); 215 rsgBindFont(gFontSerif); 216 rsgMeasureText(gTestScripts[benchMode].testName, &left, &right, &top, &bottom); 217 rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); 218 rsgDrawText(gTestScripts[benchMode].testName, 2 -left, height - 2 + bottom); 219 220 if (benchmarkSingleTest) { 221 return; 222 } 223 224 benchMode ++; 225 int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts)); 226 if (benchMode == testCount) { 227 rsSendToClientBlocking(RS_MSG_RESULTS_READY, gResultBuffer, testCount*sizeof(float)); 228 benchMode = 0; 229 runningLoops++; 230 if ((gMaxLoops > 0) && (runningLoops > gMaxLoops) && !sendMsgFlag) { 231 //Notifiy the test to stop and get results 232 rsDebug("gMaxLoops and runningLoops: ", gMaxLoops, runningLoops); 233 rsSendToClientBlocking(RS_MSG_TEST_DONE); 234 sendMsgFlag = true; 235 } 236 } 237 } 238 239 static void debug() { 240 gDt = rsGetDt(); 241 runSubTest(benchMode); 242 } 243 244 int root(void) { 245 gRenderSurfaceW = rsgGetWidth(); 246 gRenderSurfaceH = rsgGetHeight(); 247 rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f); 248 rsgClearDepth(1.0f); 249 250 if (!gLoadComplete) { 251 rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); 252 rsgBindFont(gFontSerif); 253 rsgDrawText("Loading", 50, 50); 254 return 0; 255 } 256 257 if(!checkInit()) { 258 return 1; 259 } 260 261 if (gPauseRendering) { 262 rsgDrawText("Paused", 50, 50); 263 return 30; 264 } 265 if (gIsDebugMode) { 266 debug(); 267 } else { 268 benchmark(); 269 } 270 271 return 1; 272 } 273