You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
372 lines
14 KiB
372 lines
14 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL ES 3.0 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 Long running shader stress tests.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "es3sLongRunningShaderTests.hpp"
|
|
|
|
#include "gluShaderProgram.hpp"
|
|
#include "gluShaderUtil.hpp"
|
|
#include "gluDrawUtil.hpp"
|
|
|
|
#include "tcuRenderTarget.hpp"
|
|
#include "tcuVector.hpp"
|
|
#include "tcuTestLog.hpp"
|
|
|
|
#include "deRandom.hpp"
|
|
#include "deStringUtil.hpp"
|
|
#include "deString.h"
|
|
|
|
#include "glwFunctions.hpp"
|
|
#include "glwEnums.hpp"
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gles3
|
|
{
|
|
namespace Stress
|
|
{
|
|
|
|
using tcu::TestLog;
|
|
using tcu::Vec2;
|
|
using std::vector;
|
|
|
|
namespace
|
|
{
|
|
|
|
enum LoopType
|
|
{
|
|
LOOPTYPE_FOR = 0,
|
|
LOOPTYPE_WHILE,
|
|
LOOPTYPE_DO_WHILE,
|
|
|
|
LOOPTYPE_LAST
|
|
};
|
|
|
|
enum IterCountType
|
|
{
|
|
ITERCOUNTTYPE_STATIC = 0,
|
|
ITERCOUNTTYPE_UNIFORM,
|
|
ITERCOUNTTYPE_DYNAMIC,
|
|
|
|
ITERCOUNTTYPE_LAST
|
|
};
|
|
|
|
class LongRunningShaderCase : public TestCase
|
|
{
|
|
public:
|
|
struct Params
|
|
{
|
|
const char* name;
|
|
const char* description;
|
|
glu::ShaderType shaderType;
|
|
LoopType loopType;
|
|
IterCountType iterCountType;
|
|
int numInvocations;
|
|
int minLoopIterCount;
|
|
int maxLoopIterCount;
|
|
};
|
|
|
|
LongRunningShaderCase (Context& context, const Params* params);
|
|
~LongRunningShaderCase (void);
|
|
|
|
void init (void);
|
|
void deinit (void);
|
|
IterateResult iterate (void);
|
|
|
|
private:
|
|
LongRunningShaderCase (const LongRunningShaderCase&);
|
|
LongRunningShaderCase& operator= (const LongRunningShaderCase&);
|
|
|
|
static glu::ProgramSources genSources (const Params& params);
|
|
static deUint32 getSeed (const Params& params);
|
|
|
|
const Params* const m_params;
|
|
const int m_numCaseIters;
|
|
|
|
glu::ShaderProgram* m_program;
|
|
int m_caseIterNdx;
|
|
};
|
|
|
|
LongRunningShaderCase::LongRunningShaderCase (Context& context, const Params* params)
|
|
: TestCase (context, params->name, params->description)
|
|
, m_params (params)
|
|
, m_numCaseIters (5)
|
|
, m_program (DE_NULL)
|
|
, m_caseIterNdx (0)
|
|
{
|
|
}
|
|
|
|
LongRunningShaderCase::~LongRunningShaderCase (void)
|
|
{
|
|
deinit();
|
|
}
|
|
|
|
glu::ProgramSources LongRunningShaderCase::genSources (const Params& params)
|
|
{
|
|
const bool isVertCase = params.shaderType == glu::SHADERTYPE_VERTEX;
|
|
std::ostringstream vert, frag;
|
|
|
|
vert << "#version 300 es\n"
|
|
<< "in highp vec2 a_position;\n";
|
|
|
|
frag << "#version 300 es\n";
|
|
|
|
if (params.iterCountType == ITERCOUNTTYPE_DYNAMIC)
|
|
{
|
|
vert << "in highp int a_iterCount;\n";
|
|
if (!isVertCase)
|
|
{
|
|
vert << "flat out highp int v_iterCount;\n";
|
|
frag << "flat in highp int v_iterCount;\n";
|
|
}
|
|
}
|
|
else if (params.iterCountType == ITERCOUNTTYPE_UNIFORM)
|
|
(isVertCase ? vert : frag) << "uniform highp int u_iterCount;\n";
|
|
|
|
if (isVertCase)
|
|
{
|
|
vert << "out mediump vec4 v_color;\n";
|
|
frag << "in mediump vec4 v_color;\n";
|
|
}
|
|
|
|
frag << "out mediump vec4 o_color;\n";
|
|
|
|
vert << "\nvoid main (void)\n{\n"
|
|
<< " gl_Position = vec4(a_position, 0.0, 1.0);\n"
|
|
<< " gl_PointSize = 1.0;\n";
|
|
|
|
if (!isVertCase && params.iterCountType == ITERCOUNTTYPE_DYNAMIC)
|
|
vert << " v_iterCount = a_iterCount;\n";
|
|
|
|
frag << "\nvoid main (void)\n{\n";
|
|
|
|
{
|
|
const std::string iterCount = params.iterCountType == ITERCOUNTTYPE_DYNAMIC ? (isVertCase ? "a_iterCount" : "v_iterCount") :
|
|
params.iterCountType == ITERCOUNTTYPE_UNIFORM ? "u_iterCount" :
|
|
params.iterCountType == ITERCOUNTTYPE_STATIC ? de::toString(params.maxLoopIterCount) : "<invalid>";
|
|
const char* const body = "color = cos(sin(color*1.25)*0.8);";
|
|
std::ostringstream& op = isVertCase ? vert : frag;
|
|
|
|
op << " mediump vec4 color = " << (isVertCase ? "a_position.xyxy" : "gl_FragCoord") << ";\n";
|
|
|
|
if (params.loopType == LOOPTYPE_FOR)
|
|
{
|
|
op << " for (highp int i = 0; i < " << iterCount << " || " << iterCount << " < 0; ++i)\n"
|
|
<< " " << body << "\n";
|
|
}
|
|
else if (params.loopType == LOOPTYPE_WHILE)
|
|
{
|
|
op << " highp int i = 0;\n"
|
|
<< " while (i < " << iterCount << " || " << iterCount << " < 0) {\n"
|
|
<< " i += 1;\n"
|
|
<< " " << body << "\n"
|
|
<< " }\n";
|
|
}
|
|
else
|
|
{
|
|
DE_ASSERT(params.loopType == LOOPTYPE_DO_WHILE);
|
|
op << " highp int i = 0;\n"
|
|
<< " do {\n"
|
|
<< " i += 1;\n"
|
|
<< " " << body << "\n"
|
|
<< " } while (i <= " << iterCount << " || " << iterCount << " < 0);\n";
|
|
}
|
|
}
|
|
|
|
if (isVertCase)
|
|
{
|
|
vert << " v_color = color;\n";
|
|
frag << " o_color = v_color;\n";
|
|
}
|
|
else
|
|
frag << " o_color = color;\n";
|
|
|
|
vert << "}\n";
|
|
frag << "}\n";
|
|
|
|
return glu::ProgramSources() << glu::VertexSource(vert.str()) << glu::FragmentSource(frag.str());
|
|
}
|
|
|
|
void LongRunningShaderCase::init (void)
|
|
{
|
|
DE_ASSERT(!m_program);
|
|
m_program = new glu::ShaderProgram(m_context.getRenderContext(), genSources(*m_params));
|
|
|
|
m_testCtx.getLog() << *m_program;
|
|
|
|
if (!m_program->isOk())
|
|
{
|
|
deinit();
|
|
TCU_FAIL("Failed to compile shader program");
|
|
}
|
|
|
|
m_caseIterNdx = 0;
|
|
|
|
if (m_params->iterCountType != ITERCOUNTTYPE_STATIC)
|
|
{
|
|
m_testCtx.getLog() << TestLog::Message << "Loop iteration counts in range: [" << m_params->minLoopIterCount
|
|
<< ", " << m_params->maxLoopIterCount << "]"
|
|
<< TestLog::EndMessage;
|
|
}
|
|
|
|
m_testCtx.getLog() << TestLog::Message << "Number of vertices and fragments: " << m_params->numInvocations << TestLog::EndMessage;
|
|
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Test will pass or timeout, unless driver/device crashes.
|
|
}
|
|
|
|
void LongRunningShaderCase::deinit (void)
|
|
{
|
|
delete m_program;
|
|
m_program = DE_NULL;
|
|
}
|
|
|
|
void genPositions (const tcu::RenderTarget& renderTarget, int numPoints, Vec2* positions)
|
|
{
|
|
const int width = renderTarget.getWidth();
|
|
const int height = renderTarget.getHeight();
|
|
|
|
if (width*height < numPoints)
|
|
throw tcu::NotSupportedError("Too small viewport to fit all test points");
|
|
|
|
for (int pointNdx = 0; pointNdx < numPoints; pointNdx++)
|
|
{
|
|
const int xi = pointNdx % width;
|
|
const int yi = pointNdx / height;
|
|
const float xf = 2.0f * ((float(xi) + 0.5f) / float(width)) - 1.0f;
|
|
const float yf = 2.0f * ((float(yi) + 0.5f) / float(height)) - 1.0f;
|
|
|
|
positions[pointNdx] = Vec2(xf, yf);
|
|
}
|
|
}
|
|
|
|
deUint32 LongRunningShaderCase::getSeed (const Params& params)
|
|
{
|
|
const deUint32 seed = deStringHash(params.name)
|
|
^ deInt32Hash(params.shaderType)
|
|
^ deInt32Hash(params.loopType)
|
|
^ deInt32Hash(params.iterCountType)
|
|
^ deInt32Hash(params.minLoopIterCount)
|
|
^ deInt32Hash(params.maxLoopIterCount)
|
|
^ deInt32Hash(params.numInvocations);
|
|
return seed;
|
|
}
|
|
|
|
LongRunningShaderCase::IterateResult LongRunningShaderCase::iterate (void)
|
|
{
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
de::Random rnd (getSeed(*m_params));
|
|
vector<Vec2> positions (m_params->numInvocations);
|
|
vector<int> iterCounts (m_params->iterCountType == ITERCOUNTTYPE_DYNAMIC ? m_params->numInvocations : 1);
|
|
vector<glu::VertexArrayBinding> vertexArrays;
|
|
|
|
vertexArrays.push_back(glu::va::Float("a_position", 2, (int)positions.size(), 0, positions[0].getPtr()));
|
|
if (m_params->iterCountType == ITERCOUNTTYPE_DYNAMIC)
|
|
vertexArrays.push_back(glu::va::Int32("a_iterCount", 1, (int)iterCounts.size(), 0, &iterCounts[0]));
|
|
|
|
genPositions(m_context.getRenderTarget(), (int)positions.size(), &positions[0]);
|
|
|
|
for (vector<int>::iterator i = iterCounts.begin(); i != iterCounts.end(); ++i)
|
|
*i = rnd.getInt(m_params->minLoopIterCount, m_params->maxLoopIterCount);
|
|
|
|
gl.useProgram(m_program->getProgram());
|
|
|
|
if (m_params->iterCountType == ITERCOUNTTYPE_UNIFORM)
|
|
gl.uniform1i(gl.getUniformLocation(m_program->getProgram(), "u_iterCount"), iterCounts[0]);
|
|
|
|
glu::draw(m_context.getRenderContext(), m_program->getProgram(),
|
|
(int)vertexArrays.size(), &vertexArrays[0],
|
|
glu::pr::Points(m_params->numInvocations));
|
|
|
|
m_caseIterNdx += 1;
|
|
return (m_caseIterNdx < m_numCaseIters) ? CONTINUE : STOP;
|
|
}
|
|
|
|
} // anonymous
|
|
|
|
LongRunningShaderTests::LongRunningShaderTests (Context& context)
|
|
: TestCaseGroup(context, "long_running_shaders", "Long-running shader stress tests")
|
|
{
|
|
}
|
|
|
|
LongRunningShaderTests::~LongRunningShaderTests (void)
|
|
{
|
|
}
|
|
|
|
void LongRunningShaderTests::init (void)
|
|
{
|
|
const int numInvocations = 4096;
|
|
const int shortLoopMin = 5;
|
|
const int shortLoopMax = 10;
|
|
const int mediumLoopMin = 10000;
|
|
const int mediumLoopMax = 50000;
|
|
const int longLoopMin = 100000;
|
|
const int longLoopMax = 500000;
|
|
|
|
static const LongRunningShaderCase::Params s_cases[] =
|
|
{
|
|
{ "short_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, shortLoopMin, shortLoopMax },
|
|
{ "short_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, shortLoopMin, shortLoopMax },
|
|
{ "short_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, shortLoopMin, shortLoopMax },
|
|
{ "short_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, shortLoopMin, shortLoopMax },
|
|
{ "short_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, shortLoopMin, shortLoopMax },
|
|
{ "short_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, shortLoopMin, shortLoopMax },
|
|
|
|
{ "medium_static_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_STATIC, numInvocations, mediumLoopMin, mediumLoopMax },
|
|
{ "medium_static_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_STATIC, numInvocations, mediumLoopMin, mediumLoopMax },
|
|
{ "medium_uniform_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_UNIFORM, numInvocations, mediumLoopMin, mediumLoopMax },
|
|
{ "medium_uniform_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_UNIFORM, numInvocations, mediumLoopMin, mediumLoopMax },
|
|
|
|
{ "medium_dynamic_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, mediumLoopMin, mediumLoopMax },
|
|
{ "medium_dynamic_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, mediumLoopMin, mediumLoopMax },
|
|
{ "medium_dynamic_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, mediumLoopMin, mediumLoopMax },
|
|
{ "medium_dynamic_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, mediumLoopMin, mediumLoopMax },
|
|
{ "medium_dynamic_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, mediumLoopMin, mediumLoopMax },
|
|
{ "medium_dynamic_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, mediumLoopMin, mediumLoopMax },
|
|
|
|
{ "long_static_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_STATIC, numInvocations, longLoopMin, longLoopMax },
|
|
{ "long_static_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_STATIC, numInvocations, longLoopMin, longLoopMax },
|
|
{ "long_uniform_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_UNIFORM, numInvocations, longLoopMin, longLoopMax },
|
|
{ "long_uniform_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_UNIFORM, numInvocations, longLoopMin, longLoopMax },
|
|
|
|
{ "long_dynamic_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, longLoopMin, longLoopMax },
|
|
{ "long_dynamic_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, longLoopMin, longLoopMax },
|
|
{ "long_dynamic_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, longLoopMin, longLoopMax },
|
|
{ "long_dynamic_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, longLoopMin, longLoopMax },
|
|
{ "long_dynamic_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, longLoopMin, longLoopMax },
|
|
{ "long_dynamic_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, longLoopMin, longLoopMax },
|
|
|
|
{ "infinite_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1, -1 },
|
|
{ "infinite_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1, -1 },
|
|
{ "infinite_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1, -1 },
|
|
{ "infinite_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1, -1 },
|
|
{ "infinite_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1, -1 },
|
|
{ "infinite_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1, -1 },
|
|
};
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_cases); ndx++)
|
|
addChild(new LongRunningShaderCase(m_context, &s_cases[ndx]));
|
|
}
|
|
|
|
} // Stress
|
|
} // gles3
|
|
} // deqp
|