1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL (ES) Module 3 * ----------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Single-program test case wrapper for ShaderPerformanceMeasurer. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "glsShaderPerformanceCase.hpp" 25 #include "tcuRenderTarget.hpp" 26 #include "deStringUtil.hpp" 27 #include "deMath.h" 28 29 #include "glwFunctions.hpp" 30 #include "glwEnums.hpp" 31 32 using tcu::Vec4; 33 using tcu::TestLog; 34 using namespace glw; // GL types 35 36 namespace deqp 37 { 38 namespace gls 39 { 40 41 ShaderPerformanceCase::ShaderPerformanceCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, PerfCaseType caseType) 42 : tcu::TestCase (testCtx, tcu::NODETYPE_PERFORMANCE, name, description) 43 , m_renderCtx (renderCtx) 44 , m_caseType (caseType) 45 , m_program (DE_NULL) 46 , m_measurer (renderCtx, caseType) 47 { 48 } 49 50 ShaderPerformanceCase::~ShaderPerformanceCase (void) 51 { 52 ShaderPerformanceCase::deinit(); 53 } 54 55 void ShaderPerformanceCase::setGridSize (int gridW, int gridH) 56 { 57 m_measurer.setGridSize(gridW, gridH); 58 } 59 60 void ShaderPerformanceCase::setViewportSize (int width, int height) 61 { 62 m_measurer.setViewportSize(width, height); 63 } 64 65 void ShaderPerformanceCase::setVertexFragmentRatio (float fragmentsPerVertices) 66 { 67 const float eps = 0.01f; 68 int gridW = 255; 69 int gridH = 255; 70 int viewportW = m_renderCtx.getRenderTarget().getWidth(); 71 int viewportH = m_renderCtx.getRenderTarget().getHeight(); 72 73 for (int i = 0; i < 10; i++) 74 { 75 int numVert = (gridW+1)*(gridH+1); 76 int numFrag = viewportW*viewportH; 77 float ratio = (float)numFrag / (float)numVert; 78 79 if (de::abs(ratio - fragmentsPerVertices) < eps) 80 break; 81 else if (ratio < fragmentsPerVertices) 82 { 83 // Not enough fragments. 84 numVert = deRoundFloatToInt32((float)numFrag / fragmentsPerVertices); 85 86 while ((gridW+1)*(gridH+1) > numVert) 87 { 88 if (gridW > gridH) 89 gridW -= 1; 90 else 91 gridH -= 1; 92 } 93 } 94 else 95 { 96 // Not enough vertices. 97 numFrag = deRoundFloatToInt32((float)numVert * fragmentsPerVertices); 98 99 while (viewportW*viewportH > numFrag) 100 { 101 if (viewportW > viewportH) 102 viewportW -= 1; 103 else 104 viewportH -= 1; 105 } 106 } 107 } 108 109 float finalRatio = (float)(viewportW*viewportH) / (float)((gridW+1)*(gridH+1)); 110 m_testCtx.getLog() << TestLog::Message << "Requested fragment/vertex-ratio: " << de::floatToString(fragmentsPerVertices, 2) << "\n" 111 << "Computed fragment/vertex-ratio: " << de::floatToString(finalRatio, 2) 112 << TestLog::EndMessage; 113 114 setGridSize(gridW, gridH); 115 setViewportSize(viewportW, viewportH); 116 } 117 118 static void logRenderTargetInfo (TestLog& log, const tcu::RenderTarget& renderTarget) 119 { 120 log << TestLog::Section("RenderTarget", "Render target") 121 << TestLog::Message << "size: " << renderTarget.getWidth() << "x" << renderTarget.getHeight() << TestLog::EndMessage 122 << TestLog::Message << "bits:" 123 << " R" << renderTarget.getPixelFormat().redBits 124 << " G" << renderTarget.getPixelFormat().greenBits 125 << " B" << renderTarget.getPixelFormat().blueBits 126 << " A" << renderTarget.getPixelFormat().alphaBits 127 << " D" << renderTarget.getDepthBits() 128 << " S" << renderTarget.getStencilBits() 129 << TestLog::EndMessage; 130 131 if (renderTarget.getNumSamples() != 0) 132 log << TestLog::Message << renderTarget.getNumSamples() << "x MSAA" << TestLog::EndMessage; 133 else 134 log << TestLog::Message << "No MSAA" << TestLog::EndMessage; 135 136 log << TestLog::EndSection; 137 } 138 139 void ShaderPerformanceCase::init (void) 140 { 141 tcu::TestLog& log = m_testCtx.getLog(); 142 143 m_program = new glu::ShaderProgram(m_renderCtx, glu::makeVtxFragSources(m_vertShaderSource, m_fragShaderSource)); 144 145 if (m_program->isOk()) 146 { 147 const int initialCallCount = m_initialCalibration ? m_initialCalibration->initialNumCalls : 1; 148 logRenderTargetInfo(log, m_renderCtx.getRenderTarget()); 149 m_measurer.init(m_program->getProgram(), m_attributes, initialCallCount); 150 m_measurer.logParameters(log); 151 log << *m_program; 152 } 153 else 154 { 155 log << *m_program; 156 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed"); 157 return; // Skip rest of init. 158 } 159 160 setupProgram(m_program->getProgram()); 161 setupRenderState(); 162 } 163 164 void ShaderPerformanceCase::deinit (void) 165 { 166 delete m_program; 167 m_program = DE_NULL; 168 169 m_measurer.deinit(); 170 } 171 172 void ShaderPerformanceCase::setupProgram (deUint32 program) 173 { 174 DE_UNREF(program); 175 } 176 177 void ShaderPerformanceCase::setupRenderState (void) 178 { 179 } 180 181 ShaderPerformanceCase::IterateResult ShaderPerformanceCase::iterate (void) 182 { 183 DE_ASSERT(m_program); 184 185 if (!m_program->isOk()) // This happens when compilation failed in init(). 186 return STOP; 187 188 m_measurer.iterate(); 189 190 if (m_measurer.isFinished()) 191 { 192 m_measurer.logMeasurementInfo(m_testCtx.getLog()); 193 194 if (m_initialCalibration) 195 m_initialCalibration->initialNumCalls = de::max(1, m_measurer.getFinalCallCount()); 196 197 const ShaderPerformanceMeasurer::Result result = m_measurer.getResult(); 198 reportResult(result.megaVertPerSec, result.megaFragPerSec); 199 return STOP; 200 } 201 else 202 return CONTINUE; 203 } 204 205 void ShaderPerformanceCase::reportResult (float mvertPerSecond, float mfragPerSecond) 206 { 207 float result = 0.0f; 208 switch (m_caseType) 209 { 210 case CASETYPE_VERTEX: result = mvertPerSecond; break; 211 case CASETYPE_FRAGMENT: result = mfragPerSecond; break; 212 case CASETYPE_BALANCED: result = mfragPerSecond; break; 213 default: 214 DE_ASSERT(false); 215 } 216 217 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString(result, 2).c_str()); 218 } 219 220 ShaderPerformanceCaseGroup::ShaderPerformanceCaseGroup (tcu::TestContext& testCtx, const char* name, const char* description) 221 : TestCaseGroup (testCtx, name, description) 222 , m_initialCalibrationStorage (new ShaderPerformanceCase::InitialCalibration) 223 { 224 } 225 226 void ShaderPerformanceCaseGroup::addChild (ShaderPerformanceCase* perfCase) 227 { 228 perfCase->setCalibrationInitialParamStorage(m_initialCalibrationStorage); 229 TestCaseGroup::addChild(perfCase); 230 } 231 232 } // gls 233 } // deqp 234