Home | History | Annotate | Download | only in stress
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 2.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 Drawing tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es2sDrawTests.hpp"
     25 #include "glsDrawTest.hpp"
     26 #include "tcuRenderTarget.hpp"
     27 #include "deRandom.hpp"
     28 #include "deStringUtil.hpp"
     29 #include "deUniquePtr.hpp"
     30 
     31 #include "glwEnums.hpp"
     32 
     33 #include <set>
     34 
     35 namespace deqp
     36 {
     37 namespace gles2
     38 {
     39 namespace Stress
     40 {
     41 namespace
     42 {
     43 
     44 static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method)
     45 {
     46 	spec.apiType							= glu::ApiType::es(2,0);
     47 	spec.primitive							= gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
     48 	spec.primitiveCount						= 5;
     49 	spec.drawMethod							= method;
     50 	spec.indexType							= gls::DrawTestSpec::INDEXTYPE_LAST;
     51 	spec.indexPointerOffset					= 0;
     52 	spec.indexStorage						= gls::DrawTestSpec::STORAGE_LAST;
     53 	spec.first								= 0;
     54 	spec.indexMin							= 0;
     55 	spec.indexMax							= 0;
     56 	spec.instanceCount						= 1;
     57 
     58 	spec.attribs.resize(2);
     59 
     60 	spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
     61 	spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
     62 	spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
     63 	spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
     64 	spec.attribs[0].componentCount			= 4;
     65 	spec.attribs[0].offset					= 0;
     66 	spec.attribs[0].stride					= 0;
     67 	spec.attribs[0].normalize				= false;
     68 	spec.attribs[0].instanceDivisor			= 0;
     69 	spec.attribs[0].useDefaultAttribute		= false;
     70 
     71 	spec.attribs[1].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
     72 	spec.attribs[1].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
     73 	spec.attribs[1].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
     74 	spec.attribs[1].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
     75 	spec.attribs[1].componentCount			= 2;
     76 	spec.attribs[1].offset					= 0;
     77 	spec.attribs[1].stride					= 0;
     78 	spec.attribs[1].normalize				= false;
     79 	spec.attribs[1].instanceDivisor			= 0;
     80 	spec.attribs[1].useDefaultAttribute		= false;
     81 }
     82 
     83 class IndexGroup : public TestCaseGroup
     84 {
     85 public:
     86 									IndexGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
     87 									~IndexGroup		(void);
     88 
     89 	void							init			(void);
     90 
     91 private:
     92 	gls::DrawTestSpec::DrawMethod	m_method;
     93 };
     94 
     95 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
     96 	: TestCaseGroup		(context, name, descr)
     97 	, m_method			(drawMethod)
     98 {
     99 }
    100 
    101 IndexGroup::~IndexGroup (void)
    102 {
    103 }
    104 
    105 void IndexGroup::init (void)
    106 {
    107 	struct IndexTest
    108 	{
    109 		gls::DrawTestSpec::Storage		storage;
    110 		gls::DrawTestSpec::IndexType	type;
    111 		bool							aligned;
    112 		int								offsets[3];
    113 	};
    114 
    115 	const IndexTest tests[] =
    116 	{
    117 		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_SHORT,	false,	{ 1, 3, -1 } },
    118 	};
    119 
    120 	gls::DrawTestSpec spec;
    121 
    122 	tcu::TestCaseGroup* unalignedBufferGroup	= new tcu::TestCaseGroup(m_testCtx, "unaligned_buffer", "unaligned buffer");
    123 
    124 	genBasicSpec(spec, m_method);
    125 
    126 	this->addChild(unalignedBufferGroup);
    127 
    128 	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
    129 	{
    130 		const IndexTest&				indexTest	= tests[testNdx];
    131 
    132 		DE_ASSERT(indexTest.storage != gls::DrawTestSpec::STORAGE_USER);
    133 		DE_ASSERT(!indexTest.aligned);
    134 		tcu::TestCaseGroup*				group		= unalignedBufferGroup;
    135 
    136 		const std::string				name		= std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
    137 		const std::string				desc		= std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage);
    138 		de::MovePtr<gls::DrawTest>		test		(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()));
    139 
    140 		spec.indexType			= indexTest.type;
    141 		spec.indexStorage		= indexTest.storage;
    142 
    143 		for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
    144 		{
    145 			const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]);
    146 			spec.indexPointerOffset	= indexTest.offsets[iterationNdx];
    147 			test->addIteration(spec, iterationDesc.c_str());
    148 		}
    149 
    150 		DE_ASSERT(spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET ||
    151 				  spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE);
    152 		group->addChild(test.release());
    153 	}
    154 }
    155 
    156 class MethodGroup : public TestCaseGroup
    157 {
    158 public:
    159 									MethodGroup			(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
    160 									~MethodGroup		(void);
    161 
    162 	void							init				(void);
    163 
    164 private:
    165 	gls::DrawTestSpec::DrawMethod	m_method;
    166 };
    167 
    168 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
    169 	: TestCaseGroup		(context, name, descr)
    170 	, m_method			(drawMethod)
    171 {
    172 }
    173 
    174 MethodGroup::~MethodGroup (void)
    175 {
    176 }
    177 
    178 void MethodGroup::init (void)
    179 {
    180 	const bool indexed = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
    181 
    182 	DE_ASSERT(indexed);
    183 	DE_UNREF(indexed);
    184 
    185 	this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
    186 }
    187 
    188 class RandomGroup : public TestCaseGroup
    189 {
    190 public:
    191 									RandomGroup		(Context& context, const char* name, const char* descr);
    192 									~RandomGroup	(void);
    193 
    194 	void							init			(void);
    195 };
    196 
    197 template <int SIZE>
    198 struct UniformWeightArray
    199 {
    200 	float weights[SIZE];
    201 
    202 	UniformWeightArray (void)
    203 	{
    204 		for (int i=0; i<SIZE; ++i)
    205 			weights[i] = 1.0f;
    206 	}
    207 };
    208 
    209 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
    210 	: TestCaseGroup	(context, name, descr)
    211 {
    212 }
    213 
    214 RandomGroup::~RandomGroup (void)
    215 {
    216 }
    217 
    218 void RandomGroup::init (void)
    219 {
    220 	const int	numAttempts				= 100;
    221 
    222 	const int	attribCounts[]			= { 1, 2, 5 };
    223 	const float	attribWeights[]			= { 30, 10, 1 };
    224 	const int	primitiveCounts[]		= { 1, 5, 64 };
    225 	const float	primitiveCountWeights[]	= { 20, 10, 1 };
    226 	const int	indexOffsets[]			= { 0, 7, 13 };
    227 	const float	indexOffsetWeights[]	= { 20, 20, 1 };
    228 	const int	firsts[]				= { 0, 7, 13 };
    229 	const float	firstWeights[]			= { 20, 20, 1 };
    230 	const int	offsets[]				= { 0, 1, 5, 12 };
    231 	const float	offsetWeights[]			= { 50, 10, 10, 10 };
    232 	const int	strides[]				= { 0, 7, 16, 17 };
    233 	const float	strideWeights[]			= { 50, 10, 10, 10 };
    234 
    235 	gls::DrawTestSpec::Primitive primitives[] =
    236 	{
    237 		gls::DrawTestSpec::PRIMITIVE_POINTS,
    238 		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
    239 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
    240 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
    241 		gls::DrawTestSpec::PRIMITIVE_LINES,
    242 		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
    243 		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
    244 	};
    245 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
    246 
    247 	gls::DrawTestSpec::DrawMethod drawMethods[] =
    248 	{
    249 		gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
    250 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
    251 	};
    252 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
    253 
    254 	gls::DrawTestSpec::IndexType indexTypes[] =
    255 	{
    256 		gls::DrawTestSpec::INDEXTYPE_BYTE,
    257 		gls::DrawTestSpec::INDEXTYPE_SHORT,
    258 	};
    259 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
    260 
    261 	gls::DrawTestSpec::Storage storages[] =
    262 	{
    263 		gls::DrawTestSpec::STORAGE_USER,
    264 		gls::DrawTestSpec::STORAGE_BUFFER,
    265 	};
    266 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights;
    267 
    268 	gls::DrawTestSpec::InputType inputTypes[] =
    269 	{
    270 		gls::DrawTestSpec::INPUTTYPE_FLOAT,
    271 		gls::DrawTestSpec::INPUTTYPE_FIXED,
    272 		gls::DrawTestSpec::INPUTTYPE_BYTE,
    273 		gls::DrawTestSpec::INPUTTYPE_SHORT,
    274 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
    275 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT
    276 	};
    277 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
    278 
    279 	gls::DrawTestSpec::OutputType outputTypes[] =
    280 	{
    281 		gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
    282 		gls::DrawTestSpec::OUTPUTTYPE_VEC2,
    283 		gls::DrawTestSpec::OUTPUTTYPE_VEC3,
    284 		gls::DrawTestSpec::OUTPUTTYPE_VEC4,
    285 	};
    286 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
    287 
    288 	gls::DrawTestSpec::Usage usages[] =
    289 	{
    290 		gls::DrawTestSpec::USAGE_STATIC_DRAW,
    291 		gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
    292 		gls::DrawTestSpec::USAGE_STREAM_DRAW,
    293 	};
    294 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
    295 
    296 	const deUint32 blacklistedCases[]=
    297 	{
    298 		3153,	//!< extremely narrow triangle, results depend on sample positions
    299 	};
    300 
    301 	std::set<deUint32>	insertedHashes;
    302 	size_t				insertedCount = 0;
    303 
    304 	for (int ndx = 0; ndx < numAttempts; ++ndx)
    305 	{
    306 		de::Random random(0xc551393 + ndx); // random does not depend on previous cases
    307 
    308 		int					attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
    309 		gls::DrawTestSpec	spec;
    310 
    311 		spec.apiType				= glu::ApiType::es(2,0);
    312 		spec.primitive				= random.chooseWeighted<gls::DrawTestSpec::Primitive>	(DE_ARRAY_BEGIN(primitives),		DE_ARRAY_END(primitives),		primitiveWeights.weights);
    313 		spec.primitiveCount			= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(primitiveCounts),	DE_ARRAY_END(primitiveCounts),	primitiveCountWeights);
    314 		spec.drawMethod				= random.chooseWeighted<gls::DrawTestSpec::DrawMethod>	(DE_ARRAY_BEGIN(drawMethods),		DE_ARRAY_END(drawMethods),		drawMethodWeights.weights);
    315 		spec.indexType				= random.chooseWeighted<gls::DrawTestSpec::IndexType>	(DE_ARRAY_BEGIN(indexTypes),		DE_ARRAY_END(indexTypes),		indexTypeWeights.weights);
    316 		spec.indexPointerOffset		= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexOffsets),		DE_ARRAY_END(indexOffsets),		indexOffsetWeights);
    317 		spec.indexStorage			= random.chooseWeighted<gls::DrawTestSpec::Storage>		(DE_ARRAY_BEGIN(storages),			DE_ARRAY_END(storages),			storageWeights.weights);
    318 		spec.first					= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(firsts),			DE_ARRAY_END(firsts),			firstWeights);
    319 		spec.indexMin				= 0;
    320 		spec.indexMax				= 0;
    321 		spec.instanceCount			= 0;
    322 
    323 		// check spec is legal
    324 		if (!spec.valid())
    325 			continue;
    326 
    327 		for (int attrNdx = 0; attrNdx < attributeCount;)
    328 		{
    329 			bool valid;
    330 			gls::DrawTestSpec::AttributeSpec attribSpec;
    331 
    332 			attribSpec.inputType			= random.chooseWeighted<gls::DrawTestSpec::InputType>	(DE_ARRAY_BEGIN(inputTypes),		DE_ARRAY_END(inputTypes),		inputTypeWeights.weights);
    333 			attribSpec.outputType			= random.chooseWeighted<gls::DrawTestSpec::OutputType>	(DE_ARRAY_BEGIN(outputTypes),		DE_ARRAY_END(outputTypes),		outputTypeWeights.weights);
    334 			attribSpec.storage				= random.chooseWeighted<gls::DrawTestSpec::Storage>		(DE_ARRAY_BEGIN(storages),			DE_ARRAY_END(storages),			storageWeights.weights);
    335 			attribSpec.usage				= random.chooseWeighted<gls::DrawTestSpec::Usage>		(DE_ARRAY_BEGIN(usages),			DE_ARRAY_END(usages),			usageWeights.weights);
    336 			attribSpec.componentCount		= random.getInt(1, 4);
    337 			attribSpec.offset				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
    338 			attribSpec.stride				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
    339 			attribSpec.normalize			= random.getBool();
    340 			attribSpec.instanceDivisor		= 0;
    341 			attribSpec.useDefaultAttribute	= random.getBool();
    342 
    343 			// check spec is legal
    344 			valid = attribSpec.valid(spec.apiType);
    345 
    346 			// we do not want interleaved elements. (Might result in some weird floating point values)
    347 			if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
    348 				valid = false;
    349 
    350 			// try again if not valid
    351 			if (valid)
    352 			{
    353 				spec.attribs.push_back(attribSpec);
    354 				++attrNdx;
    355 			}
    356 		}
    357 
    358 		// Do not collapse all vertex positions to a single positions
    359 		if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
    360 			spec.attribs[0].instanceDivisor = 0;
    361 
    362 		// Is render result meaningful?
    363 		{
    364 			// Only one vertex
    365 			if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
    366 				continue;
    367 			if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
    368 				continue;
    369 
    370 			// Triangle only on one axis
    371 			if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
    372 			{
    373 				if (spec.attribs[0].componentCount == 1)
    374 					continue;
    375 				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)
    376 					continue;
    377 				if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
    378 					continue;
    379 			}
    380 		}
    381 
    382 		// Add case
    383 		{
    384 			deUint32 hash = spec.hash();
    385 			for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
    386 				hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
    387 
    388 			if (insertedHashes.find(hash) == insertedHashes.end() &&
    389 				std::find(DE_ARRAY_BEGIN(blacklistedCases), DE_ARRAY_END(blacklistedCases), hash) == DE_ARRAY_END(blacklistedCases))
    390 			{
    391 				// Only unaligned cases
    392 				if (spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET ||
    393 					spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
    394 					this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
    395 				insertedHashes.insert(hash);
    396 
    397 				++insertedCount;
    398 			}
    399 		}
    400 	}
    401 }
    402 
    403 } // anonymous
    404 
    405 DrawTests::DrawTests (Context& context)
    406 	: TestCaseGroup(context, "draw", "Drawing tests")
    407 {
    408 }
    409 
    410 DrawTests::~DrawTests (void)
    411 {
    412 }
    413 
    414 void DrawTests::init (void)
    415 {
    416 	tcu::TestCaseGroup* const unalignedGroup	= new tcu::TestCaseGroup(m_testCtx, "unaligned_data", "Test with unaligned data");
    417 
    418 	addChild(unalignedGroup);
    419 
    420 	// .unaligned_data
    421 	{
    422 		const gls::DrawTestSpec::DrawMethod basicMethods[] =
    423 		{
    424 			// gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
    425 			gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
    426 		};
    427 
    428 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
    429 		{
    430 			std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
    431 			std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
    432 
    433 			unalignedGroup->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
    434 		}
    435 
    436 		// Random
    437 
    438 		unalignedGroup->addChild(new RandomGroup(m_context, "random", "random draw commands."));
    439 	}
    440 
    441 }
    442 
    443 } // Stress
    444 } // gles2
    445 } // deqp
    446