1 /* 2 * Copyright 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include <EGL/egl.h> 19 #include <android/performance_hint.h> 20 #include <jni.h> 21 22 #include <chrono> 23 #include <map> 24 #include <memory> 25 #include <optional> 26 27 #include "Model.h" 28 #include "Shader.h" 29 #include "external/android_native_app_glue.h" 30 31 struct android_app; 32 33 struct FrameStats { 34 // Median of the durations 35 int64_t medianWorkDuration; 36 // Median of the intervals 37 int64_t medianFrameInterval; 38 // Standard deviation of a given run 39 double deviation; 40 // The total number of frames that exceeded target 41 std::optional<int64_t> exceededCount; 42 // The percent of frames that exceeded target 43 std::optional<double> exceededFraction; 44 // Efficiency of a given run is calculated by how close to min(target, baseline) the median is 45 std::optional<double> efficiency; 46 }; 47 48 class Renderer { 49 public: 50 /*! 51 * @param pApp the android_app this Renderer belongs to, needed to configure GL 52 */ Renderer(android_app * pApp)53 inline Renderer(android_app *pApp) 54 : app_(pApp), 55 display_(EGL_NO_DISPLAY), 56 surface_(EGL_NO_SURFACE), 57 context_(EGL_NO_CONTEXT), 58 width_(0), 59 height_(0), 60 shaderNeedsNewProjectionMatrix_(true) { 61 initRenderer(); 62 } 63 64 virtual ~Renderer(); 65 66 /*! 67 * Renders all the models in the renderer, returns time spent waiting for CPU work 68 * to finish. 69 */ 70 jlong render(); 71 72 /*! 73 * Attempts to start hint session and returns whether ADPF is supported on a given device. 74 */ 75 bool startHintSession(std::vector<pid_t> &threads, int64_t target); 76 void closeHintSession(); 77 void reportActualWorkDuration(int64_t duration); 78 void updateTargetWorkDuration(int64_t target); 79 bool isHintSessionRunning(); 80 int64_t getTargetWorkDuration(); 81 82 /*! 83 * Sets the number of android "heads" in the scene, these are used to create a synthetic 84 * workload that scales with performance, and by adjusting the number of them, the test can 85 * adjust the amount of stress to place the system under. 86 */ 87 void setNumHeads(int headCount); 88 89 /*! 90 * Adds an entry to the final result map that gets passed up to the Java side of the app, and 91 * eventually to the test runner. 92 */ 93 void addResult(std::string name, std::string value); 94 95 /*! 96 * Retrieve the results map. 97 */ 98 std::map<std::string, std::string> &getResults(); 99 100 /* 101 * Finds the test settings that best match this device, and returns the 102 * duration of the frame's work 103 */ 104 double calibrate(int &events, android_poll_source *pSource); 105 106 /*! 107 * Sets the baseline median, used to determine efficiency score 108 */ 109 void setBaselineMedian(int64_t median); 110 111 /*! 112 * Calculates the above frame stats for a given run 113 */ 114 FrameStats getFrameStats(std::vector<int64_t> &durations, std::vector<int64_t> &intervals, 115 std::string &testName); 116 117 private: 118 /*! 119 * Performs necessary OpenGL initialization. Customize this if you want to change your EGL 120 * context or application-wide settings. 121 */ 122 void initRenderer(); 123 124 /*! 125 * @brief we have to check every frame to see if the framebuffer has changed in size. If it has, 126 * update the viewport accordingly 127 */ 128 void updateRenderArea(); 129 130 /*! 131 * Adds an android "head" to the scene. 132 */ 133 void addHead(); 134 135 android_app *app_; 136 EGLDisplay display_; 137 EGLSurface surface_; 138 EGLContext context_; 139 EGLint width_; 140 EGLint height_; 141 APerformanceHintSession *hintSession_ = nullptr; 142 APerformanceHintManager *hintManager_ = nullptr; 143 int64_t lastTarget_ = 0; 144 int64_t baselineMedian_ = 0; 145 146 bool shaderNeedsNewProjectionMatrix_; 147 148 std::unique_ptr<Shader> shader_; 149 std::vector<Model> heads_; 150 151 // Hold on to the results object in the renderer, so 152 // we can reach the data anywhere in the rendering step. 153 std::map<std::string, std::string> results_; 154 }; 155