Home | History | Annotate | Download | only in stress
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.0 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 Long running shader stress tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3sLongRunningShaderTests.hpp"
     25 
     26 #include "gluShaderProgram.hpp"
     27 #include "gluShaderUtil.hpp"
     28 #include "gluDrawUtil.hpp"
     29 
     30 #include "tcuRenderTarget.hpp"
     31 #include "tcuVector.hpp"
     32 #include "tcuTestLog.hpp"
     33 
     34 #include "deRandom.hpp"
     35 #include "deStringUtil.hpp"
     36 #include "deString.h"
     37 
     38 #include "glwFunctions.hpp"
     39 #include "glwEnums.hpp"
     40 
     41 namespace deqp
     42 {
     43 namespace gles3
     44 {
     45 namespace Stress
     46 {
     47 
     48 using tcu::TestLog;
     49 using tcu::Vec2;
     50 using std::vector;
     51 
     52 namespace
     53 {
     54 
     55 enum LoopType
     56 {
     57 	LOOPTYPE_FOR = 0,
     58 	LOOPTYPE_WHILE,
     59 	LOOPTYPE_DO_WHILE,
     60 
     61 	LOOPTYPE_LAST
     62 };
     63 
     64 enum IterCountType
     65 {
     66 	ITERCOUNTTYPE_STATIC = 0,
     67 	ITERCOUNTTYPE_UNIFORM,
     68 	ITERCOUNTTYPE_DYNAMIC,
     69 
     70 	ITERCOUNTTYPE_LAST
     71 };
     72 
     73 class LongRunningShaderCase : public TestCase
     74 {
     75 public:
     76 	struct Params
     77 	{
     78 		const char*			name;
     79 		const char*			description;
     80 		glu::ShaderType		shaderType;
     81 		LoopType			loopType;
     82 		IterCountType		iterCountType;
     83 		int					numInvocations;
     84 		int					minLoopIterCount;
     85 		int					maxLoopIterCount;
     86 	};
     87 
     88 								LongRunningShaderCase		(Context& context, const Params* params);
     89 								~LongRunningShaderCase		(void);
     90 
     91 	void						init						(void);
     92 	void						deinit						(void);
     93 	IterateResult				iterate						(void);
     94 
     95 private:
     96 								LongRunningShaderCase		(const LongRunningShaderCase&);
     97 	LongRunningShaderCase&		operator=					(const LongRunningShaderCase&);
     98 
     99 	static glu::ProgramSources	genSources					(const Params& params);
    100 	static deUint32				getSeed						(const Params& params);
    101 
    102 	const Params* const			m_params;
    103 	const int					m_numCaseIters;
    104 
    105 	glu::ShaderProgram*			m_program;
    106 	int							m_caseIterNdx;
    107 };
    108 
    109 LongRunningShaderCase::LongRunningShaderCase (Context& context, const Params* params)
    110 	: TestCase			(context, params->name, params->description)
    111 	, m_params			(params)
    112 	, m_numCaseIters	(5)
    113 	, m_program			(DE_NULL)
    114 	, m_caseIterNdx		(0)
    115 {
    116 }
    117 
    118 LongRunningShaderCase::~LongRunningShaderCase (void)
    119 {
    120 	deinit();
    121 }
    122 
    123 glu::ProgramSources LongRunningShaderCase::genSources (const Params& params)
    124 {
    125 	const bool			isVertCase		= params.shaderType == glu::SHADERTYPE_VERTEX;
    126 	std::ostringstream	vert, frag;
    127 
    128 	vert << "#version 300 es\n"
    129 		 << "in highp vec2 a_position;\n";
    130 
    131 	frag << "#version 300 es\n";
    132 
    133 	if (params.iterCountType == ITERCOUNTTYPE_DYNAMIC)
    134 	{
    135 		vert << "in highp int a_iterCount;\n";
    136 		if (!isVertCase)
    137 		{
    138 			vert << "flat out highp int v_iterCount;\n";
    139 			frag << "flat in highp int v_iterCount;\n";
    140 		}
    141 	}
    142 	else if (params.iterCountType == ITERCOUNTTYPE_UNIFORM)
    143 		(isVertCase ? vert : frag) << "uniform highp int u_iterCount;\n";
    144 
    145 	if (isVertCase)
    146 	{
    147 		vert << "out mediump vec4 v_color;\n";
    148 		frag << "in mediump vec4 v_color;\n";
    149 	}
    150 
    151 	frag << "out mediump vec4 o_color;\n";
    152 
    153 	vert << "\nvoid main (void)\n{\n"
    154 		 << "	gl_Position = vec4(a_position, 0.0, 1.0);\n"
    155 		 << "	gl_PointSize = 1.0;\n";
    156 
    157 	if (!isVertCase && params.iterCountType == ITERCOUNTTYPE_DYNAMIC)
    158 		vert << "	v_iterCount = a_iterCount;\n";
    159 
    160 	frag << "\nvoid main (void)\n{\n";
    161 
    162 	{
    163 		const std::string	iterCount	= params.iterCountType == ITERCOUNTTYPE_DYNAMIC ? (isVertCase ? "a_iterCount" : "v_iterCount")	:
    164 										  params.iterCountType == ITERCOUNTTYPE_UNIFORM ? "u_iterCount"									:
    165 										  params.iterCountType == ITERCOUNTTYPE_STATIC	? de::toString(params.maxLoopIterCount)			: "<invalid>";
    166 		const char* const	body		= "color = cos(sin(color*1.25)*0.8);";
    167 		std::ostringstream&	op			= isVertCase ? vert : frag;
    168 
    169 		op << "	mediump vec4 color = " << (isVertCase ? "a_position.xyxy" : "gl_FragCoord") << ";\n";
    170 
    171 		if (params.loopType == LOOPTYPE_FOR)
    172 		{
    173 			op << "	for (highp int i = 0; i < " << iterCount << " || " << iterCount << " < 0; ++i)\n"
    174 			   << "		" << body << "\n";
    175 		}
    176 		else if (params.loopType == LOOPTYPE_WHILE)
    177 		{
    178 			op << "	highp int i = 0;\n"
    179 			   << "	while (i < " << iterCount << " || " << iterCount << " < 0) {\n"
    180 			   << "		i += 1;\n"
    181 			   << "		" << body << "\n"
    182 			   << "	}\n";
    183 		}
    184 		else
    185 		{
    186 			DE_ASSERT(params.loopType == LOOPTYPE_DO_WHILE);
    187 			op << "	highp int i = 0;\n"
    188 			   << "	do {\n"
    189 			   << "		i += 1;\n"
    190 			   << "		" << body << "\n"
    191 			   << "	} while (i <= " << iterCount << " || " << iterCount << " < 0);\n";
    192 		}
    193 	}
    194 
    195 	if (isVertCase)
    196 	{
    197 		vert << "	v_color = color;\n";
    198 		frag << "	o_color = v_color;\n";
    199 	}
    200 	else
    201 		frag << "	o_color = color;\n";
    202 
    203 	vert << "}\n";
    204 	frag << "}\n";
    205 
    206 	return glu::ProgramSources() << glu::VertexSource(vert.str()) << glu::FragmentSource(frag.str());
    207 }
    208 
    209 void LongRunningShaderCase::init (void)
    210 {
    211 	DE_ASSERT(!m_program);
    212 	m_program = new glu::ShaderProgram(m_context.getRenderContext(), genSources(*m_params));
    213 
    214 	m_testCtx.getLog() << *m_program;
    215 
    216 	if (!m_program->isOk())
    217 	{
    218 		deinit();
    219 		TCU_FAIL("Failed to compile shader program");
    220 	}
    221 
    222 	m_caseIterNdx = 0;
    223 
    224 	if (m_params->iterCountType != ITERCOUNTTYPE_STATIC)
    225 	{
    226 		m_testCtx.getLog() << TestLog::Message << "Loop iteration counts in range: [" << m_params->minLoopIterCount
    227 											   << ", " << m_params->maxLoopIterCount << "]"
    228 						   << TestLog::EndMessage;
    229 	}
    230 
    231 	m_testCtx.getLog() << TestLog::Message << "Number of vertices and fragments: " << m_params->numInvocations << TestLog::EndMessage;
    232 
    233 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Test will pass or timeout, unless driver/device crashes.
    234 }
    235 
    236 void LongRunningShaderCase::deinit (void)
    237 {
    238 	delete m_program;
    239 	m_program = DE_NULL;
    240 }
    241 
    242 void genPositions (const tcu::RenderTarget& renderTarget, int numPoints, Vec2* positions)
    243 {
    244 	const int	width		= renderTarget.getWidth();
    245 	const int	height		= renderTarget.getHeight();
    246 
    247 	if (width*height < numPoints)
    248 		throw tcu::NotSupportedError("Too small viewport to fit all test points");
    249 
    250 	for (int pointNdx = 0; pointNdx < numPoints; pointNdx++)
    251 	{
    252 		const int		xi		= pointNdx % width;
    253 		const int		yi		= pointNdx / height;
    254 		const float		xf		= 2.0f * ((float(xi) + 0.5f) / float(width)) - 1.0f;
    255 		const float		yf		= 2.0f * ((float(yi) + 0.5f) / float(height)) - 1.0f;
    256 
    257 		positions[pointNdx] = Vec2(xf, yf);
    258 	}
    259 }
    260 
    261 deUint32 LongRunningShaderCase::getSeed (const Params& params)
    262 {
    263 	const deUint32	seed	= deStringHash(params.name)
    264 							^ deInt32Hash(params.shaderType)
    265 							^ deInt32Hash(params.loopType)
    266 							^ deInt32Hash(params.iterCountType)
    267 							^ deInt32Hash(params.minLoopIterCount)
    268 							^ deInt32Hash(params.maxLoopIterCount)
    269 							^ deInt32Hash(params.numInvocations);
    270 	return seed;
    271 }
    272 
    273 LongRunningShaderCase::IterateResult LongRunningShaderCase::iterate (void)
    274 {
    275 	const glw::Functions&			gl				= m_context.getRenderContext().getFunctions();
    276 	de::Random						rnd				(getSeed(*m_params));
    277 	vector<Vec2>					positions		(m_params->numInvocations);
    278 	vector<int>						iterCounts		(m_params->iterCountType == ITERCOUNTTYPE_DYNAMIC ? m_params->numInvocations : 1);
    279 	vector<glu::VertexArrayBinding>	vertexArrays;
    280 
    281 	vertexArrays.push_back(glu::va::Float("a_position", 2, (int)positions.size(), 0, positions[0].getPtr()));
    282 	if (m_params->iterCountType == ITERCOUNTTYPE_DYNAMIC)
    283 		vertexArrays.push_back(glu::va::Int32("a_iterCount", 1, (int)iterCounts.size(), 0, &iterCounts[0]));
    284 
    285 	genPositions(m_context.getRenderTarget(), (int)positions.size(), &positions[0]);
    286 
    287 	for (vector<int>::iterator i = iterCounts.begin(); i != iterCounts.end(); ++i)
    288 		*i = rnd.getInt(m_params->minLoopIterCount, m_params->maxLoopIterCount);
    289 
    290 	gl.useProgram(m_program->getProgram());
    291 
    292 	if (m_params->iterCountType == ITERCOUNTTYPE_UNIFORM)
    293 		gl.uniform1i(gl.getUniformLocation(m_program->getProgram(), "u_iterCount"), iterCounts[0]);
    294 
    295 	glu::draw(m_context.getRenderContext(), m_program->getProgram(),
    296 			  (int)vertexArrays.size(), &vertexArrays[0],
    297 			  glu::pr::Points(m_params->numInvocations));
    298 
    299 	m_caseIterNdx += 1;
    300 	return (m_caseIterNdx < m_numCaseIters) ? CONTINUE : STOP;
    301 }
    302 
    303 } // anonymous
    304 
    305 LongRunningShaderTests::LongRunningShaderTests (Context& context)
    306 	: TestCaseGroup(context, "long_running_shaders",	"Long-running shader stress tests")
    307 {
    308 }
    309 
    310 LongRunningShaderTests::~LongRunningShaderTests (void)
    311 {
    312 }
    313 
    314 void LongRunningShaderTests::init (void)
    315 {
    316 	const int	numInvocations	= 4096;
    317 	const int	shortLoopMin	= 5;
    318 	const int	shortLoopMax	= 10;
    319 	const int	mediumLoopMin	= 10000;
    320 	const int	mediumLoopMax	= 50000;
    321 	const int	longLoopMin		= 100000;
    322 	const int	longLoopMax		= 500000;
    323 
    324 	static const LongRunningShaderCase::Params s_cases[] =
    325 	{
    326 		{ "short_for_vertex",					"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_FOR,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	shortLoopMin,	shortLoopMax	},
    327 		{ "short_for_fragment",					"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_FOR,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	shortLoopMin,	shortLoopMax	},
    328 		{ "short_while_vertex",					"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_WHILE,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	shortLoopMin,	shortLoopMax	},
    329 		{ "short_while_fragment",				"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_WHILE,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	shortLoopMin,	shortLoopMax	},
    330 		{ "short_do_while_vertex",				"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_DO_WHILE,	ITERCOUNTTYPE_DYNAMIC,	numInvocations,	shortLoopMin,	shortLoopMax	},
    331 		{ "short_do_while_fragment",			"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_DO_WHILE,	ITERCOUNTTYPE_DYNAMIC,	numInvocations,	shortLoopMin,	shortLoopMax	},
    332 
    333 		{ "medium_static_for_vertex",			"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_FOR,		ITERCOUNTTYPE_STATIC,	numInvocations,	mediumLoopMin,	mediumLoopMax	},
    334 		{ "medium_static_while_fragment",		"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_WHILE,		ITERCOUNTTYPE_STATIC,	numInvocations,	mediumLoopMin,	mediumLoopMax	},
    335 		{ "medium_uniform_do_while_vertex",		"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_DO_WHILE,	ITERCOUNTTYPE_UNIFORM,	numInvocations,	mediumLoopMin,	mediumLoopMax	},
    336 		{ "medium_uniform_for_fragment",		"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_FOR,		ITERCOUNTTYPE_UNIFORM,	numInvocations,	mediumLoopMin,	mediumLoopMax	},
    337 
    338 		{ "medium_dynamic_for_vertex",			"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_FOR,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	mediumLoopMin,	mediumLoopMax	},
    339 		{ "medium_dynamic_for_fragment",		"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_FOR,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	mediumLoopMin,	mediumLoopMax	},
    340 		{ "medium_dynamic_while_vertex",		"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_WHILE,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	mediumLoopMin,	mediumLoopMax	},
    341 		{ "medium_dynamic_while_fragment",		"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_WHILE,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	mediumLoopMin,	mediumLoopMax	},
    342 		{ "medium_dynamic_do_while_vertex",		"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_DO_WHILE,	ITERCOUNTTYPE_DYNAMIC,	numInvocations,	mediumLoopMin,	mediumLoopMax	},
    343 		{ "medium_dynamic_do_while_fragment",	"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_DO_WHILE,	ITERCOUNTTYPE_DYNAMIC,	numInvocations,	mediumLoopMin,	mediumLoopMax	},
    344 
    345 		{ "long_static_while_vertex",			"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_WHILE,		ITERCOUNTTYPE_STATIC,	numInvocations,	longLoopMin,	longLoopMax		},
    346 		{ "long_static_do_while_fragment",		"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_DO_WHILE,	ITERCOUNTTYPE_STATIC,	numInvocations,	longLoopMin,	longLoopMax		},
    347 		{ "long_uniform_for_vertex",			"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_FOR,		ITERCOUNTTYPE_UNIFORM,	numInvocations,	longLoopMin,	longLoopMax		},
    348 		{ "long_uniform_do_while_fragment",		"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_DO_WHILE,	ITERCOUNTTYPE_UNIFORM,	numInvocations,	longLoopMin,	longLoopMax		},
    349 
    350 		{ "long_dynamic_for_vertex",			"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_FOR,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	longLoopMin,	longLoopMax		},
    351 		{ "long_dynamic_for_fragment",			"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_FOR,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	longLoopMin,	longLoopMax		},
    352 		{ "long_dynamic_while_vertex",			"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_WHILE,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	longLoopMin,	longLoopMax		},
    353 		{ "long_dynamic_while_fragment",		"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_WHILE,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	longLoopMin,	longLoopMax		},
    354 		{ "long_dynamic_do_while_vertex",		"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_DO_WHILE,	ITERCOUNTTYPE_DYNAMIC,	numInvocations,	longLoopMin,	longLoopMax		},
    355 		{ "long_dynamic_do_while_fragment",		"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_DO_WHILE,	ITERCOUNTTYPE_DYNAMIC,	numInvocations,	longLoopMin,	longLoopMax		},
    356 
    357 		{ "infinite_for_vertex",				"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_FOR,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	-1,				-1				},
    358 		{ "infinite_for_fragment",				"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_FOR,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	-1,				-1				},
    359 		{ "infinite_while_vertex",				"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_WHILE,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	-1,				-1				},
    360 		{ "infinite_while_fragment",			"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_WHILE,		ITERCOUNTTYPE_DYNAMIC,	numInvocations,	-1,				-1				},
    361 		{ "infinite_do_while_vertex",			"",	glu::SHADERTYPE_VERTEX,		LOOPTYPE_DO_WHILE,	ITERCOUNTTYPE_DYNAMIC,	numInvocations,	-1,				-1				},
    362 		{ "infinite_do_while_fragment",			"",	glu::SHADERTYPE_FRAGMENT,	LOOPTYPE_DO_WHILE,	ITERCOUNTTYPE_DYNAMIC,	numInvocations,	-1,				-1				},
    363 	};
    364 
    365 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_cases); ndx++)
    366 		addChild(new LongRunningShaderCase(m_context, &s_cases[ndx]));
    367 }
    368 
    369 } // Stress
    370 } // gles3
    371 } // deqp
    372