Home | History | Annotate | Download | only in stress
      1 
      2 /*-------------------------------------------------------------------------
      3  * drawElements Quality Program OpenGL ES 3.1 Module
      4  * -------------------------------------------------
      5  *
      6  * Copyright 2014 The Android Open Source Project
      7  *
      8  * Licensed under the Apache License, Version 2.0 (the "License");
      9  * you may not use this file except in compliance with the License.
     10  * You may obtain a copy of the License at
     11  *
     12  *      http://www.apache.org/licenses/LICENSE-2.0
     13  *
     14  * Unless required by applicable law or agreed to in writing, software
     15  * distributed under the License is distributed on an "AS IS" BASIS,
     16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     17  * See the License for the specific language governing permissions and
     18  * limitations under the License.
     19  *
     20  *//*!
     21  * \file
     22  * \brief Drawing stress tests.
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "es31sDrawTests.hpp"
     26 #include "glsDrawTest.hpp"
     27 #include "gluRenderContext.hpp"
     28 #include "gluCallLogWrapper.hpp"
     29 #include "gluShaderProgram.hpp"
     30 #include "glwEnums.hpp"
     31 #include "glwFunctions.hpp"
     32 #include "deRandom.hpp"
     33 #include "deStringUtil.hpp"
     34 #include "deUniquePtr.hpp"
     35 
     36 #include <set>
     37 
     38 namespace deqp
     39 {
     40 namespace gles31
     41 {
     42 namespace Stress
     43 {
     44 namespace
     45 {
     46 
     47 static const char* s_colorVertexShaderSource =		"#version 310 es\n"
     48 													"in highp vec4 a_position;\n"
     49 													"in highp vec4 a_color;\n"
     50 													"out highp vec4 v_color;\n"
     51 													"void main (void)\n"
     52 													"{\n"
     53 													"	gl_Position = a_position;\n"
     54 													"	v_color = a_color;\n"
     55 													"}\n";
     56 static const char* s_colorFragmentShaderSource	=	"#version 310 es\n"
     57 													"layout(location = 0) out highp vec4 fragColor;\n"
     58 													"in highp vec4 v_color;\n"
     59 													"void main (void)\n"
     60 													"{\n"
     61 													"	fragColor = v_color;\n"
     62 													"}\n";
     63 struct DrawElementsCommand
     64 {
     65 	deUint32 count;
     66 	deUint32 primCount;
     67 	deUint32 firstIndex;
     68 	deInt32  baseVertex;
     69 	deUint32 reservedMustBeZero;
     70 };
     71 DE_STATIC_ASSERT(5 * sizeof(deUint32) == sizeof(DrawElementsCommand)); // tight packing
     72 
     73 struct DrawArraysCommand
     74 {
     75 	deUint32 count;
     76 	deUint32 primCount;
     77 	deUint32 first;
     78 	deUint32 reservedMustBeZero;
     79 };
     80 DE_STATIC_ASSERT(4 * sizeof(deUint32) == sizeof(DrawArraysCommand)); // tight packing
     81 
     82 class InvalidDrawCase : public TestCase
     83 {
     84 public:
     85 	enum DrawType
     86 	{
     87 		DRAW_ARRAYS,
     88 		DRAW_ELEMENTS,
     89 
     90 		DRAW_LAST
     91 	};
     92 	enum InvalidOperation
     93 	{
     94 		INVALID_DATA_COUNT = 0,
     95 		INVALID_DATA_FIRST,
     96 		INVALID_DATA_INSTANCED,
     97 		INVALID_INDEX_COUNT,
     98 		INVALID_INDEX_FIRST,
     99 		INVALID_RESERVED,
    100 		INVALID_INDEX,
    101 
    102 		INVALID_LAST
    103 	};
    104 
    105 							InvalidDrawCase		(Context& context, const char* name, const char* desc, DrawType type, InvalidOperation op);
    106 							~InvalidDrawCase	(void);
    107 
    108 	void					init				(void);
    109 	void					deinit				(void);
    110 	IterateResult			iterate				(void);
    111 
    112 private:
    113 	const DrawType			m_drawType;
    114 	const InvalidOperation	m_op;
    115 	glw::GLuint				m_dataBufferID;
    116 	glw::GLuint				m_indexBufferID;
    117 	glw::GLuint				m_cmdBufferID;
    118 	glw::GLuint				m_colorBufferID;
    119 	glw::GLuint				m_vao;
    120 };
    121 
    122 InvalidDrawCase::InvalidDrawCase (Context& context, const char* name, const char* desc, DrawType type, InvalidOperation op)
    123 	: TestCase			(context, name, desc)
    124 	, m_drawType		(type)
    125 	, m_op				(op)
    126 	, m_dataBufferID	(0)
    127 	, m_indexBufferID	(0)
    128 	, m_cmdBufferID		(0)
    129 	, m_colorBufferID	(0)
    130 	, m_vao				(0)
    131 {
    132 	DE_ASSERT(type < DRAW_LAST);
    133 	DE_ASSERT(op < INVALID_LAST);
    134 }
    135 
    136 InvalidDrawCase::~InvalidDrawCase (void)
    137 {
    138 	deinit();
    139 }
    140 
    141 void InvalidDrawCase::init (void)
    142 {
    143 }
    144 
    145 void InvalidDrawCase::deinit (void)
    146 {
    147 	if (m_dataBufferID)
    148 	{
    149 		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_dataBufferID);
    150 		m_dataBufferID = 0;
    151 	}
    152 	if (m_indexBufferID)
    153 	{
    154 		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_indexBufferID);
    155 		m_indexBufferID = 0;
    156 	}
    157 	if (m_cmdBufferID)
    158 	{
    159 		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_cmdBufferID);
    160 		m_cmdBufferID = 0;
    161 	}
    162 	if (m_colorBufferID)
    163 	{
    164 		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_colorBufferID);
    165 		m_colorBufferID = 0;
    166 	}
    167 	if (m_vao)
    168 	{
    169 		m_context.getRenderContext().getFunctions().deleteVertexArrays(1, &m_vao);
    170 		m_vao = 0;
    171 	}
    172 }
    173 
    174 InvalidDrawCase::IterateResult InvalidDrawCase::iterate (void)
    175 {
    176 	const int drawCount				= 10;		//!< number of elements safe to draw (all buffers have this)
    177 	const int overBoundDrawCount	= 10000;	//!< number of elements in all other buffers than our target buffer
    178 	const int drawInstances			= 1;
    179 	const int overBoundInstances	= 1000;
    180 
    181 	glu::CallLogWrapper gl				(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    182 	glu::ShaderProgram	program			(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(s_colorVertexShaderSource) << glu::FragmentSource(s_colorFragmentShaderSource));
    183 	const deUint32		programID		= program.getProgram();
    184 	const deInt32		posLocation		= gl.glGetAttribLocation(programID, "a_position");
    185 	const deInt32		colorLocation	= gl.glGetAttribLocation(programID, "a_color");
    186 
    187 	gl.enableLogging(true);
    188 
    189 	gl.glGenVertexArrays(1, &m_vao);
    190 	gl.glBindVertexArray(m_vao);
    191 	glu::checkError(gl.glGetError(), "gen vao", __FILE__, __LINE__);
    192 
    193 	// indices
    194 	if (m_drawType == DRAW_ELEMENTS)
    195 	{
    196 		const int				indexBufferSize = (m_op == INVALID_INDEX_COUNT) ? (drawCount) : (overBoundDrawCount);
    197 		std::vector<deUint16>	indices			(indexBufferSize);
    198 
    199 		for (int ndx = 0; ndx < (int)indices.size(); ++ndx)
    200 			indices[ndx] = (deUint16)((m_op == INVALID_INDEX) ? (overBoundDrawCount + ndx) : (ndx));
    201 
    202 		gl.glGenBuffers(1, &m_indexBufferID);
    203 		gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBufferID);
    204 		gl.glBufferData(GL_ELEMENT_ARRAY_BUFFER, (int)(indices.size() * sizeof(deUint16)), &indices[0], GL_STATIC_DRAW);
    205 		glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
    206 	}
    207 
    208 	// data
    209 	{
    210 		const int dataSize = (m_op == INVALID_DATA_COUNT) ? (drawCount) : (overBoundDrawCount);
    211 
    212 		// any data is ok
    213 		gl.glGenBuffers(1, &m_dataBufferID);
    214 		gl.glBindBuffer(GL_ARRAY_BUFFER, m_dataBufferID);
    215 		gl.glBufferData(GL_ARRAY_BUFFER, dataSize * sizeof(float[4]), DE_NULL, GL_STATIC_DRAW);
    216 		gl.glVertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
    217 		gl.glEnableVertexAttribArray(posLocation);
    218 		glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
    219 	}
    220 
    221 	// potentially instanced data
    222 	{
    223 		const int dataSize = drawInstances;
    224 
    225 		gl.glGenBuffers(1, &m_colorBufferID);
    226 		gl.glBindBuffer(GL_ARRAY_BUFFER, m_colorBufferID);
    227 		gl.glBufferData(GL_ARRAY_BUFFER, dataSize * sizeof(float[4]), DE_NULL, GL_STATIC_DRAW);
    228 		gl.glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
    229 		gl.glEnableVertexAttribArray(colorLocation);
    230 		gl.glVertexAttribDivisor(colorLocation, 1);
    231 		glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
    232 	}
    233 
    234 	// command
    235 	if (m_drawType == DRAW_ARRAYS)
    236 	{
    237 		DrawArraysCommand drawCommand;
    238 		drawCommand.count				= overBoundDrawCount;
    239 		drawCommand.primCount			= (m_op == INVALID_DATA_INSTANCED)	? (overBoundInstances)	: (drawInstances);
    240 		drawCommand.first				= (m_op == INVALID_DATA_FIRST)		? (overBoundDrawCount)	: (0);
    241 		drawCommand.reservedMustBeZero	= (m_op == INVALID_RESERVED)		? (5)					: (0);
    242 
    243 		m_testCtx.getLog()
    244 			<< tcu::TestLog::Message
    245 			<< "drawCommand:"
    246 			<< "\n\tcount:\t" << drawCommand.count
    247 			<< "\n\tprimCount\t" << drawCommand.primCount
    248 			<< "\n\tfirst\t" << drawCommand.first
    249 			<< "\n\treservedMustBeZero\t" << drawCommand.reservedMustBeZero
    250 			<< tcu::TestLog::EndMessage;
    251 
    252 		gl.glGenBuffers(1, &m_cmdBufferID);
    253 		gl.glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_cmdBufferID);
    254 		gl.glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(drawCommand), &drawCommand, GL_STATIC_DRAW);
    255 		glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
    256 	}
    257 	else if (m_drawType == DRAW_ELEMENTS)
    258 	{
    259 		DrawElementsCommand drawCommand;
    260 		drawCommand.count				= overBoundDrawCount;
    261 		drawCommand.primCount			= (m_op == INVALID_DATA_INSTANCED)	? (overBoundInstances)	: (drawInstances);
    262 		drawCommand.firstIndex			= (m_op == INVALID_INDEX_FIRST)		? (overBoundDrawCount)	: (0);
    263 		drawCommand.baseVertex			= (m_op == INVALID_DATA_FIRST)		? (overBoundDrawCount)	: (0);
    264 		drawCommand.reservedMustBeZero	= (m_op == INVALID_RESERVED)		? (5)					: (0);
    265 
    266 		m_testCtx.getLog()
    267 			<< tcu::TestLog::Message
    268 			<< "drawCommand:"
    269 			<< "\n\tcount:\t" << drawCommand.count
    270 			<< "\n\tprimCount\t" << drawCommand.primCount
    271 			<< "\n\tfirstIndex\t" << drawCommand.firstIndex
    272 			<< "\n\tbaseVertex\t" << drawCommand.baseVertex
    273 			<< "\n\treservedMustBeZero\t" << drawCommand.reservedMustBeZero
    274 			<< tcu::TestLog::EndMessage;
    275 
    276 		gl.glGenBuffers(1, &m_cmdBufferID);
    277 		gl.glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_cmdBufferID);
    278 		gl.glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(drawCommand), &drawCommand, GL_STATIC_DRAW);
    279 		glu::checkError(gl.glGetError(), "", __FILE__, __LINE__);
    280 	}
    281 	else
    282 		DE_ASSERT(DE_FALSE);
    283 
    284 	gl.glViewport(0, 0, 1, 1);
    285 	gl.glUseProgram(programID);
    286 
    287 	if (m_drawType == DRAW_ELEMENTS)
    288 		gl.glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, DE_NULL);
    289 	else if (m_drawType == DRAW_ARRAYS)
    290 		gl.glDrawArraysIndirect(GL_TRIANGLES, DE_NULL);
    291 	else
    292 		DE_ASSERT(DE_FALSE);
    293 
    294 	gl.glUseProgram(0);
    295 	gl.glFinish();
    296 
    297 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    298 	return STOP;
    299 }
    300 
    301 class RandomGroup : public TestCaseGroup
    302 {
    303 public:
    304 			RandomGroup		(Context& context, const char* name, const char* descr);
    305 			~RandomGroup	(void);
    306 
    307 	void	init			(void);
    308 };
    309 
    310 template <int SIZE>
    311 struct UniformWeightArray
    312 {
    313 	float weights[SIZE];
    314 
    315 	UniformWeightArray (void)
    316 	{
    317 		for (int i=0; i<SIZE; ++i)
    318 			weights[i] = 1.0f;
    319 	}
    320 };
    321 
    322 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
    323 	: TestCaseGroup	(context, name, descr)
    324 {
    325 }
    326 
    327 RandomGroup::~RandomGroup (void)
    328 {
    329 }
    330 
    331 void RandomGroup::init (void)
    332 {
    333 	const int	numAttempts				= 100;
    334 
    335 	const int	attribCounts[]			= { 1,   2,   5 };
    336 	const float	attribWeights[]			= { 30, 10,   1 };
    337 	const int	primitiveCounts[]		= { 1,   5,  64 };
    338 	const float	primitiveCountWeights[]	= { 20, 10,   1 };
    339 	const int	indexOffsets[]			= { 0,   7,  13 };
    340 	const float	indexOffsetWeights[]	= { 20, 20,   1 };
    341 	const int	firsts[]				= { 0,   7,  13 };
    342 	const float	firstWeights[]			= { 20, 20,   1 };
    343 
    344 	const int	instanceCounts[]		= { 1,   2,  16,  17 };
    345 	const float	instanceWeights[]		= { 20, 10,   5,   1 };
    346 	const int	indexMins[]				= { 0,   1,   3,   8 };
    347 	const int	indexMaxs[]				= { 4,   8, 128, 257 };
    348 	const float	indexWeights[]			= { 50, 50,  50,  50 };
    349 	const int	offsets[]				= { 0,   1,   5,  12 };
    350 	const float	offsetWeights[]			= { 50, 10,  10,  10 };
    351 	const int	strides[]				= { 0,   7,  16,  17 };
    352 	const float	strideWeights[]			= { 50, 10,  10,  10 };
    353 	const int	instanceDivisors[]		= { 0,   1,   3, 129 };
    354 	const float	instanceDivisorWeights[]= { 70, 30,  10,  10 };
    355 
    356 	const int	indirectOffsets[]		= { 0,   1,   2 };
    357 	const float indirectOffsetWeigths[]	= { 2,   1,   1 };
    358 	const int	baseVertices[]			= { 0,   1,  -2,   4,  3 };
    359 	const float baseVertexWeigths[]		= { 4,   1,   1,   1,  1 };
    360 
    361 	gls::DrawTestSpec::Primitive primitives[] =
    362 	{
    363 		gls::DrawTestSpec::PRIMITIVE_POINTS,
    364 		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
    365 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
    366 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
    367 		gls::DrawTestSpec::PRIMITIVE_LINES,
    368 		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
    369 		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
    370 	};
    371 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
    372 
    373 	gls::DrawTestSpec::DrawMethod drawMethods[] =
    374 	{
    375 		gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INDIRECT,
    376 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INDIRECT,
    377 	};
    378 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
    379 
    380 	gls::DrawTestSpec::IndexType indexTypes[] =
    381 	{
    382 		gls::DrawTestSpec::INDEXTYPE_BYTE,
    383 		gls::DrawTestSpec::INDEXTYPE_SHORT,
    384 		gls::DrawTestSpec::INDEXTYPE_INT,
    385 	};
    386 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
    387 
    388 	gls::DrawTestSpec::InputType inputTypes[] =
    389 	{
    390 		gls::DrawTestSpec::INPUTTYPE_FLOAT,
    391 		gls::DrawTestSpec::INPUTTYPE_FIXED,
    392 		gls::DrawTestSpec::INPUTTYPE_BYTE,
    393 		gls::DrawTestSpec::INPUTTYPE_SHORT,
    394 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
    395 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT,
    396 		gls::DrawTestSpec::INPUTTYPE_INT,
    397 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT,
    398 		gls::DrawTestSpec::INPUTTYPE_HALF,
    399 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
    400 		gls::DrawTestSpec::INPUTTYPE_INT_2_10_10_10,
    401 	};
    402 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
    403 
    404 	gls::DrawTestSpec::OutputType outputTypes[] =
    405 	{
    406 		gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
    407 		gls::DrawTestSpec::OUTPUTTYPE_VEC2,
    408 		gls::DrawTestSpec::OUTPUTTYPE_VEC3,
    409 		gls::DrawTestSpec::OUTPUTTYPE_VEC4,
    410 		gls::DrawTestSpec::OUTPUTTYPE_INT,
    411 		gls::DrawTestSpec::OUTPUTTYPE_UINT,
    412 		gls::DrawTestSpec::OUTPUTTYPE_IVEC2,
    413 		gls::DrawTestSpec::OUTPUTTYPE_IVEC3,
    414 		gls::DrawTestSpec::OUTPUTTYPE_IVEC4,
    415 		gls::DrawTestSpec::OUTPUTTYPE_UVEC2,
    416 		gls::DrawTestSpec::OUTPUTTYPE_UVEC3,
    417 		gls::DrawTestSpec::OUTPUTTYPE_UVEC4,
    418 	};
    419 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
    420 
    421 	gls::DrawTestSpec::Usage usages[] =
    422 	{
    423 		gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
    424 		gls::DrawTestSpec::USAGE_STATIC_DRAW,
    425 		gls::DrawTestSpec::USAGE_STREAM_DRAW,
    426 		gls::DrawTestSpec::USAGE_STREAM_READ,
    427 		gls::DrawTestSpec::USAGE_STREAM_COPY,
    428 		gls::DrawTestSpec::USAGE_STATIC_READ,
    429 		gls::DrawTestSpec::USAGE_STATIC_COPY,
    430 		gls::DrawTestSpec::USAGE_DYNAMIC_READ,
    431 		gls::DrawTestSpec::USAGE_DYNAMIC_COPY,
    432 	};
    433 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
    434 
    435 	std::set<deUint32>	insertedHashes;
    436 	size_t				insertedCount = 0;
    437 
    438 	for (int ndx = 0; ndx < numAttempts; ++ndx)
    439 	{
    440 		de::Random random(0xc551393 + ndx); // random does not depend on previous cases
    441 
    442 		int					attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
    443 		int					drawCommandSize;
    444 		gls::DrawTestSpec	spec;
    445 
    446 		spec.apiType				= glu::ApiType::es(3,1);
    447 		spec.primitive				= random.chooseWeighted<gls::DrawTestSpec::Primitive>	(DE_ARRAY_BEGIN(primitives),		DE_ARRAY_END(primitives),		primitiveWeights.weights);
    448 		spec.primitiveCount			= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(primitiveCounts),	DE_ARRAY_END(primitiveCounts),	primitiveCountWeights);
    449 		spec.drawMethod				= random.chooseWeighted<gls::DrawTestSpec::DrawMethod>	(DE_ARRAY_BEGIN(drawMethods),		DE_ARRAY_END(drawMethods),		drawMethodWeights.weights);
    450 
    451 		if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INDIRECT)
    452 			drawCommandSize = sizeof(deUint32[4]);
    453 		else if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INDIRECT)
    454 			drawCommandSize = sizeof(deUint32[5]);
    455 		else
    456 		{
    457 			DE_ASSERT(DE_FALSE);
    458 			return;
    459 		}
    460 
    461 		spec.indexType				= random.chooseWeighted<gls::DrawTestSpec::IndexType>	(DE_ARRAY_BEGIN(indexTypes),		DE_ARRAY_END(indexTypes),		indexTypeWeights.weights);
    462 		spec.indexPointerOffset		= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexOffsets),		DE_ARRAY_END(indexOffsets),		indexOffsetWeights);
    463 		spec.indexStorage			= gls::DrawTestSpec::STORAGE_BUFFER;
    464 		spec.first					= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(firsts),			DE_ARRAY_END(firsts),			firstWeights);
    465 		spec.indexMin				= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexMins),			DE_ARRAY_END(indexMins),		indexWeights);
    466 		spec.indexMax				= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexMaxs),			DE_ARRAY_END(indexMaxs),		indexWeights);
    467 		spec.instanceCount			= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(instanceCounts),	DE_ARRAY_END(instanceCounts),	instanceWeights);
    468 		spec.indirectOffset			= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indirectOffsets),	DE_ARRAY_END(indirectOffsets),	indirectOffsetWeigths) * drawCommandSize;
    469 		spec.baseVertex				= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(baseVertices),		DE_ARRAY_END(baseVertices),		baseVertexWeigths);
    470 
    471 		// check spec is legal
    472 		if (!spec.valid())
    473 			continue;
    474 
    475 		for (int attrNdx = 0; attrNdx < attributeCount;)
    476 		{
    477 			bool valid;
    478 			gls::DrawTestSpec::AttributeSpec attribSpec;
    479 
    480 			attribSpec.inputType			= random.chooseWeighted<gls::DrawTestSpec::InputType>	(DE_ARRAY_BEGIN(inputTypes),		DE_ARRAY_END(inputTypes),		inputTypeWeights.weights);
    481 			attribSpec.outputType			= random.chooseWeighted<gls::DrawTestSpec::OutputType>	(DE_ARRAY_BEGIN(outputTypes),		DE_ARRAY_END(outputTypes),		outputTypeWeights.weights);
    482 			attribSpec.storage				= gls::DrawTestSpec::STORAGE_BUFFER;
    483 			attribSpec.usage				= random.chooseWeighted<gls::DrawTestSpec::Usage>		(DE_ARRAY_BEGIN(usages),			DE_ARRAY_END(usages),			usageWeights.weights);
    484 			attribSpec.componentCount		= random.getInt(1, 4);
    485 			attribSpec.offset				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
    486 			attribSpec.stride				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
    487 			attribSpec.normalize			= random.getBool();
    488 			attribSpec.instanceDivisor		= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(instanceDivisors), DE_ARRAY_END(instanceDivisors), instanceDivisorWeights);
    489 			attribSpec.useDefaultAttribute	= random.getBool();
    490 
    491 			// check spec is legal
    492 			valid = attribSpec.valid(spec.apiType);
    493 
    494 			// we do not want interleaved elements. (Might result in some weird floating point values)
    495 			if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
    496 				valid = false;
    497 
    498 			// try again if not valid
    499 			if (valid)
    500 			{
    501 				spec.attribs.push_back(attribSpec);
    502 				++attrNdx;
    503 			}
    504 		}
    505 
    506 		// Do not collapse all vertex positions to a single positions
    507 		if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
    508 			spec.attribs[0].instanceDivisor = 0;
    509 
    510 		// Is render result meaningful?
    511 		{
    512 			// Only one vertex
    513 			if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
    514 				continue;
    515 			if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
    516 				continue;
    517 
    518 			// Triangle only on one axis
    519 			if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
    520 			{
    521 				if (spec.attribs[0].componentCount == 1)
    522 					continue;
    523 				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)
    524 					continue;
    525 				if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
    526 					continue;
    527 			}
    528 		}
    529 
    530 		// Add case
    531 		{
    532 			deUint32 hash = spec.hash();
    533 			for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
    534 				hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
    535 
    536 			if (insertedHashes.find(hash) == insertedHashes.end())
    537 			{
    538 				// Only unaligned cases
    539 				if (spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET ||
    540 					spec.isCompatibilityTest() == gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
    541 					this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
    542 				insertedHashes.insert(hash);
    543 
    544 				++insertedCount;
    545 			}
    546 		}
    547 	}
    548 }
    549 
    550 } // anonymous
    551 
    552 DrawTests::DrawTests (Context& context)
    553 	: TestCaseGroup(context, "draw_indirect", "Indirect drawing tests")
    554 {
    555 }
    556 
    557 DrawTests::~DrawTests (void)
    558 {
    559 }
    560 
    561 void DrawTests::init (void)
    562 {
    563 	tcu::TestCaseGroup* const unalignedGroup	= new tcu::TestCaseGroup(m_testCtx, "unaligned_data", "Test with unaligned data");
    564 	tcu::TestCaseGroup* const drawArraysGroup	= new tcu::TestCaseGroup(m_testCtx, "drawarrays", "draw arrays");
    565 	tcu::TestCaseGroup* const drawElementsGroup	= new tcu::TestCaseGroup(m_testCtx, "drawelements", "draw elements");
    566 
    567 	addChild(unalignedGroup);
    568 	addChild(drawArraysGroup);
    569 	addChild(drawElementsGroup);
    570 
    571 	// .unaligned_data
    572 	{
    573 		unalignedGroup->addChild(new RandomGroup(m_context, "random", "random draw commands."));
    574 	}
    575 
    576 	// .drawarrays
    577 	{
    578 		drawArraysGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_count",			"Draw arrays vertex elements beyond the array end are accessed",	InvalidDrawCase::DRAW_ARRAYS,	InvalidDrawCase::INVALID_DATA_COUNT));
    579 		drawArraysGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_first",			"Draw arrays vertex elements beyond the array end are accessed",	InvalidDrawCase::DRAW_ARRAYS,	InvalidDrawCase::INVALID_DATA_FIRST));
    580 		drawArraysGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_primcount",		"Draw arrays vertex elements beyond the array end are accessed",	InvalidDrawCase::DRAW_ARRAYS,	InvalidDrawCase::INVALID_DATA_INSTANCED));
    581 		drawArraysGroup->addChild(new InvalidDrawCase(m_context, "reserved_non_zero",					"reservedMustBeZero is set to non-zero value",						InvalidDrawCase::DRAW_ARRAYS,	InvalidDrawCase::INVALID_RESERVED));
    582 	}
    583 
    584 	// .drawelements
    585 	{
    586 		drawElementsGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_count",		"Draw elements vertex elements beyond the array end are accessed",	InvalidDrawCase::DRAW_ELEMENTS, InvalidDrawCase::INVALID_DATA_COUNT));
    587 		drawElementsGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_basevertex",	"Draw elements vertex elements beyond the array end are accessed",	InvalidDrawCase::DRAW_ELEMENTS,	InvalidDrawCase::INVALID_DATA_FIRST));
    588 		drawElementsGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_indices",		"Draw elements vertex elements beyond the array end are accessed",	InvalidDrawCase::DRAW_ELEMENTS,	InvalidDrawCase::INVALID_INDEX));
    589 		drawElementsGroup->addChild(new InvalidDrawCase(m_context, "data_over_bounds_with_primcount",	"Draw elements vertex elements beyond the array end are accessed",	InvalidDrawCase::DRAW_ELEMENTS,	InvalidDrawCase::INVALID_DATA_INSTANCED));
    590 		drawElementsGroup->addChild(new InvalidDrawCase(m_context, "index_over_bounds_with_count",		"Draw elements index elements beyond the array end are accessed",	InvalidDrawCase::DRAW_ELEMENTS,	InvalidDrawCase::INVALID_INDEX_COUNT));
    591 		drawElementsGroup->addChild(new InvalidDrawCase(m_context, "index_over_bounds_with_firstindex",	"Draw elements index elements beyond the array end are accessed",	InvalidDrawCase::DRAW_ELEMENTS,	InvalidDrawCase::INVALID_INDEX_FIRST));
    592 		drawElementsGroup->addChild(new InvalidDrawCase(m_context, "reserved_non_zero",					"reservedMustBeZero is set to non-zero value",						InvalidDrawCase::DRAW_ELEMENTS,	InvalidDrawCase::INVALID_RESERVED));
    593 	}
    594 }
    595 
    596 } // Stress
    597 } // gles31
    598 } // deqp
    599