/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL (ES) Module * ----------------------------------------------- * * Copyright 2014 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. * *//*! * \file * \brief Single-program test case wrapper for ShaderPerformanceMeasurer. *//*--------------------------------------------------------------------*/ #include "glsShaderPerformanceCase.hpp" #include "tcuRenderTarget.hpp" #include "deStringUtil.hpp" #include "deMath.h" #include "glwFunctions.hpp" #include "glwEnums.hpp" using tcu::Vec4; using tcu::TestLog; using namespace glw; // GL types namespace deqp { namespace gls { ShaderPerformanceCase::ShaderPerformanceCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, PerfCaseType caseType) : tcu::TestCase (testCtx, tcu::NODETYPE_PERFORMANCE, name, description) , m_renderCtx (renderCtx) , m_caseType (caseType) , m_program (DE_NULL) , m_measurer (renderCtx, caseType) { } ShaderPerformanceCase::~ShaderPerformanceCase (void) { ShaderPerformanceCase::deinit(); } void ShaderPerformanceCase::setGridSize (int gridW, int gridH) { m_measurer.setGridSize(gridW, gridH); } void ShaderPerformanceCase::setViewportSize (int width, int height) { m_measurer.setViewportSize(width, height); } void ShaderPerformanceCase::setVertexFragmentRatio (float fragmentsPerVertices) { const float eps = 0.01f; int gridW = 255; int gridH = 255; int viewportW = m_renderCtx.getRenderTarget().getWidth(); int viewportH = m_renderCtx.getRenderTarget().getHeight(); for (int i = 0; i < 10; i++) { int numVert = (gridW+1)*(gridH+1); int numFrag = viewportW*viewportH; float ratio = (float)numFrag / (float)numVert; if (de::abs(ratio - fragmentsPerVertices) < eps) break; else if (ratio < fragmentsPerVertices) { // Not enough fragments. numVert = deRoundFloatToInt32((float)numFrag / fragmentsPerVertices); while ((gridW+1)*(gridH+1) > numVert) { if (gridW > gridH) gridW -= 1; else gridH -= 1; } } else { // Not enough vertices. numFrag = deRoundFloatToInt32((float)numVert * fragmentsPerVertices); while (viewportW*viewportH > numFrag) { if (viewportW > viewportH) viewportW -= 1; else viewportH -= 1; } } } float finalRatio = (float)(viewportW*viewportH) / (float)((gridW+1)*(gridH+1)); m_testCtx.getLog() << TestLog::Message << "Requested fragment/vertex-ratio: " << de::floatToString(fragmentsPerVertices, 2) << "\n" << "Computed fragment/vertex-ratio: " << de::floatToString(finalRatio, 2) << TestLog::EndMessage; setGridSize(gridW, gridH); setViewportSize(viewportW, viewportH); } static void logRenderTargetInfo (TestLog& log, const tcu::RenderTarget& renderTarget) { log << TestLog::Section("RenderTarget", "Render target") << TestLog::Message << "size: " << renderTarget.getWidth() << "x" << renderTarget.getHeight() << TestLog::EndMessage << TestLog::Message << "bits:" << " R" << renderTarget.getPixelFormat().redBits << " G" << renderTarget.getPixelFormat().greenBits << " B" << renderTarget.getPixelFormat().blueBits << " A" << renderTarget.getPixelFormat().alphaBits << " D" << renderTarget.getDepthBits() << " S" << renderTarget.getStencilBits() << TestLog::EndMessage; if (renderTarget.getNumSamples() != 0) log << TestLog::Message << renderTarget.getNumSamples() << "x MSAA" << TestLog::EndMessage; else log << TestLog::Message << "No MSAA" << TestLog::EndMessage; log << TestLog::EndSection; } void ShaderPerformanceCase::init (void) { tcu::TestLog& log = m_testCtx.getLog(); m_program = new glu::ShaderProgram(m_renderCtx, glu::makeVtxFragSources(m_vertShaderSource, m_fragShaderSource)); if (m_program->isOk()) { const int initialCallCount = m_initialCalibration ? m_initialCalibration->initialNumCalls : 1; logRenderTargetInfo(log, m_renderCtx.getRenderTarget()); m_measurer.init(m_program->getProgram(), m_attributes, initialCallCount); m_measurer.logParameters(log); log << *m_program; } else { log << *m_program; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed"); return; // Skip rest of init. } setupProgram(m_program->getProgram()); setupRenderState(); } void ShaderPerformanceCase::deinit (void) { delete m_program; m_program = DE_NULL; m_measurer.deinit(); } void ShaderPerformanceCase::setupProgram (deUint32 program) { DE_UNREF(program); } void ShaderPerformanceCase::setupRenderState (void) { } ShaderPerformanceCase::IterateResult ShaderPerformanceCase::iterate (void) { DE_ASSERT(m_program); if (!m_program->isOk()) // This happens when compilation failed in init(). return STOP; m_measurer.iterate(); if (m_measurer.isFinished()) { m_measurer.logMeasurementInfo(m_testCtx.getLog()); if (m_initialCalibration) m_initialCalibration->initialNumCalls = de::max(1, m_measurer.getFinalCallCount()); const ShaderPerformanceMeasurer::Result result = m_measurer.getResult(); reportResult(result.megaVertPerSec, result.megaFragPerSec); return STOP; } else return CONTINUE; } void ShaderPerformanceCase::reportResult (float mvertPerSecond, float mfragPerSecond) { float result = 0.0f; switch (m_caseType) { case CASETYPE_VERTEX: result = mvertPerSecond; break; case CASETYPE_FRAGMENT: result = mfragPerSecond; break; case CASETYPE_BALANCED: result = mfragPerSecond; break; default: DE_ASSERT(false); } m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString(result, 2).c_str()); } ShaderPerformanceCaseGroup::ShaderPerformanceCaseGroup (tcu::TestContext& testCtx, const char* name, const char* description) : TestCaseGroup (testCtx, name, description) , m_initialCalibrationStorage (new ShaderPerformanceCase::InitialCalibration) { } void ShaderPerformanceCaseGroup::addChild (ShaderPerformanceCase* perfCase) { perfCase->setCalibrationInitialParamStorage(m_initialCalibrationStorage); TestCaseGroup::addChild(perfCase); } } // gls } // deqp