// 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. #pragma version(1) #pragma rs java_package_name(com.android.perftest) #include "rs_graphics.rsh" #include "shader_def.rsh" #include "subtest_def.rsh" /* Message sent from script to renderscript */ const int RS_MSG_TEST_DONE = 100; const int RS_MSG_RESULTS_READY = 101; static const int gMaxModes = 64; int gMaxLoops = 1; int gDisplayMode = 1; // Allocation to write the results into static float gResultBuffer[gMaxModes]; rs_font gFontSerif; rs_sampler gLinearClamp; rs_program_vertex gProgVertex; rs_program_fragment gProgFragmentTexture; rs_allocation gRenderBufferColor; rs_allocation gRenderBufferDepth; VertexShaderInputs *gVSInputs; typedef struct TestScripts_s { rs_allocation testData; rs_allocation testName; rs_allocation debugName; rs_script testScript; } TestScripts; TestScripts *gTestScripts; bool gLoadComplete = false; bool gPauseRendering = false; static float gDt = 0; void init() { } static int gRenderSurfaceW; static int gRenderSurfaceH; static void fillSurfaceParams(TestData *testData) { testData->renderSurfaceW = gRenderSurfaceW; testData->renderSurfaceH = gRenderSurfaceH; testData->dt = gDt; } static void setupOffscreenTarget() { rsgBindColorTarget(gRenderBufferColor, 0); rsgBindDepthTarget(gRenderBufferDepth); } static void bindProgramVertexOrtho() { // Default vertex shader rsgBindProgramVertex(gProgVertex); // Setup the projection matrix rs_matrix4x4 proj; rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500); rsgProgramVertexLoadProjectionMatrix(&proj); } static void runSubTest(int index) { TestData testData; fillSurfaceParams(&testData); rs_allocation null_alloc = {0}; rsForEach(gTestScripts[index].testScript, gTestScripts[index].testData, null_alloc, &testData, sizeof(testData)); } static bool checkInit() { static int countdown = 3; // Perform all the uploads so we only measure rendered time if(countdown > 1) { int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts)); for(int i = 0; i < testCount; i ++) { rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f); runSubTest(i); rsgFinish(); } countdown --; rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f); rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); rsgBindFont(gFontSerif); if (countdown == 1) { rsgDrawText("Rendering", 50, 50); } else { rsgDrawText("Initializing", 50, 50); } return false; } return true; } static int benchMode = 0; static bool benchmarkSingleTest = false; static int runningLoops = 0; static bool sendMsgFlag = false; static bool gIsDebugMode = false; void setDebugMode(int testNumber) { gIsDebugMode = true; benchMode = testNumber; rsgClearAllRenderTargets(); } void setBenchmarkMode(int testNumber) { gIsDebugMode = false; if (testNumber == -1) { benchmarkSingleTest = false; benchMode = 0; } else { benchmarkSingleTest = true; benchMode = testNumber; } runningLoops = 0; } static void drawOffscreenResult(int posX, int posY, int width, int height) { bindProgramVertexOrtho(); rs_matrix4x4 matrix; rsMatrixLoadIdentity(&matrix); rsgProgramVertexLoadModelMatrix(&matrix); rsgBindProgramFragment(gProgFragmentTexture); rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); rsgBindTexture(gProgFragmentTexture, 0, gRenderBufferColor); float startX = posX, startY = posY; rsgDrawQuadTexCoords(startX, startY, 0, 0, 1, startX, startY + height, 0, 0, 0, startX + width, startY + height, 0, 1, 0, startX + width, startY, 0, 1, 1); } static void benchmark() { gDt = 1.0f / 60.0f; rsgFinish(); int64_t start = rsUptimeMillis(); int drawPos = 0; int frameCount = 100; for(int i = 0; i < frameCount; i ++) { setupOffscreenTarget(); gRenderSurfaceW = rsAllocationGetDimX(gRenderBufferColor); gRenderSurfaceH = rsAllocationGetDimY(gRenderBufferColor); rsgClearColor(0.1f, 0.1f, 0.1f, 1.0f); rsgClearDepth(1.0f); runSubTest(benchMode); rsgClearAllRenderTargets(); gRenderSurfaceW = rsgGetWidth(); gRenderSurfaceH = rsgGetHeight(); int size = 8; // draw each frame at (8, 3/4 gRenderSurfaceH) with size drawOffscreenResult((drawPos+=size)%gRenderSurfaceW, (gRenderSurfaceH * 3) / 4, size, size); } rsgFinish(); int64_t end = rsUptimeMillis(); float fps = (float)(frameCount) / ((float)(end - start)*0.001f); const char *testName = rsGetElementAt(gTestScripts[benchMode].debugName, 0); rsDebug(testName, fps); gResultBuffer[benchMode] = fps; int bufferW = rsAllocationGetDimX(gRenderBufferColor); int bufferH = rsAllocationGetDimY(gRenderBufferColor); int quadW = gRenderSurfaceW / 2; int quadH = (quadW * bufferH) / bufferW; drawOffscreenResult(0, 0, quadW, quadH); int left = 0, right = 0, top = 0, bottom = 0; uint height = rsgGetHeight(); rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); rsgBindFont(gFontSerif); rsgMeasureText(gTestScripts[benchMode].testName, &left, &right, &top, &bottom); rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); rsgDrawText(gTestScripts[benchMode].testName, 2 -left, height - 2 + bottom); if (benchmarkSingleTest) { return; } benchMode ++; int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts)); if (benchMode == testCount) { rsSendToClientBlocking(RS_MSG_RESULTS_READY, gResultBuffer, testCount*sizeof(float)); benchMode = 0; runningLoops++; if ((gMaxLoops > 0) && (runningLoops > gMaxLoops) && !sendMsgFlag) { //Notifiy the test to stop and get results rsDebug("gMaxLoops and runningLoops: ", gMaxLoops, runningLoops); rsSendToClientBlocking(RS_MSG_TEST_DONE); sendMsgFlag = true; } } } static void debug() { gDt = rsGetDt(); runSubTest(benchMode); } int root(void) { gRenderSurfaceW = rsgGetWidth(); gRenderSurfaceH = rsgGetHeight(); rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f); rsgClearDepth(1.0f); if (!gLoadComplete) { rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); rsgBindFont(gFontSerif); rsgDrawText("Loading", 50, 50); return 0; } if(!checkInit()) { return 1; } if (gPauseRendering) { rsgDrawText("Paused", 50, 50); return 30; } if (gIsDebugMode) { debug(); } else { benchmark(); } return 1; }