| // 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; |
| 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 benchSubMode = 0; |
| 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 width = rsgGetWidth(); |
| 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; |
| } |