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 Draw stress tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3sDrawTests.hpp"
     25 #include "tcuVector.hpp"
     26 #include "tcuTestLog.hpp"
     27 #include "tcuRenderTarget.hpp"
     28 #include "tcuSurface.hpp"
     29 #include "gluCallLogWrapper.hpp"
     30 #include "gluObjectWrapper.hpp"
     31 #include "gluPixelTransfer.hpp"
     32 #include "gluRenderContext.hpp"
     33 #include "gluShaderProgram.hpp"
     34 #include "gluStrUtil.hpp"
     35 #include "glsDrawTest.hpp"
     36 #include "glwFunctions.hpp"
     37 #include "glwEnums.hpp"
     38 #include "deRandom.hpp"
     39 #include "deStringUtil.hpp"
     40 #include "deUniquePtr.hpp"
     41 
     42 #include <set>
     43 
     44 namespace deqp
     45 {
     46 namespace gles3
     47 {
     48 namespace Stress
     49 {
     50 namespace
     51 {
     52 
     53 static const char* const s_vertexSource =		"#version 300 es\n"
     54 												"in highp vec4 a_position;\n"
     55 												"void main (void)\n"
     56 												"{\n"
     57 												"	gl_Position = a_position;\n"
     58 												"}\n";
     59 static const char* const s_fragmentSource =		"#version 300 es\n"
     60 												"layout(location = 0) out mediump vec4 fragColor;\n"
     61 												"void main (void)\n"
     62 												"{\n"
     63 												"	fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
     64 												"}\n";
     65 
     66 class DrawInvalidRangeCase : public TestCase
     67 {
     68 public:
     69 						DrawInvalidRangeCase	(Context& ctx, const char* name, const char* desc, deUint32 min, deUint32 max, bool useLimitMin = false, bool useLimitMax = false);
     70 						~DrawInvalidRangeCase	(void);
     71 
     72 	void				init					(void);
     73 	void				deinit					(void);
     74 	IterateResult		iterate					(void);
     75 
     76 private:
     77 	const int			m_min;
     78 	const int			m_max;
     79 	const int			m_bufferedElements;
     80 	const int			m_numIndices;
     81 	const bool			m_useLimitMin;
     82 	const bool			m_useLimitMax;
     83 
     84 	deUint32			m_buffer;
     85 	deUint32			m_indexBuffer;
     86 	glu::ShaderProgram*	m_program;
     87 };
     88 
     89 DrawInvalidRangeCase::DrawInvalidRangeCase (Context& ctx, const char* name, const char* desc, deUint32 min, deUint32 max, bool useLimitMin, bool useLimitMax)
     90 	: TestCase				(ctx, name, desc)
     91 	, m_min					(min)
     92 	, m_max					(max)
     93 	, m_bufferedElements	(128)
     94 	, m_numIndices			(64)
     95 	, m_useLimitMin			(useLimitMin)
     96 	, m_useLimitMax			(useLimitMax)
     97 	, m_buffer				(0)
     98 	, m_indexBuffer			(0)
     99 	, m_program				(DE_NULL)
    100 {
    101 }
    102 
    103 DrawInvalidRangeCase::~DrawInvalidRangeCase (void)
    104 {
    105 	deinit();
    106 }
    107 
    108 void DrawInvalidRangeCase::init (void)
    109 {
    110 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
    111 	std::vector<tcu::Vec4>	data	(m_bufferedElements); // !< some junk data to make sure buffer is really allocated
    112 	std::vector<deUint32>	indices	(m_numIndices);
    113 
    114 	for (int ndx = 0; ndx < m_numIndices; ++ndx)
    115 		indices[ndx] = ndx;
    116 
    117 	gl.genBuffers(1, &m_buffer);
    118 	gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer);
    119 	gl.bufferData(GL_ARRAY_BUFFER, int(m_bufferedElements * sizeof(tcu::Vec4)), &data[0], GL_STATIC_DRAW);
    120 	GLU_EXPECT_NO_ERROR(gl.getError(), "buffer gen");
    121 
    122 	gl.genBuffers(1, &m_indexBuffer);
    123 	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer);
    124 	gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, int(m_numIndices * sizeof(deUint32)), &indices[0], GL_STATIC_DRAW);
    125 	GLU_EXPECT_NO_ERROR(gl.getError(), "buffer gen");
    126 
    127 	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(s_vertexSource) << glu::FragmentSource(s_fragmentSource));
    128 	if (!m_program->isOk())
    129 	{
    130 		m_testCtx.getLog() << *m_program;
    131 		throw tcu::TestError("could not build program");
    132 	}
    133 }
    134 
    135 void DrawInvalidRangeCase::deinit (void)
    136 {
    137 	if (m_buffer)
    138 	{
    139 		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffer);
    140 		m_buffer = 0;
    141 	}
    142 
    143 	if (m_indexBuffer)
    144 	{
    145 		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_indexBuffer);
    146 		m_indexBuffer = 0;
    147 	}
    148 
    149 	delete m_program;
    150 	m_program = DE_NULL;
    151 }
    152 
    153 DrawInvalidRangeCase::IterateResult DrawInvalidRangeCase::iterate (void)
    154 {
    155 	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    156 	const deInt32			positionLoc = gl.glGetAttribLocation(m_program->getProgram(), "a_position");
    157 	tcu::Surface			dst			(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
    158 	glu::VertexArray		vao			(m_context.getRenderContext());
    159 
    160 	deInt64					indexLimit	= 0;
    161 	deUint32				min			= m_min;
    162 	deUint32				max			= m_max;
    163 
    164 	gl.enableLogging(true);
    165 
    166 	if (m_useLimitMin || m_useLimitMax)
    167 	{
    168 		gl.glGetInteger64v(GL_MAX_ELEMENT_INDEX, &indexLimit);
    169 		GLU_EXPECT_NO_ERROR(gl.glGetError(), "query limit");
    170 	}
    171 
    172 	if (m_useLimitMin)
    173 	{
    174 		if ((deUint64)indexLimit > 0xFFFFFFFFULL)
    175 			min = 0xFFFFFFF0;
    176 		else
    177 			min = (deUint32)(indexLimit - 16);
    178 	}
    179 
    180 	if (m_useLimitMax)
    181 	{
    182 		if ((deUint64)indexLimit > 0xFFFFFFFFULL)
    183 			max = 0xFFFFFFFF;
    184 		else
    185 			max = (deUint32)indexLimit;
    186 	}
    187 
    188 	gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    189 	gl.glClear(GL_COLOR_BUFFER_BIT);
    190 	GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup");
    191 
    192 	gl.glUseProgram(m_program->getProgram());
    193 	GLU_EXPECT_NO_ERROR(gl.glGetError(), "use program");
    194 
    195 	gl.glBindVertexArray(*vao);
    196 	gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer);
    197 
    198 	gl.glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
    199 	gl.glEnableVertexAttribArray(positionLoc);
    200 	gl.glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
    201 	GLU_EXPECT_NO_ERROR(gl.glGetError(), "set buffer");
    202 
    203 	gl.glDrawRangeElements(GL_POINTS, min, max, m_numIndices, GL_UNSIGNED_INT, DE_NULL);
    204 
    205 	// Indexing outside range is an error, but it doesnt need to be checked. Causes implementation-dependent behavior.
    206 	// Even if the indices are in range (m_min = 0), the specification allows partial processing of vertices in the range,
    207 	// which might cause access over buffer bounds. Causes implementation-dependent behavior.
    208 
    209 	// allow errors
    210 	{
    211 		const deUint32 error = gl.glGetError();
    212 
    213 		if (error != GL_NO_ERROR)
    214 			m_testCtx.getLog() << tcu::TestLog::Message << "Got error: " << glu::getErrorStr(error) << ", ignoring..." << tcu::TestLog::EndMessage;
    215 	}
    216 
    217 	// read pixels to wait for rendering
    218 	gl.glFinish();
    219 	glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
    220 
    221 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    222 	return STOP;
    223 }
    224 
    225 static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method)
    226 {
    227 	spec.apiType				= glu::ApiType::es(3,0);
    228 	spec.primitive				= gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
    229 	spec.primitiveCount			= 5;
    230 	spec.drawMethod				= method;
    231 	spec.indexType				= gls::DrawTestSpec::INDEXTYPE_LAST;
    232 	spec.indexPointerOffset		= 0;
    233 	spec.indexStorage			= gls::DrawTestSpec::STORAGE_LAST;
    234 	spec.first					= 0;
    235 	spec.indexMin				= 0;
    236 	spec.indexMax				= 0;
    237 	spec.instanceCount			= 1;
    238 
    239 	spec.attribs.resize(2);
    240 
    241 	spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    242 	spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    243 	spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    244 	spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    245 	spec.attribs[0].componentCount			= 4;
    246 	spec.attribs[0].offset					= 0;
    247 	spec.attribs[0].stride					= 0;
    248 	spec.attribs[0].normalize				= false;
    249 	spec.attribs[0].instanceDivisor			= 0;
    250 	spec.attribs[0].useDefaultAttribute		= false;
    251 
    252 	spec.attribs[1].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    253 	spec.attribs[1].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    254 	spec.attribs[1].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    255 	spec.attribs[1].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    256 	spec.attribs[1].componentCount			= 2;
    257 	spec.attribs[1].offset					= 0;
    258 	spec.attribs[1].stride					= 0;
    259 	spec.attribs[1].normalize				= false;
    260 	spec.attribs[1].instanceDivisor			= 0;
    261 	spec.attribs[1].useDefaultAttribute		= false;
    262 }
    263 
    264 class IndexGroup : public TestCaseGroup
    265 {
    266 public:
    267 									IndexGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
    268 									~IndexGroup		(void);
    269 
    270 	void							init			(void);
    271 
    272 private:
    273 	gls::DrawTestSpec::DrawMethod	m_method;
    274 };
    275 
    276 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
    277 	: TestCaseGroup		(context, name, descr)
    278 	, m_method			(drawMethod)
    279 {
    280 }
    281 
    282 IndexGroup::~IndexGroup (void)
    283 {
    284 }
    285 
    286 void IndexGroup::init (void)
    287 {
    288 	struct IndexTest
    289 	{
    290 		gls::DrawTestSpec::Storage		storage;
    291 		gls::DrawTestSpec::IndexType	type;
    292 		bool							aligned;
    293 		int								offsets[3];
    294 	};
    295 
    296 	const IndexTest tests[] =
    297 	{
    298 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_BYTE,	true,	{ 0, 1, -1 } },
    299 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_SHORT,	true,	{ 0, 2, -1 } },
    300 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_INT,	true,	{ 0, 4, -1 } },
    301 
    302 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_SHORT,	false,	{ 1, 3, -1 } },
    303 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_INT,	false,	{ 2, 3, -1 } },
    304 
    305 		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_BYTE,	true,	{ 0, 1, -1 } },
    306 		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_SHORT,	true,	{ 0, 2, -1 } },
    307 		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_INT,	true,	{ 0, 4, -1 } },
    308 
    309 		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_SHORT,	false,	{ 1, 3, -1 } },
    310 		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_INT,	false,	{ 2, 3, -1 } },
    311 	};
    312 
    313 	gls::DrawTestSpec spec;
    314 
    315 	tcu::TestCaseGroup* const	userPtrGroup			= new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer");
    316 	tcu::TestCaseGroup* const	unalignedUserPtrGroup	= new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer");
    317 	tcu::TestCaseGroup* const	bufferGroup				= new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer");
    318 	tcu::TestCaseGroup* const	unalignedBufferGroup	= new tcu::TestCaseGroup(m_testCtx, "unaligned_buffer", "unaligned buffer");
    319 	const bool					isRangedMethod			= (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED || m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX);
    320 
    321 	genBasicSpec(spec, m_method);
    322 
    323 	this->addChild(userPtrGroup);
    324 	this->addChild(unalignedUserPtrGroup);
    325 	this->addChild(bufferGroup);
    326 	this->addChild(unalignedBufferGroup);
    327 
    328 	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
    329 	{
    330 		const IndexTest&				indexTest	= tests[testNdx];
    331 		tcu::TestCaseGroup*				group		= (indexTest.storage == gls::DrawTestSpec::STORAGE_USER) ? ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup)) : ((indexTest.aligned) ? (bufferGroup) : (unalignedBufferGroup));
    332 
    333 		const std::string				name		= std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
    334 		const std::string				desc		= std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage);
    335 		de::MovePtr<gls::DrawTest>		test		(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()));
    336 
    337 		spec.indexType			= indexTest.type;
    338 		spec.indexStorage		= indexTest.storage;
    339 
    340 		if (isRangedMethod)
    341 		{
    342 			spec.indexMin = 0;
    343 			spec.indexMax = 55;
    344 		}
    345 
    346 		for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
    347 		{
    348 			const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]);
    349 			spec.indexPointerOffset	= indexTest.offsets[iterationNdx];
    350 			test->addIteration(spec, iterationDesc.c_str());
    351 		}
    352 
    353 		if (spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET ||
    354 			spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
    355 			group->addChild(test.release());
    356 	}
    357 }
    358 
    359 class MethodGroup : public TestCaseGroup
    360 {
    361 public:
    362 									MethodGroup			(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
    363 									~MethodGroup		(void);
    364 
    365 	void							init				(void);
    366 
    367 private:
    368 	gls::DrawTestSpec::DrawMethod	m_method;
    369 };
    370 
    371 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
    372 	: TestCaseGroup		(context, name, descr)
    373 	, m_method			(drawMethod)
    374 {
    375 }
    376 
    377 MethodGroup::~MethodGroup (void)
    378 {
    379 }
    380 
    381 void MethodGroup::init (void)
    382 {
    383 	const bool indexed		= (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
    384 
    385 	DE_ASSERT(indexed);
    386 	DE_UNREF(indexed);
    387 
    388 	this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
    389 }
    390 
    391 class RandomGroup : public TestCaseGroup
    392 {
    393 public:
    394 									RandomGroup		(Context& context, const char* name, const char* descr);
    395 									~RandomGroup	(void);
    396 
    397 	void							init			(void);
    398 };
    399 
    400 template <int SIZE>
    401 struct UniformWeightArray
    402 {
    403 	float weights[SIZE];
    404 
    405 	UniformWeightArray (void)
    406 	{
    407 		for (int i=0; i<SIZE; ++i)
    408 			weights[i] = 1.0f;
    409 	}
    410 };
    411 
    412 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
    413 	: TestCaseGroup	(context, name, descr)
    414 {
    415 }
    416 
    417 RandomGroup::~RandomGroup (void)
    418 {
    419 }
    420 
    421 void RandomGroup::init (void)
    422 {
    423 	const int	numAttempts				= 300;
    424 
    425 	const int	attribCounts[]			= { 1, 2, 5 };
    426 	const float	attribWeights[]			= { 30, 10, 1 };
    427 	const int	primitiveCounts[]		= { 1, 5, 64 };
    428 	const float	primitiveCountWeights[]	= { 20, 10, 1 };
    429 	const int	indexOffsets[]			= { 0, 7, 13 };
    430 	const float	indexOffsetWeights[]	= { 20, 20, 1 };
    431 	const int	firsts[]				= { 0, 7, 13 };
    432 	const float	firstWeights[]			= { 20, 20, 1 };
    433 	const int	instanceCounts[]		= { 1, 2, 16, 17 };
    434 	const float	instanceWeights[]		= { 20, 10, 5, 1 };
    435 	const int	indexMins[]				= { 0, 1, 3, 8 };
    436 	const int	indexMaxs[]				= { 4, 8, 128, 257 };
    437 	const float	indexWeights[]			= { 50, 50, 50, 50 };
    438 	const int	offsets[]				= { 0, 1, 5, 12 };
    439 	const float	offsetWeights[]			= { 50, 10, 10, 10 };
    440 	const int	strides[]				= { 0, 7, 16, 17 };
    441 	const float	strideWeights[]			= { 50, 10, 10, 10 };
    442 	const int	instanceDivisors[]		= { 0, 1, 3, 129 };
    443 	const float	instanceDivisorWeights[]= { 70, 30, 10, 10 };
    444 
    445 	gls::DrawTestSpec::Primitive primitives[] =
    446 	{
    447 		gls::DrawTestSpec::PRIMITIVE_POINTS,
    448 		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
    449 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
    450 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
    451 		gls::DrawTestSpec::PRIMITIVE_LINES,
    452 		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
    453 		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
    454 	};
    455 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
    456 
    457 	gls::DrawTestSpec::DrawMethod drawMethods[] =
    458 	{
    459 		gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
    460 		gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED,
    461 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
    462 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED,
    463 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED
    464 	};
    465 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
    466 
    467 	gls::DrawTestSpec::IndexType indexTypes[] =
    468 	{
    469 		gls::DrawTestSpec::INDEXTYPE_BYTE,
    470 		gls::DrawTestSpec::INDEXTYPE_SHORT,
    471 		gls::DrawTestSpec::INDEXTYPE_INT,
    472 	};
    473 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
    474 
    475 	gls::DrawTestSpec::Storage storages[] =
    476 	{
    477 		gls::DrawTestSpec::STORAGE_USER,
    478 		gls::DrawTestSpec::STORAGE_BUFFER,
    479 	};
    480 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights;
    481 
    482 	gls::DrawTestSpec::InputType inputTypes[] =
    483 	{
    484 		gls::DrawTestSpec::INPUTTYPE_FLOAT,
    485 		gls::DrawTestSpec::INPUTTYPE_FIXED,
    486 		gls::DrawTestSpec::INPUTTYPE_BYTE,
    487 		gls::DrawTestSpec::INPUTTYPE_SHORT,
    488 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
    489 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT,
    490 		gls::DrawTestSpec::INPUTTYPE_INT,
    491 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT,
    492 		gls::DrawTestSpec::INPUTTYPE_HALF,
    493 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
    494 		gls::DrawTestSpec::INPUTTYPE_INT_2_10_10_10,
    495 	};
    496 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
    497 
    498 	gls::DrawTestSpec::OutputType outputTypes[] =
    499 	{
    500 		gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
    501 		gls::DrawTestSpec::OUTPUTTYPE_VEC2,
    502 		gls::DrawTestSpec::OUTPUTTYPE_VEC3,
    503 		gls::DrawTestSpec::OUTPUTTYPE_VEC4,
    504 		gls::DrawTestSpec::OUTPUTTYPE_INT,
    505 		gls::DrawTestSpec::OUTPUTTYPE_UINT,
    506 		gls::DrawTestSpec::OUTPUTTYPE_IVEC2,
    507 		gls::DrawTestSpec::OUTPUTTYPE_IVEC3,
    508 		gls::DrawTestSpec::OUTPUTTYPE_IVEC4,
    509 		gls::DrawTestSpec::OUTPUTTYPE_UVEC2,
    510 		gls::DrawTestSpec::OUTPUTTYPE_UVEC3,
    511 		gls::DrawTestSpec::OUTPUTTYPE_UVEC4,
    512 	};
    513 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
    514 
    515 	gls::DrawTestSpec::Usage usages[] =
    516 	{
    517 		gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
    518 		gls::DrawTestSpec::USAGE_STATIC_DRAW,
    519 		gls::DrawTestSpec::USAGE_STREAM_DRAW,
    520 		gls::DrawTestSpec::USAGE_STREAM_READ,
    521 		gls::DrawTestSpec::USAGE_STREAM_COPY,
    522 		gls::DrawTestSpec::USAGE_STATIC_READ,
    523 		gls::DrawTestSpec::USAGE_STATIC_COPY,
    524 		gls::DrawTestSpec::USAGE_DYNAMIC_READ,
    525 		gls::DrawTestSpec::USAGE_DYNAMIC_COPY,
    526 	};
    527 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
    528 
    529 	std::set<deUint32>	insertedHashes;
    530 	size_t				insertedCount = 0;
    531 
    532 	for (int ndx = 0; ndx < numAttempts; ++ndx)
    533 	{
    534 		de::Random random(0xc551393 + ndx); // random does not depend on previous cases
    535 
    536 		int					attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
    537 		gls::DrawTestSpec	spec;
    538 
    539 		spec.apiType				= glu::ApiType::es(3,0);
    540 		spec.primitive				= random.chooseWeighted<gls::DrawTestSpec::Primitive>	(DE_ARRAY_BEGIN(primitives),		DE_ARRAY_END(primitives),		primitiveWeights.weights);
    541 		spec.primitiveCount			= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(primitiveCounts),	DE_ARRAY_END(primitiveCounts),	primitiveCountWeights);
    542 		spec.drawMethod				= random.chooseWeighted<gls::DrawTestSpec::DrawMethod>	(DE_ARRAY_BEGIN(drawMethods),		DE_ARRAY_END(drawMethods),		drawMethodWeights.weights);
    543 		spec.indexType				= random.chooseWeighted<gls::DrawTestSpec::IndexType>	(DE_ARRAY_BEGIN(indexTypes),		DE_ARRAY_END(indexTypes),		indexTypeWeights.weights);
    544 		spec.indexPointerOffset		= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexOffsets),		DE_ARRAY_END(indexOffsets),		indexOffsetWeights);
    545 		spec.indexStorage			= random.chooseWeighted<gls::DrawTestSpec::Storage>		(DE_ARRAY_BEGIN(storages),			DE_ARRAY_END(storages),			storageWeights.weights);
    546 		spec.first					= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(firsts),			DE_ARRAY_END(firsts),			firstWeights);
    547 		spec.indexMin				= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexMins),			DE_ARRAY_END(indexMins),		indexWeights);
    548 		spec.indexMax				= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexMaxs),			DE_ARRAY_END(indexMaxs),		indexWeights);
    549 		spec.instanceCount			= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(instanceCounts),	DE_ARRAY_END(instanceCounts),	instanceWeights);
    550 
    551 		// check spec is legal
    552 		if (!spec.valid())
    553 			continue;
    554 
    555 		for (int attrNdx = 0; attrNdx < attributeCount;)
    556 		{
    557 			bool valid;
    558 			gls::DrawTestSpec::AttributeSpec attribSpec;
    559 
    560 			attribSpec.inputType			= random.chooseWeighted<gls::DrawTestSpec::InputType>	(DE_ARRAY_BEGIN(inputTypes),		DE_ARRAY_END(inputTypes),		inputTypeWeights.weights);
    561 			attribSpec.outputType			= random.chooseWeighted<gls::DrawTestSpec::OutputType>	(DE_ARRAY_BEGIN(outputTypes),		DE_ARRAY_END(outputTypes),		outputTypeWeights.weights);
    562 			attribSpec.storage				= random.chooseWeighted<gls::DrawTestSpec::Storage>		(DE_ARRAY_BEGIN(storages),			DE_ARRAY_END(storages),			storageWeights.weights);
    563 			attribSpec.usage				= random.chooseWeighted<gls::DrawTestSpec::Usage>		(DE_ARRAY_BEGIN(usages),			DE_ARRAY_END(usages),			usageWeights.weights);
    564 			attribSpec.componentCount		= random.getInt(1, 4);
    565 			attribSpec.offset				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
    566 			attribSpec.stride				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
    567 			attribSpec.normalize			= random.getBool();
    568 			attribSpec.instanceDivisor		= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(instanceDivisors), DE_ARRAY_END(instanceDivisors), instanceDivisorWeights);
    569 			attribSpec.useDefaultAttribute	= random.getBool();
    570 
    571 			// check spec is legal
    572 			valid = attribSpec.valid(spec.apiType);
    573 
    574 			// we do not want interleaved elements. (Might result in some weird floating point values)
    575 			if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
    576 				valid = false;
    577 
    578 			// try again if not valid
    579 			if (valid)
    580 			{
    581 				spec.attribs.push_back(attribSpec);
    582 				++attrNdx;
    583 			}
    584 		}
    585 
    586 		// Do not collapse all vertex positions to a single positions
    587 		if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
    588 			spec.attribs[0].instanceDivisor = 0;
    589 
    590 		// Is render result meaningful?
    591 		{
    592 			// Only one vertex
    593 			if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
    594 				continue;
    595 			if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
    596 				continue;
    597 
    598 			// Triangle only on one axis
    599 			if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
    600 			{
    601 				if (spec.attribs[0].componentCount == 1)
    602 					continue;
    603 				if (spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_FLOAT || spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_INT || spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_UINT)
    604 					continue;
    605 				if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
    606 					continue;
    607 			}
    608 		}
    609 
    610 		// Add case
    611 		{
    612 			deUint32 hash = spec.hash();
    613 			for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
    614 				hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
    615 
    616 			if (insertedHashes.find(hash) == insertedHashes.end())
    617 			{
    618 				// Only unaligned cases
    619 				if (spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET ||
    620 					spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
    621 					this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
    622 				insertedHashes.insert(hash);
    623 
    624 				++insertedCount;
    625 			}
    626 		}
    627 	}
    628 }
    629 
    630 } // anonymous
    631 
    632 DrawTests::DrawTests (Context& context)
    633 	: TestCaseGroup(context, "draw", "Draw stress tests")
    634 {
    635 }
    636 
    637 DrawTests::~DrawTests (void)
    638 {
    639 }
    640 
    641 void DrawTests::init (void)
    642 {
    643 	tcu::TestCaseGroup* const unalignedGroup	= new tcu::TestCaseGroup(m_testCtx, "unaligned_data", "Test with unaligned data");
    644 	tcu::TestCaseGroup* const drawRangeGroup	= new tcu::TestCaseGroup(m_testCtx, "draw_range_elements", "Test drawRangeElements");
    645 
    646 	addChild(unalignedGroup);
    647 	addChild(drawRangeGroup);
    648 
    649 	// .unaligned_data
    650 	{
    651 		const gls::DrawTestSpec::DrawMethod basicMethods[] =
    652 		{
    653 			// gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
    654 			gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
    655 			// gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED,
    656 			gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED,
    657 			gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED,
    658 		};
    659 
    660 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
    661 		{
    662 			const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
    663 			const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
    664 
    665 			unalignedGroup->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
    666 		}
    667 
    668 		// Random
    669 
    670 		unalignedGroup->addChild(new RandomGroup(m_context, "random", "random draw commands."));
    671 	}
    672 
    673 	// .draw_range_elements
    674 	{
    675 		// use a larger range than the buffer size is
    676 		drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_max_over_bounds",							"Range over buffer bounds",	0x00000000,	0x00210000));
    677 		drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_max_over_bounds_near_signed_wrap",			"Range over buffer bounds",	0x00000000,	0x7FFFFFFF));
    678 		drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_max_over_bounds_near_unsigned_wrap",		"Range over buffer bounds",	0x00000000,	0xFFFFFFFF));
    679 		drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_max_over_bounds_near_max",					"Range over buffer bounds",	0x00000000, 0x00000000, false, true));
    680 
    681 		drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_min_max_over_bounds",						"Range over buffer bounds",	0x00200000,	0x00210000));
    682 		drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_min_max_over_bounds_near_signed_wrap",		"Range over buffer bounds",	0x7FFFFFF0,	0x7FFFFFFF));
    683 		drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_min_max_over_bounds_near_unsigned_wrap",	"Range over buffer bounds",	0xFFFFFFF0,	0xFFFFFFFF));
    684 		drawRangeGroup->addChild(new DrawInvalidRangeCase(m_context, "range_min_max_over_bounds_near_max",				"Range over buffer bounds",	0x00000000, 0x00000000, true, true));
    685 	}
    686 }
    687 
    688 } // Stress
    689 } // gles3
    690 } // deqp
    691