234 lines
6.5 KiB
C++
234 lines
6.5 KiB
C++
/*-------------------------------------------------------------------------
|
|
* 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
|