blob: 64b0d32b49614fc8714b7c8135567d74f39b0836 [file] [log] [blame] [edit]
/*-------------------------------------------------------------------------
* 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::TestLog;
using tcu::Vec4;
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(uint32_t 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);
}
} // namespace gls
} // namespace deqp