Home | History | Annotate | Download | only in gles31
      1 /*-------------------------------------------------------------------------
      2  * OpenGL Conformance Test Suite
      3  * -----------------------------
      4  *
      5  * Copyright (c) 2014-2016 The Khronos Group Inc.
      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
     22  */ /*-------------------------------------------------------------------*/
     23 
     24 #include "es31cDrawIndirectTests.hpp"
     25 #include "gluContextInfo.hpp"
     26 #include "glwEnums.hpp"
     27 #include "tcuMatrix.hpp"
     28 #include "tcuRenderTarget.hpp"
     29 #include "tcuVectorUtil.hpp"
     30 
     31 #include <map>
     32 
     33 namespace glcts
     34 {
     35 using namespace glw;
     36 namespace
     37 {
     38 
     39 class DILogger
     40 {
     41 public:
     42 	DILogger() : null_log_(0)
     43 	{
     44 	}
     45 
     46 	DILogger(const DILogger& rhs)
     47 	{
     48 		null_log_ = rhs.null_log_;
     49 		if (!null_log_)
     50 		{
     51 			str_ << rhs.str_.str();
     52 		}
     53 	}
     54 
     55 	~DILogger()
     56 	{
     57 		s_tcuLog->writeMessage(str_.str().c_str());
     58 		if (!str_.str().empty())
     59 		{
     60 			s_tcuLog->writeMessage(NL);
     61 		}
     62 	}
     63 
     64 	template <class T>
     65 	DILogger& operator<<(const T& t)
     66 	{
     67 		if (!null_log_)
     68 		{
     69 			str_ << t;
     70 		}
     71 		return *this;
     72 	}
     73 
     74 	DILogger& nullify()
     75 	{
     76 		null_log_ = true;
     77 		return *this;
     78 	}
     79 
     80 	static void setOutput(tcu::TestLog& log)
     81 	{
     82 		s_tcuLog = &log;
     83 	}
     84 
     85 private:
     86 	void				 operator=(const DILogger&);
     87 	bool				 null_log_;
     88 	std::ostringstream   str_;
     89 	static tcu::TestLog* s_tcuLog;
     90 };
     91 tcu::TestLog* DILogger::s_tcuLog = NULL;
     92 
     93 class DIResult
     94 {
     95 public:
     96 	DIResult() : status_(NO_ERROR)
     97 	{
     98 	}
     99 
    100 	DILogger error()
    101 	{
    102 		return sub_result(ERROR);
    103 	}
    104 	long code() const
    105 	{
    106 		return status_;
    107 	}
    108 	DILogger sub_result(long _code)
    109 	{
    110 		if (_code == NO_ERROR)
    111 		{
    112 			return sub_result_inner(_code).nullify();
    113 		}
    114 		else
    115 		{
    116 			return sub_result_inner(_code);
    117 		}
    118 	}
    119 
    120 private:
    121 	DILogger sub_result_inner(long _code)
    122 	{
    123 		status_ |= _code;
    124 		return DILogger();
    125 	}
    126 	DILogger logger_;
    127 	long	 status_;
    128 };
    129 
    130 namespace test_api
    131 {
    132 struct ES3
    133 {
    134 	static bool isES()
    135 	{
    136 		return true;
    137 	}
    138 	static std::string glslVer(bool = false)
    139 	{
    140 		return "#version 310 es";
    141 	}
    142 	static void ES_Only()
    143 	{
    144 	}
    145 };
    146 
    147 struct GL
    148 {
    149 	static bool isES()
    150 	{
    151 		return false;
    152 	}
    153 	static std::string glslVer(bool compute = false)
    154 	{
    155 		if (compute)
    156 		{
    157 			return "#version 430";
    158 		}
    159 		else
    160 		{
    161 			return "#version 400";
    162 		}
    163 	}
    164 	static void GL_Only()
    165 	{
    166 	}
    167 };
    168 }
    169 
    170 namespace shaders
    171 {
    172 
    173 template <typename api>
    174 std::string vshSimple()
    175 {
    176 	return api::glslVer() + NL "in vec4 i_vertex;" NL "void main()" NL "{" NL "    gl_Position = i_vertex;" NL "}";
    177 }
    178 template <typename api>
    179 std::string vshSimple_point()
    180 {
    181 	return api::glslVer() + NL "in vec4 i_vertex;" NL "void main()" NL "{" NL "    gl_Position = i_vertex;" NL
    182 							   "#if defined(GL_ES)" NL "    gl_PointSize = 1.0;" NL "#endif" NL "}";
    183 }
    184 
    185 template <typename api>
    186 std::string fshSimple()
    187 {
    188 	return api::glslVer() + NL "precision highp float; " NL "out vec4 outColor;" NL "void main() {" NL
    189 							   "  outColor = vec4(0.1,0.2,0.3,1.0);" NL "}";
    190 }
    191 }
    192 
    193 class DrawIndirectBase : public glcts::SubcaseBase
    194 {
    195 protected:
    196 	typedef std::vector<unsigned int> CDataArray;
    197 	typedef std::vector<tcu::Vec3>	CVertexArray;
    198 	typedef std::vector<tcu::Vec4>	CColorArray;
    199 	typedef std::vector<GLuint>		  CElementArray;
    200 
    201 	enum TDrawFunction
    202 	{
    203 		DRAW_ARRAYS,
    204 		DRAW_ELEMENTS,
    205 	};
    206 
    207 	typedef struct
    208 	{
    209 		GLuint count;
    210 		GLuint primCount;
    211 		GLuint first;
    212 		GLuint reservedMustBeZero;
    213 	} DrawArraysIndirectCommand;
    214 
    215 	typedef struct
    216 	{
    217 		GLuint count;
    218 		GLuint primCount;
    219 		GLuint firstIndex;
    220 		GLint  baseVertex;
    221 		GLuint reservedMustBeZero;
    222 	} DrawElementsIndirectCommand;
    223 
    224 	int getWindowWidth()
    225 	{
    226 		return m_context.getRenderContext().getRenderTarget().getWidth();
    227 	}
    228 
    229 	int getWindowHeight()
    230 	{
    231 		return m_context.getRenderContext().getRenderTarget().getHeight();
    232 	}
    233 
    234 	void getDataSize(int& width, int& height)
    235 	{
    236 		width  = std::min(getWindowWidth(), 16384);				 // Cap width to 16384
    237 		height = std::min(getWindowHeight(), 4 * 16384 / width); // Height is 4 if width is capped
    238 	}
    239 
    240 	GLuint CreateComputeProgram(const std::string& cs, bool linkAndCheck)
    241 	{
    242 		const GLuint p = glCreateProgram();
    243 
    244 		const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
    245 		glAttachShader(p, sh);
    246 		glDeleteShader(sh);
    247 		const char* const src[1] = { cs.c_str() };
    248 		glShaderSource(sh, 1, src, NULL);
    249 		glCompileShader(sh);
    250 
    251 		if (linkAndCheck)
    252 		{
    253 			glLinkProgram(p);
    254 			if (!CheckProgram(p))
    255 			{
    256 				return 0;
    257 			}
    258 		}
    259 
    260 		return p;
    261 	}
    262 
    263 	GLuint CreateProgram(const std::string& vs, const std::string& gs, const std::string& fs, bool linkAndCheck)
    264 	{
    265 		const GLuint p = glCreateProgram();
    266 
    267 		if (!vs.empty())
    268 		{
    269 			const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
    270 			glAttachShader(p, sh);
    271 			glDeleteShader(sh);
    272 			const char* const src[1] = { vs.c_str() };
    273 			glShaderSource(sh, 1, src, NULL);
    274 			glCompileShader(sh);
    275 		}
    276 		if (!gs.empty())
    277 		{
    278 			const GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
    279 			glAttachShader(p, sh);
    280 			glDeleteShader(sh);
    281 			const char* const src[1] = { gs.c_str() };
    282 			glShaderSource(sh, 1, src, NULL);
    283 			glCompileShader(sh);
    284 		}
    285 		if (!fs.empty())
    286 		{
    287 			const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
    288 			glAttachShader(p, sh);
    289 			glDeleteShader(sh);
    290 			const char* const src[1] = { fs.c_str() };
    291 			glShaderSource(sh, 1, src, NULL);
    292 			glCompileShader(sh);
    293 		}
    294 
    295 		if (linkAndCheck)
    296 		{
    297 			glLinkProgram(p);
    298 			if (!CheckProgram(p))
    299 			{
    300 				return 0;
    301 			}
    302 		}
    303 
    304 		return p;
    305 	}
    306 
    307 	long CheckProgram(GLuint program)
    308 	{
    309 		DIResult status;
    310 		GLint	progStatus;
    311 		glGetProgramiv(program, GL_LINK_STATUS, &progStatus);
    312 
    313 		if (progStatus == GL_FALSE)
    314 		{
    315 
    316 			status.error() << "GL_LINK_STATUS is false";
    317 
    318 			GLint attached_shaders;
    319 			glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
    320 
    321 			if (attached_shaders > 0)
    322 			{
    323 				std::vector<GLuint> shaders(attached_shaders);
    324 				glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
    325 
    326 				for (GLint i = 0; i < attached_shaders; ++i)
    327 				{
    328 					// shader type
    329 					GLenum type;
    330 					glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
    331 					switch (type)
    332 					{
    333 					case GL_VERTEX_SHADER:
    334 						status.error() << "*** Vertex Shader ***\n";
    335 						break;
    336 					case GL_FRAGMENT_SHADER:
    337 						status.error() << "*** Fragment Shader ***\n";
    338 						break;
    339 					case GL_COMPUTE_SHADER:
    340 						status.error() << "*** Compute Shader ***\n";
    341 						break;
    342 					default:
    343 						status.error() << "*** Unknown Shader ***\n";
    344 						break;
    345 					}
    346 
    347 					// shader source
    348 					GLint length;
    349 					glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
    350 					if (length > 0)
    351 					{
    352 						std::vector<GLchar> source(length);
    353 						glGetShaderSource(shaders[i], length, NULL, &source[0]);
    354 						status.error() << source[0];
    355 					}
    356 
    357 					// shader info log
    358 					glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
    359 					if (length > 0)
    360 					{
    361 						std::vector<GLchar> log(length);
    362 						glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
    363 						status.error() << &log[0];
    364 					}
    365 				}
    366 			}
    367 
    368 			// program info log
    369 			GLint length;
    370 			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
    371 			if (length > 0)
    372 			{
    373 				std::vector<GLchar> log(length);
    374 				glGetProgramInfoLog(program, length, NULL, &log[0]);
    375 				status.error() << &log[0];
    376 			}
    377 		}
    378 
    379 		return status.code() == NO_ERROR;
    380 	}
    381 
    382 	template <typename api>
    383 	void ReadPixelsFloat(int x, int y, int width, int height, void* data);
    384 
    385 	template <typename api>
    386 	void GetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data);
    387 
    388 	template <typename T>
    389 	void DataGen(std::vector<T>& data, unsigned int sizeX, unsigned int sizeY, T valueMin, T valueMax)
    390 	{
    391 		data.resize(sizeX * sizeY, 0);
    392 		T range = valueMax - valueMin;
    393 		T stepX = range / sizeX;
    394 		T stepY = range / sizeY;
    395 
    396 		for (unsigned int i = 0; i < sizeY; ++i)
    397 		{
    398 			T valueY = i * stepY;
    399 
    400 			for (unsigned int j = 0; j < sizeX; ++j)
    401 			{
    402 				data[j + i * sizeX] = valueMin + j * stepX + valueY;
    403 			}
    404 		}
    405 	}
    406 
    407 	template <typename T>
    408 	long DataCompare(const std::vector<T>& dataRef, unsigned int widthRef, unsigned int heightRef,
    409 					 const std::vector<T>& dataTest, unsigned int widthTest, unsigned int heightTest,
    410 					 unsigned offsetYRef = 0, unsigned offsetYTest = 0)
    411 	{
    412 		if (widthRef * heightRef > dataRef.size())
    413 			throw std::runtime_error("Invalid reference buffer resolution!");
    414 
    415 		if (widthTest * heightTest > dataTest.size())
    416 			throw std::runtime_error("Invalid test buffer resolution!");
    417 
    418 		unsigned int width  = std::min(widthRef, widthTest);
    419 		unsigned int height = std::min(heightRef, heightTest);
    420 
    421 		for (unsigned int i = 0; i < height; ++i)
    422 		{
    423 			unsigned int offsetRef  = (i + offsetYRef) * widthRef;
    424 			unsigned int offsetTest = (i + offsetYTest) * widthTest;
    425 
    426 			for (size_t j = 0; j < width; ++j)
    427 			{
    428 				if (dataRef[offsetRef + j] != dataTest[offsetTest + j])
    429 				{
    430 					DIResult status;
    431 					status.error() << "Compare failed: different values [x: " << j << ", y: " << i + offsetYTest
    432 								   << ", reference: " << dataRef[offsetRef + j]
    433 								   << ", test: " << dataTest[offsetTest + j] << "]";
    434 					return status.code();
    435 				}
    436 			}
    437 		}
    438 
    439 		return NO_ERROR;
    440 	}
    441 
    442 	template <typename api>
    443 	long BindingPointCheck(GLuint expectedValue)
    444 	{
    445 		DIResult status;
    446 
    447 		GLint valueInt = -9999;
    448 		glGetIntegerv(GL_DRAW_INDIRECT_BUFFER_BINDING, &valueInt);
    449 		if (valueInt != static_cast<GLint>(expectedValue))
    450 		{
    451 			status.error() << "glGetIntegerv(GL_DRAW_INDIRECT_BUFFER_BINDING) returned invalid value: " << valueInt
    452 						   << ", expected: " << expectedValue;
    453 		}
    454 
    455 		GLboolean valueBool = expectedValue ? GL_FALSE : GL_TRUE;
    456 		glGetBooleanv(GL_DRAW_INDIRECT_BUFFER_BINDING, &valueBool);
    457 		if (valueBool != (expectedValue ? GL_TRUE : GL_FALSE))
    458 		{
    459 			status.error() << "glGetBooleanv(GL_DRAW_INDIRECT_BUFFER_BINDING) returned invalid value: "
    460 						   << BoolToString(valueBool)
    461 						   << ", expected: " << BoolToString(expectedValue ? GL_TRUE : GL_FALSE);
    462 		}
    463 
    464 		GLfloat valueFloat		   = -9999;
    465 		GLfloat expectedFloatValue = static_cast<GLfloat>(expectedValue);
    466 		glGetFloatv(GL_DRAW_INDIRECT_BUFFER_BINDING, &valueFloat);
    467 		if (valueFloat != expectedFloatValue)
    468 		{
    469 			status.error() << "glGetFloatv(GL_DRAW_INDIRECT_BUFFER_BINDING) returned invalid value: " << valueFloat
    470 						   << ", expected: " << expectedValue;
    471 		}
    472 
    473 		if (!api::isES())
    474 		{
    475 			GLdouble valueDouble = -9999;
    476 			glGetDoublev(GL_DRAW_INDIRECT_BUFFER_BINDING, &valueDouble);
    477 			if (valueDouble != static_cast<GLdouble>(expectedValue))
    478 			{
    479 				status.error() << "glGetDoublev(GL_DRAW_INDIRECT_BUFFER_BINDING) returned invalid value: "
    480 							   << valueDouble << ", expected: " << expectedValue;
    481 			}
    482 		}
    483 
    484 		return status.code();
    485 	}
    486 
    487 	template <typename T>
    488 	long BuffersCompare(const std::vector<T>& bufferTest, unsigned int widthTest, unsigned int heightTest,
    489 						const std::vector<T>& bufferRef, unsigned int widthRef, unsigned int heightRef)
    490 	{
    491 
    492 		const tcu::PixelFormat& pixelFormat = m_context.getRenderContext().getRenderTarget().getPixelFormat();
    493 		tcu::Vec4				epsilon		= tcu::Vec4(
    494 			1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
    495 			1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
    496 
    497 		double stepX = widthRef / static_cast<double>(widthTest);
    498 		double stepY = heightRef / static_cast<double>(heightTest);
    499 		for (unsigned int i = 0; i < heightTest; ++i)
    500 		{
    501 			unsigned int offsetTest = i * widthTest;
    502 			unsigned int offsetRef  = static_cast<int>(i * stepY + 0.5) * widthRef;
    503 			for (unsigned int j = 0; j < widthTest; ++j)
    504 			{
    505 				unsigned int posXRef = static_cast<int>(j * stepX + 0.5);
    506 				if (!ColorVerify(bufferTest[j + offsetTest], bufferRef[posXRef + offsetRef], epsilon))
    507 				{
    508 					DIResult status;
    509 					status.error() << "(x,y)= (" << j << "," << i << "). Color RGBA(" << bufferTest[j + offsetTest][0]
    510 								   << "," << bufferTest[j + offsetTest][1] << "," << bufferTest[j + offsetTest][2]
    511 								   << "," << bufferTest[j + offsetTest][3] << ") is different than expected RGBA("
    512 								   << bufferRef[posXRef + offsetRef][0] << "," << bufferRef[posXRef + offsetRef][1]
    513 								   << "," << bufferRef[posXRef + offsetRef][2] << ","
    514 								   << bufferRef[posXRef + offsetRef][3] << ")";
    515 					return status.code();
    516 				}
    517 			}
    518 		}
    519 		return NO_ERROR;
    520 	}
    521 
    522 	template <typename T>
    523 	bool ColorVerify(T color, T colorExpected, tcu::Vec4 epsilon)
    524 	{
    525 		for (int i = 0; i < 3; ++i)
    526 		{
    527 			if (fabsf(colorExpected[i] - color[i]) > epsilon[i])
    528 				return false;
    529 		}
    530 		return true;
    531 	}
    532 
    533 	long BufferCheck(const CDataArray& dataRef, unsigned int widthRef, unsigned int heightRef, const void* bufTest,
    534 					 unsigned int widthTest, unsigned int heightTest, unsigned int offsetYRef = 0,
    535 					 unsigned int offsetYTest = 0)
    536 	{
    537 		if (bufTest == 0)
    538 		{
    539 			throw std::runtime_error("Invalid test buffer!");
    540 		}
    541 
    542 		CDataArray dataTest(widthTest * heightTest, 0);
    543 		memcpy(&dataTest[0], bufTest, widthTest * heightTest * sizeof(unsigned int));
    544 
    545 		return DataCompare(dataRef, widthRef, heightRef, dataTest, widthTest, heightTest, offsetYRef, offsetYTest);
    546 	}
    547 
    548 	template <typename api>
    549 	long StateValidate(GLboolean mapped, GLbitfield access, GLbitfield accessFlag, GLintptr offset, GLsizeiptr length)
    550 	{
    551 		DIResult result;
    552 
    553 		if (!api::isES())
    554 		{
    555 			int v;
    556 			glGetBufferParameteriv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_ACCESS, &v);
    557 			if (v != static_cast<int>(access))
    558 			{
    559 				result.error() << "glGetBufferParameteriv(GL_BUFFER_ACCESS) returned incorrect state: "
    560 							   << AccessToString(v) << ", expected: " << AccessToString(access);
    561 			}
    562 		}
    563 
    564 		int v;
    565 		glGetBufferParameteriv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_ACCESS_FLAGS, &v);
    566 		if (v != static_cast<int>(accessFlag))
    567 		{
    568 			result.error() << "glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS) returned incorrect state: " << v
    569 						   << ", expected: " << accessFlag;
    570 		}
    571 
    572 		glGetBufferParameteriv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAPPED, &v);
    573 		if (v != mapped)
    574 		{
    575 			result.error() << "glGetBufferParameteriv(GL_BUFFER_MAPPED) returned incorrect state: "
    576 						   << BoolToString((GLboolean)v) << ", expected: " << BoolToString((GLboolean)access);
    577 		}
    578 
    579 		glGetBufferParameteriv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_OFFSET, &v);
    580 		if (v != offset)
    581 		{
    582 			result.error() << "glGetBufferParameteriv(GL_BUFFER_MAP_OFFSET) returned incorrect offset: " << v
    583 						   << ", expected: " << offset;
    584 		}
    585 
    586 		glGetBufferParameteriv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_LENGTH, &v);
    587 		if (v != length)
    588 		{
    589 			result.error() << "glGetBufferParameteriv(GL_BUFFER_MAP_LENGTH) returned incorrect length: " << v
    590 						   << ", expected: " << length;
    591 		}
    592 
    593 		return result.code();
    594 	}
    595 
    596 	void PointsGen(unsigned int drawSizeX, unsigned int drawSizeY, CColorArray& output)
    597 	{
    598 		output.reserve(drawSizeY * 2);
    599 		float rasterSizeX = 2.0f / static_cast<float>(getWindowWidth());
    600 		float rasterSizeY = 2.0f / static_cast<float>(getWindowHeight());
    601 		for (unsigned int i = 0; i < drawSizeY; ++i)
    602 		{
    603 			float offsetY = -1.0f + rasterSizeY * static_cast<float>(i) + rasterSizeY / 2;
    604 			for (unsigned int j = 0; j < drawSizeX; ++j)
    605 			{
    606 				float offsetX = -1.0f + rasterSizeX * static_cast<float>(j) + rasterSizeX / 2;
    607 				output.push_back(tcu::Vec4(offsetX, offsetY, 0.0f, 1.0f));
    608 			}
    609 		}
    610 	}
    611 
    612 	float LinesOffsetY(unsigned int i, float rasterSize)
    613 	{
    614 		// Offset lines slightly from the center of pixels so as not to hit rasterizer
    615 		// tie-break conditions (the right-edge of the screen at half-integer pixel
    616 		// heights is the right corner of a diamond). rasterSize/16 is the smallest
    617 		// offset that the spec guarantees the rasterizer can resolve.
    618 		return -1.0f + rasterSize * static_cast<float>(i) + rasterSize / 2 + rasterSize / 16;
    619 	}
    620 
    621 	void LinesGen(unsigned int, unsigned int drawSizeY, CColorArray& output)
    622 	{
    623 		output.reserve(drawSizeY * 2);
    624 		float rasterSize = 2.0f / static_cast<float>(getWindowHeight());
    625 		for (unsigned int i = 0; i < drawSizeY; ++i)
    626 		{
    627 			float offsetY = LinesOffsetY(i, rasterSize);
    628 			output.push_back(tcu::Vec4(-1.0f, offsetY, 0.0f, 1.0f));
    629 			output.push_back(tcu::Vec4(1.0f, offsetY, 0.0f, 1.0f));
    630 		}
    631 	}
    632 
    633 	void LinesAdjacencyGen(unsigned int, unsigned int drawSizeY, CColorArray& output)
    634 	{
    635 		float rasterSize = 2.0f / static_cast<float>(getWindowHeight());
    636 		for (unsigned int i = 0; i < drawSizeY; ++i)
    637 		{
    638 			float offsetY = LinesOffsetY(i, rasterSize);
    639 			output.push_back(tcu::Vec4(-1.5f, -1.0f + offsetY, 0.0f, 1.0f)); //adj
    640 			output.push_back(tcu::Vec4(-1.0f, offsetY, 0.0f, 1.0f));
    641 			output.push_back(tcu::Vec4(1.0f, offsetY, 0.0f, 1.0f));
    642 			output.push_back(tcu::Vec4(1.5f, -1.0f + offsetY, 0.0f, 1.0f)); //adj
    643 		}
    644 	}
    645 
    646 	void LineStripAdjacencyGen(unsigned int, unsigned int drawSizeY, CColorArray& output)
    647 	{
    648 		float rasterSize = 2.0f / static_cast<float>(getWindowHeight());
    649 		output.push_back(tcu::Vec4(-1.5f, rasterSize / 2, 0.0f, 1.0f));
    650 		for (unsigned int i = 0; i < drawSizeY; ++i)
    651 		{
    652 			float offsetY = LinesOffsetY(i, rasterSize);
    653 			output.push_back(tcu::Vec4(-1.0f, offsetY, 0.0f, 1.0f));
    654 			output.push_back(tcu::Vec4(-1.0f, offsetY, 0.0f, 1.0f));
    655 			output.push_back(tcu::Vec4(1.0f, offsetY, 0.0f, 1.0f));
    656 			output.push_back(tcu::Vec4(1.0f, offsetY, 0.0f, 1.0f));
    657 		}
    658 		output.push_back(tcu::Vec4(1.5f, 1.0f - rasterSize / 2, 0.0f, 1.0f));
    659 	}
    660 
    661 	void TrianglesGen(unsigned int drawSizeX, unsigned int drawSizeY, CColorArray& output)
    662 	{
    663 		output.reserve(drawSizeX * 2 * 6);
    664 
    665 		switch (drawSizeX)
    666 		{
    667 		case 1:
    668 		{
    669 			output.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
    670 			output.push_back(tcu::Vec4(4.0f, -1.0f, 0.0f, 1.0f));
    671 			output.push_back(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f));
    672 		}
    673 		break;
    674 		case 0:
    675 		{
    676 			throw std::runtime_error("Invalid drawSizeX!");
    677 		}
    678 		break;
    679 		default:
    680 		{
    681 			float drawStepX = 2.0f / static_cast<float>(drawSizeX);
    682 			float drawStepY = 2.0f / static_cast<float>(drawSizeY);
    683 
    684 			for (unsigned int i = 0; i < drawSizeY; ++i)
    685 			{
    686 				float offsetY = -1.0f + drawStepY * static_cast<float>(i);
    687 				for (unsigned int j = 0; j < drawSizeX; ++j)
    688 				{
    689 					float offsetX = -1.0f + drawStepX * static_cast<float>(j);
    690 
    691 					output.push_back(tcu::Vec4(offsetX, offsetY, 0.0f, 1.0f));
    692 					output.push_back(tcu::Vec4(offsetX + drawStepX, offsetY, 0.0f, 1.0f));
    693 					output.push_back(tcu::Vec4(offsetX, offsetY + drawStepY, 0.0f, 1.0f));
    694 
    695 					output.push_back(tcu::Vec4(offsetX + drawStepX, offsetY, 0.0f, 1.0f));
    696 					output.push_back(tcu::Vec4(offsetX + drawStepX, offsetY + drawStepY, 0.0f, 1.0f));
    697 					output.push_back(tcu::Vec4(offsetX, offsetY + drawStepY, 0.0f, 1.0f));
    698 				}
    699 			}
    700 		}
    701 		break;
    702 		}
    703 	}
    704 
    705 	void TrianglesAdjacencyGen(unsigned int drawSizeX, unsigned int drawSizeY, CColorArray& output)
    706 	{
    707 		float sizeX = 1.0f / static_cast<float>(drawSizeX);
    708 		float sizeY = 1.0f / static_cast<float>(drawSizeY);
    709 
    710 		for (unsigned int i = 0; i < drawSizeX; ++i)
    711 		{
    712 			float offsetY = -0.5f + sizeY * static_cast<float>(i);
    713 			for (unsigned int j = 0; j < drawSizeY; ++j)
    714 			{
    715 				float offsetX = -0.5f + sizeX * static_cast<float>(j);
    716 
    717 				output.push_back(tcu::Vec4(offsetX, offsetY, 0.0f, 1.0f));
    718 				output.push_back(tcu::Vec4(offsetX - sizeX, offsetY + sizeY, 0.0f, 1.0f));
    719 				output.push_back(tcu::Vec4(offsetX, offsetY + sizeY, 0.0f, 1.0f));
    720 				output.push_back(tcu::Vec4(offsetX + sizeX, offsetY + sizeY, 0.0f, 1.0f));
    721 				output.push_back(tcu::Vec4(offsetX + sizeX, offsetY, 0.0f, 1.0f));
    722 				output.push_back(tcu::Vec4(offsetX + sizeX, offsetY - sizeY, 0.0f, 1.0f));
    723 
    724 				output.push_back(tcu::Vec4(offsetX + sizeX, offsetY + sizeY, 0.0f, 1.0f));
    725 				output.push_back(tcu::Vec4(offsetX + 2 * sizeX, offsetY, 0.0f, 1.0f));
    726 				output.push_back(tcu::Vec4(offsetX + sizeX, offsetY, 0.0f, 1.0f));
    727 				output.push_back(tcu::Vec4(offsetX, offsetY, 0.0f, 1.0f));
    728 				output.push_back(tcu::Vec4(offsetX, offsetY + sizeY, 0.0f, 1.0f));
    729 				output.push_back(tcu::Vec4(offsetX, offsetY + 2 * sizeY, 0.0f, 1.0f));
    730 			}
    731 		}
    732 	}
    733 
    734 	void TriangleStripAdjacencyGen(unsigned int drawSizeX, unsigned int drawSizeY, CColorArray& output)
    735 	{
    736 		float sizeX = 1.0f / static_cast<float>(drawSizeX);
    737 		float sizeY = 1.0f / static_cast<float>(drawSizeY);
    738 
    739 		for (unsigned int i = 0; i < drawSizeX; ++i)
    740 		{
    741 			float offsetY = -0.5f + sizeY * static_cast<float>(i);
    742 			for (unsigned int j = 0; j < drawSizeY; ++j)
    743 			{
    744 				float offsetX = -0.5f + sizeX * static_cast<float>(j);
    745 
    746 				output.push_back(tcu::Vec4(offsetX, offsetY, 0.0f, 1.0f));
    747 				output.push_back(tcu::Vec4(offsetX - sizeX, offsetY + sizeY, 0.0f, 1.0f));
    748 				output.push_back(tcu::Vec4(offsetX, offsetY + sizeY, 0.0f, 1.0f));
    749 				output.push_back(tcu::Vec4(offsetX + sizeX, offsetY - sizeY, 0.0f, 1.0f));
    750 				output.push_back(tcu::Vec4(offsetX + sizeX, offsetY, 0.0f, 1.0f));
    751 				output.push_back(tcu::Vec4(offsetX, offsetY + 2 * sizeY, 0.0f, 1.0f));
    752 				output.push_back(tcu::Vec4(offsetX + sizeX, offsetY + sizeY, 0.0f, 1.0f));
    753 				output.push_back(tcu::Vec4(offsetX + 2 * sizeX, offsetY - sizeY, 0.0f, 1.0f));
    754 			}
    755 		}
    756 	}
    757 
    758 	void PrimitiveGen(GLenum primitiveType, unsigned int drawSizeX, unsigned int drawSizeY, CColorArray& output)
    759 	{
    760 		switch (primitiveType)
    761 		{
    762 		case GL_POINTS:
    763 			PointsGen(drawSizeX, drawSizeY, output);
    764 			break;
    765 		case GL_LINES:
    766 		case GL_LINE_STRIP:
    767 		case GL_LINE_LOOP:
    768 			LinesGen(drawSizeX, drawSizeY, output);
    769 			break;
    770 		case GL_LINES_ADJACENCY:
    771 			LinesAdjacencyGen(drawSizeX, drawSizeY, output);
    772 			break;
    773 		case GL_LINE_STRIP_ADJACENCY:
    774 			LineStripAdjacencyGen(drawSizeX, drawSizeY, output);
    775 			break;
    776 		case GL_TRIANGLES:
    777 		case GL_TRIANGLE_STRIP:
    778 		case GL_TRIANGLE_FAN:
    779 			TrianglesGen(drawSizeX, drawSizeY, output);
    780 			break;
    781 		case GL_TRIANGLES_ADJACENCY:
    782 			TrianglesAdjacencyGen(drawSizeX, drawSizeY, output);
    783 			break;
    784 		case GL_TRIANGLE_STRIP_ADJACENCY:
    785 			TriangleStripAdjacencyGen(drawSizeX, drawSizeY, output);
    786 			break;
    787 		default:
    788 			throw std::runtime_error("Unknown primitive type!");
    789 			break;
    790 		}
    791 	}
    792 
    793 	std::string BoolToString(GLboolean value)
    794 	{
    795 		if (value == GL_TRUE)
    796 			return "GL_TRUE";
    797 
    798 		return "GL_FALSE";
    799 	}
    800 
    801 	std::string AccessToString(GLbitfield access)
    802 	{
    803 		switch (access)
    804 		{
    805 		case GL_READ_WRITE:
    806 			return "GL_READ_WRITE";
    807 			break;
    808 		case GL_READ_ONLY:
    809 			return "GL_READ_ONLY";
    810 			break;
    811 		case GL_WRITE_ONLY:
    812 			return "GL_WRITE_ONLY";
    813 			break;
    814 		default:
    815 			throw std::runtime_error("Invalid access type!");
    816 			break;
    817 		}
    818 	}
    819 };
    820 
    821 template <>
    822 void DrawIndirectBase::ReadPixelsFloat<test_api::GL>(int x, int y, int width, int height, void* data)
    823 {
    824 	glReadPixels(x, y, width, height, GL_RGBA, GL_FLOAT, data);
    825 }
    826 
    827 template <>
    828 void DrawIndirectBase::ReadPixelsFloat<test_api::ES3>(int x, int y, int width, int height, void* data)
    829 {
    830 	GLfloat*			 fData = reinterpret_cast<GLfloat*>(data);
    831 	std::vector<GLubyte> uData(width * height * 4);
    832 	glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &uData[0]);
    833 	for (size_t i = 0; i < uData.size(); i++)
    834 	{
    835 		fData[i] = float(uData[i]) / 255.0f;
    836 	}
    837 }
    838 
    839 template <>
    840 void DrawIndirectBase::GetBufferSubData<test_api::GL>(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data)
    841 {
    842 	glGetBufferSubData(target, offset, size, data);
    843 }
    844 
    845 template <>
    846 void DrawIndirectBase::GetBufferSubData<test_api::ES3>(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data)
    847 {
    848 	void* ptr = glMapBufferRange(target, offset, size, GL_MAP_READ_BIT);
    849 	memcpy(data, ptr, size);
    850 	glUnmapBuffer(target);
    851 }
    852 
    853 template <typename api>
    854 struct CDefaultBindingPoint : public DrawIndirectBase
    855 {
    856 	virtual std::string Title()
    857 	{
    858 		return "Draw Indirect: Check default binding point";
    859 	}
    860 
    861 	virtual std::string Purpose()
    862 	{
    863 		return "Verify that default binding point is set to zero";
    864 	}
    865 
    866 	virtual std::string Method()
    867 	{
    868 		return "Use glGetIntegerv, glGetBooleanv, glGetFloatv, glGetDoublev to get default binding point";
    869 	}
    870 
    871 	virtual std::string PassCriteria()
    872 	{
    873 		return "The test will pass if default binding point is zero";
    874 	}
    875 
    876 	virtual long Run()
    877 	{
    878 		return BindingPointCheck<api>(0);
    879 	}
    880 };
    881 
    882 template <typename api>
    883 struct CZeroBindingPoint : public DrawIndirectBase
    884 {
    885 	virtual std::string Title()
    886 	{
    887 		return "Draw Indirect: Zero binding point";
    888 	}
    889 
    890 	virtual std::string Purpose()
    891 	{
    892 		return "Verify that binding point is set to zero";
    893 	}
    894 
    895 	virtual std::string Method()
    896 	{
    897 		return "Bind zero and check that binding point is set to zero";
    898 	}
    899 
    900 	virtual std::string PassCriteria()
    901 	{
    902 		return "The test will pass if binding point is set to zero";
    903 	}
    904 
    905 	virtual long Run()
    906 	{
    907 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
    908 
    909 		return BindingPointCheck<api>(0);
    910 	}
    911 };
    912 
    913 template <typename api>
    914 struct CSingleBindingPoint : public DrawIndirectBase
    915 {
    916 	virtual std::string Title()
    917 	{
    918 		return "Draw Indirect: Single binding point";
    919 	}
    920 
    921 	virtual std::string Purpose()
    922 	{
    923 		return "Verify that binding point is set to correct value";
    924 	}
    925 
    926 	virtual std::string Method()
    927 	{
    928 		return "Bind non-zero buffer and check that binding point is set to correct value";
    929 	}
    930 
    931 	virtual std::string PassCriteria()
    932 	{
    933 		return "The test will pass if binding point is set to correct value";
    934 	}
    935 
    936 	virtual long Run()
    937 	{
    938 		glGenBuffers(1, &_buffer);
    939 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer);
    940 
    941 		long ret = BindingPointCheck<api>(_buffer);
    942 
    943 		return ret;
    944 	}
    945 
    946 	virtual long Cleanup()
    947 	{
    948 		glDeleteBuffers(1, &_buffer);
    949 		return BindingPointCheck<api>(0);
    950 	}
    951 
    952 private:
    953 	GLuint _buffer;
    954 };
    955 
    956 template <typename api>
    957 class CMultiBindingPoint : public DrawIndirectBase
    958 {
    959 public:
    960 	virtual std::string Title()
    961 	{
    962 		return "Draw Indirect: Multi binding point";
    963 	}
    964 
    965 	virtual std::string Purpose()
    966 	{
    967 		return "Verify that binding points are set to correct value";
    968 	}
    969 
    970 	virtual std::string Method()
    971 	{
    972 		return "Bind in loop non-zero buffers and check that binding points are set to correct value";
    973 	}
    974 
    975 	virtual std::string PassCriteria()
    976 	{
    977 		return "The test will pass if binding points are set to correct value";
    978 	}
    979 
    980 	virtual long Run()
    981 	{
    982 		DIResult result;
    983 
    984 		const int buffNum = sizeof(_buffers) / sizeof(_buffers[0]);
    985 
    986 		glGenBuffers(buffNum, _buffers);
    987 
    988 		for (int i = 0; i < buffNum; ++i)
    989 		{
    990 			glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[i]);
    991 			result.sub_result(BindingPointCheck<api>(_buffers[i]));
    992 		}
    993 
    994 		return result.code();
    995 	}
    996 
    997 	virtual long Cleanup()
    998 	{
    999 		glDeleteBuffers(sizeof(_buffers) / sizeof(_buffers[0]), _buffers);
   1000 		return BindingPointCheck<api>(0);
   1001 	}
   1002 
   1003 private:
   1004 	GLuint _buffers[10];
   1005 };
   1006 
   1007 template <typename api>
   1008 struct CDeleteBindingPoint : public DrawIndirectBase
   1009 {
   1010 	virtual std::string Title()
   1011 	{
   1012 		return "Draw Indirect: Delete binding point";
   1013 	}
   1014 
   1015 	virtual std::string Purpose()
   1016 	{
   1017 		return "Verify that after deleting buffer, binding point is set to correct value";
   1018 	}
   1019 
   1020 	virtual std::string Method()
   1021 	{
   1022 		return "Bind non-zero buffer, delete buffer, check that binding point is set to 0";
   1023 	}
   1024 
   1025 	virtual std::string PassCriteria()
   1026 	{
   1027 		return "The test will pass if binding point is set to correct value";
   1028 	}
   1029 
   1030 	virtual long Run()
   1031 	{
   1032 		glGenBuffers(1, &_buffer);
   1033 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer);
   1034 		glDeleteBuffers(1, &_buffer);
   1035 		return BindingPointCheck<api>(0);
   1036 	}
   1037 
   1038 private:
   1039 	GLuint _buffer;
   1040 };
   1041 
   1042 template <typename api>
   1043 struct CBufferData : public DrawIndirectBase
   1044 {
   1045 	virtual std::string Title()
   1046 	{
   1047 		return "Check functions: glBufferData and GetBufferSubData<api>";
   1048 	}
   1049 
   1050 	virtual std::string Purpose()
   1051 	{
   1052 		return "Verify that glBufferData and GetBufferSubData<api> accepts GL_DRAW_INDIRECT_BUFFER enum";
   1053 	}
   1054 
   1055 	virtual std::string Method()
   1056 	{
   1057 		return "1. Create buffer" NL "2. Bind buffer" NL "3. Set data using glBufferData" NL
   1058 			   "4. Get data using GetBufferSubData<api>" NL "5. Verify results";
   1059 	}
   1060 
   1061 	virtual std::string PassCriteria()
   1062 	{
   1063 		return "The test will pass if no OpenGL errors reported";
   1064 	}
   1065 
   1066 	virtual long Run()
   1067 	{
   1068 		DIResult result;
   1069 
   1070 		int dataWidth, dataHeight;
   1071 		getDataSize(dataWidth, dataHeight);
   1072 
   1073 		CDataArray dataTest(dataWidth * dataHeight, 0);
   1074 
   1075 		glGenBuffers(sizeof(_buffers) / sizeof(_buffers[0]), _buffers);
   1076 		CDataArray dataRef1;
   1077 		DataGen<unsigned int>(dataRef1, dataWidth, dataHeight, 0, 50);
   1078 
   1079 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[1]);
   1080 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef1.size() * sizeof(unsigned int)), &dataRef1[0],
   1081 					 GL_DYNAMIC_DRAW);
   1082 		result.sub_result(BindingPointCheck<api>(_buffers[1]));
   1083 
   1084 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1085 							  &dataTest[0]);
   1086 		result.sub_result(DataCompare(dataRef1, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1087 
   1088 		CDataArray dataRef2;
   1089 		DataGen<unsigned int>(dataRef2, dataWidth, dataHeight, 10, 70);
   1090 
   1091 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[2]);
   1092 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef2.size() * sizeof(unsigned int)), &dataRef2[0],
   1093 					 GL_STREAM_DRAW);
   1094 		result.sub_result(BindingPointCheck<api>(_buffers[2]));
   1095 
   1096 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1097 							  &dataTest[0]);
   1098 		result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1099 
   1100 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[3]);
   1101 		glBufferData(GL_DRAW_INDIRECT_BUFFER, 300, NULL, GL_STATIC_DRAW);
   1102 		result.sub_result(BindingPointCheck<api>(_buffers[3]));
   1103 
   1104 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[4]);
   1105 		glBufferData(GL_DRAW_INDIRECT_BUFFER, 400, NULL, GL_DYNAMIC_READ);
   1106 		result.sub_result(BindingPointCheck<api>(_buffers[4]));
   1107 
   1108 		CDataArray dataRef5;
   1109 		DataGen<unsigned int>(dataRef5, dataWidth, dataHeight, 0, 50);
   1110 
   1111 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[5]);
   1112 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef5.size() * sizeof(unsigned int)), &dataRef5[0],
   1113 					 GL_STREAM_READ);
   1114 		result.sub_result(BindingPointCheck<api>(_buffers[5]));
   1115 
   1116 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1117 							  &dataTest[0]);
   1118 		result.sub_result(DataCompare(dataRef5, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1119 
   1120 		CDataArray dataRef6;
   1121 		DataGen<unsigned int>(dataRef6, dataWidth, dataHeight, 10, 40);
   1122 
   1123 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[6]);
   1124 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef6.size() * sizeof(unsigned int)), &dataRef6[0],
   1125 					 GL_STATIC_READ);
   1126 		result.sub_result(BindingPointCheck<api>(_buffers[6]));
   1127 
   1128 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1129 							  &dataTest[0]);
   1130 		result.sub_result(DataCompare(dataRef6, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1131 
   1132 		CDataArray dataRef7;
   1133 		DataGen<unsigned int>(dataRef7, dataWidth, dataHeight, 4, 70);
   1134 
   1135 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[7]);
   1136 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef7.size() * sizeof(unsigned int)), &dataRef7[0],
   1137 					 GL_DYNAMIC_COPY);
   1138 		result.sub_result(BindingPointCheck<api>(_buffers[7]));
   1139 
   1140 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1141 							  &dataTest[0]);
   1142 		result.sub_result(DataCompare(dataRef7, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1143 
   1144 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[8]);
   1145 		glBufferData(GL_DRAW_INDIRECT_BUFFER, 800, NULL, GL_STREAM_COPY);
   1146 		result.sub_result(BindingPointCheck<api>(_buffers[8]));
   1147 
   1148 		CDataArray dataRef9;
   1149 		DataGen<unsigned int>(dataRef9, dataWidth, dataHeight, 18, 35);
   1150 
   1151 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[9]);
   1152 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef9.size() * sizeof(unsigned int)), &dataRef9[0],
   1153 					 GL_STATIC_COPY);
   1154 		result.sub_result(BindingPointCheck<api>(_buffers[9]));
   1155 
   1156 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1157 							  &dataTest[0]);
   1158 		result.sub_result(DataCompare(dataRef9, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1159 
   1160 		//reallocation: same size
   1161 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef9.size() * sizeof(unsigned int)), &dataRef9[0],
   1162 					 GL_STATIC_COPY);
   1163 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1164 							  &dataTest[0]);
   1165 		result.sub_result(DataCompare(dataRef9, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1166 
   1167 		//reallocation: larger size
   1168 		DataGen<unsigned int>(dataRef9, dataWidth * 2, dataHeight * 2, 18, 35);
   1169 		dataTest.resize(dataRef9.size());
   1170 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef9.size() * sizeof(unsigned int)), &dataRef9[0],
   1171 					 GL_STATIC_COPY);
   1172 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1173 							  &dataTest[0]);
   1174 		result.sub_result(
   1175 			DataCompare(dataRef9, dataWidth * 2, dataHeight * 2, dataTest, dataWidth * 2, dataHeight * 2));
   1176 
   1177 		//reallocation: smaller size
   1178 		DataGen<unsigned int>(dataRef9, dataWidth / 2, dataHeight / 2, 18, 35);
   1179 		dataTest.resize(dataRef9.size());
   1180 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef9.size() * sizeof(unsigned int)), &dataRef9[0],
   1181 					 GL_STATIC_COPY);
   1182 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1183 							  &dataTest[0]);
   1184 		result.sub_result(
   1185 			DataCompare(dataRef9, dataWidth / 2, dataHeight / 2, dataTest, dataWidth / 2, dataHeight / 2));
   1186 
   1187 		return result.code();
   1188 	}
   1189 
   1190 	virtual long Cleanup()
   1191 	{
   1192 		glDeleteBuffers(sizeof(_buffers) / sizeof(_buffers[0]), _buffers);
   1193 		return BindingPointCheck<api>(0);
   1194 	}
   1195 
   1196 private:
   1197 	GLuint _buffers[10];
   1198 };
   1199 
   1200 template <typename api>
   1201 struct CBufferSubData : public DrawIndirectBase
   1202 {
   1203 	virtual std::string Title()
   1204 	{
   1205 		return "Check function: glBufferSubData and GetBufferSubData<api>";
   1206 	}
   1207 
   1208 	virtual std::string Purpose()
   1209 	{
   1210 		return "Verify that glBufferSubData and GetBufferSubData<api> accepts GL_DRAW_INDIRECT_BUFFER enum";
   1211 	}
   1212 
   1213 	virtual std::string Method()
   1214 	{
   1215 		return "1. Create buffer" NL "2. Bind buffer" NL "3. Allocate buffer using glBufferData" NL
   1216 			   "4. Set data using glBufferSubData" NL "5. Get data using GetBufferSubData<api>" NL "6. Verify results";
   1217 	}
   1218 
   1219 	virtual std::string PassCriteria()
   1220 	{
   1221 		return "The test will pass if no OpenGL errors reported";
   1222 	}
   1223 
   1224 	virtual long Run()
   1225 	{
   1226 		DIResult result;
   1227 
   1228 		glGenBuffers(1, &_buffer);
   1229 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer);
   1230 
   1231 		CDataArray dataRef;
   1232 		int		   dataWidth, dataHeight;
   1233 		getDataSize(dataWidth, dataHeight);
   1234 		DataGen<unsigned int>(dataRef, dataWidth, dataHeight, 4, 70);
   1235 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), NULL,
   1236 					 GL_DYNAMIC_DRAW);
   1237 		glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), &dataRef[0]);
   1238 
   1239 		CDataArray dataTest(dataWidth * dataHeight, 0);
   1240 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1241 							  &dataTest[0]);
   1242 
   1243 		result.sub_result(DataCompare(dataRef, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1244 
   1245 		CDataArray dataSubRef;
   1246 		DataGen<unsigned int>(dataSubRef, dataWidth / 2, dataHeight / 2, 80, 90);
   1247 		glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 4, (GLsizeiptr)(dataSubRef.size() * sizeof(unsigned int)),
   1248 						&dataSubRef[0]);
   1249 		std::copy(dataSubRef.begin(), dataSubRef.end(), dataRef.begin() + 1);
   1250 
   1251 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1252 							  &dataTest[0]);
   1253 		result.sub_result(DataCompare(dataRef, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1254 
   1255 		return result.code();
   1256 	}
   1257 
   1258 	virtual long Cleanup()
   1259 	{
   1260 		glDeleteBuffers(1, &_buffer);
   1261 		return BindingPointCheck<api>(0);
   1262 	}
   1263 
   1264 private:
   1265 	GLuint _buffer;
   1266 };
   1267 
   1268 template <typename api>
   1269 struct CBufferMap : public DrawIndirectBase
   1270 {
   1271 	virtual std::string Title()
   1272 	{
   1273 		return "Check functions: glMapBuffer, glUnmapBuffer and getParameteriv";
   1274 	}
   1275 
   1276 	virtual std::string Purpose()
   1277 	{
   1278 		return "Verify that glMapBuffer, glUnmapBuffer and getParameteriv accepts GL_DRAW_INDIRECT_BUFFER enum";
   1279 	}
   1280 
   1281 	virtual std::string Method()
   1282 	{
   1283 		return "1. Create buffer" NL "2. Bind buffer" NL "3. Set data" NL "4. Map buffer" NL
   1284 			   "5. Verify mapped buffer" NL "6. Check state" NL "7. Unmap buffer" NL "8. Check state";
   1285 	}
   1286 
   1287 	virtual std::string PassCriteria()
   1288 	{
   1289 		return "The test will pass if no OpenGL errors reported";
   1290 	}
   1291 
   1292 	virtual long Run()
   1293 	{
   1294 		DIResult result;
   1295 
   1296 		api::GL_Only();
   1297 
   1298 		glGenBuffers(1, &_buffer);
   1299 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer);
   1300 
   1301 		CDataArray dataRef;
   1302 		int		   dataWidth, dataHeight;
   1303 		getDataSize(dataWidth, dataHeight);
   1304 		DataGen<unsigned int>(dataRef, dataWidth, dataHeight, 30, 50);
   1305 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), &dataRef[0],
   1306 					 GL_DYNAMIC_DRAW);
   1307 
   1308 		result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0));
   1309 
   1310 		void* buf = glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_READ_ONLY);
   1311 		if (buf == 0)
   1312 		{
   1313 			result.error() << "glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_READ_ONLY) returned NULL";
   1314 		}
   1315 
   1316 		if (buf)
   1317 		{
   1318 			result.sub_result(BufferCheck(dataRef, dataWidth, dataHeight, buf, dataWidth, dataHeight));
   1319 
   1320 			result.sub_result(StateValidate<api>(GL_TRUE, GL_READ_ONLY, GL_MAP_READ_BIT, 0,
   1321 												 (GLsizeiptr)(dataRef.size() * sizeof(unsigned int))));
   1322 
   1323 			if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE)
   1324 			{
   1325 				result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE";
   1326 			}
   1327 			buf = 0;
   1328 
   1329 			result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0));
   1330 		}
   1331 
   1332 		buf = glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_WRITE_ONLY);
   1333 		if (buf == 0)
   1334 		{
   1335 			result.error() << "glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_WRITE_ONLY) returned NULL";
   1336 		}
   1337 
   1338 		if (buf)
   1339 		{
   1340 			result.sub_result(BufferCheck(dataRef, dataWidth, dataHeight, buf, dataWidth, dataHeight));
   1341 
   1342 			result.sub_result(StateValidate<api>(GL_TRUE, GL_WRITE_ONLY, GL_MAP_WRITE_BIT, 0,
   1343 												 (GLsizeiptr)(dataRef.size() * sizeof(unsigned int))));
   1344 
   1345 			if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) != GL_TRUE)
   1346 			{
   1347 				result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE";
   1348 			}
   1349 			buf = 0;
   1350 
   1351 			result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0));
   1352 		}
   1353 
   1354 		buf = glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_READ_WRITE);
   1355 		if (buf == 0)
   1356 		{
   1357 			result.error() << "glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_READ_WRITE) returned NULL";
   1358 		}
   1359 
   1360 		if (buf)
   1361 		{
   1362 			result.sub_result(BufferCheck(dataRef, dataWidth, dataHeight, buf, dataWidth, dataHeight));
   1363 
   1364 			result.sub_result(StateValidate<api>(GL_TRUE, GL_READ_WRITE, GL_MAP_WRITE_BIT | GL_MAP_READ_BIT, 0,
   1365 												 (GLsizeiptr)(dataRef.size() * sizeof(unsigned int))));
   1366 
   1367 			if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE)
   1368 			{
   1369 				result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE";
   1370 			}
   1371 			buf = 0;
   1372 
   1373 			result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0));
   1374 		}
   1375 
   1376 		return result.code();
   1377 	}
   1378 
   1379 	virtual long Cleanup()
   1380 	{
   1381 		glDeleteBuffers(1, &_buffer);
   1382 		return BindingPointCheck<api>(0);
   1383 	}
   1384 
   1385 private:
   1386 	GLuint _buffer;
   1387 };
   1388 
   1389 template <typename api>
   1390 struct CBufferGetPointerv : public DrawIndirectBase
   1391 {
   1392 	virtual std::string Title()
   1393 	{
   1394 		return "Check functions: glBuffergetPointerv";
   1395 	}
   1396 
   1397 	virtual std::string Purpose()
   1398 	{
   1399 		return "Verify that glBuffergetPointerv accepts GL_DRAW_INDIRECT_BUFFER enum";
   1400 	}
   1401 
   1402 	virtual std::string Method()
   1403 	{
   1404 		return "1. Create buffer" NL "2. Bind buffer" NL "3. Set data" NL "4. Map buffer" NL
   1405 			   "5. Get a pointer to buffer" NL "6. Compare pointers from point 4) and 5)" NL
   1406 			   "7. Verify mapped buffer" NL "8. Unmap buffer";
   1407 	}
   1408 
   1409 	virtual std::string PassCriteria()
   1410 	{
   1411 		return "The test will pass if no OpenGL errors reported";
   1412 	}
   1413 
   1414 	virtual long Run()
   1415 	{
   1416 		DIResult result;
   1417 
   1418 		glGenBuffers(1, &_buffer);
   1419 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer);
   1420 
   1421 		CDataArray dataRef;
   1422 		int		   dataWidth, dataHeight;
   1423 		getDataSize(dataWidth, dataHeight);
   1424 		DataGen<unsigned int>(dataRef, dataWidth, dataHeight, 30, 50);
   1425 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), &dataRef[0],
   1426 					 GL_DYNAMIC_DRAW);
   1427 
   1428 		void* ptr = 0;
   1429 		glGetBufferPointerv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_POINTER, &ptr);
   1430 
   1431 		if (ptr != 0)
   1432 		{
   1433 			result.error() << "glGetBufferPointerv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_POINTER) returned invalid "
   1434 							  "pointer, expected: NULL";
   1435 		}
   1436 
   1437 		void* buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)),
   1438 									 GL_MAP_READ_BIT);
   1439 		if (buf == 0)
   1440 		{
   1441 			result.error() << "glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, GL_MAP_READ_BIT) returned NULL";
   1442 
   1443 			return result.code();
   1444 		}
   1445 
   1446 		glGetBufferPointerv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_POINTER, &ptr);
   1447 
   1448 		if (ptr == 0)
   1449 		{
   1450 			result.error() << "glGetBufferPointerv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_POINTER) returned NULL";
   1451 		}
   1452 
   1453 		if (ptr)
   1454 		{
   1455 			result.sub_result(BufferCheck(dataRef, dataWidth, dataHeight, ptr, dataWidth, dataHeight));
   1456 		}
   1457 
   1458 		if (ptr != buf)
   1459 		{
   1460 			result.error() << "glGetBufferPointerv(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_MAP_POINTER) different pointer "
   1461 							  "than glMapBuffer(GL_DRAW_INDIRECT_BUFFER)";
   1462 		}
   1463 
   1464 		if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE)
   1465 		{
   1466 			result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE";
   1467 		}
   1468 		buf = 0;
   1469 		ptr = 0;
   1470 
   1471 		return result.code();
   1472 	}
   1473 
   1474 	virtual long Cleanup()
   1475 	{
   1476 		glDeleteBuffers(1, &_buffer);
   1477 		return BindingPointCheck<api>(0);
   1478 	}
   1479 
   1480 private:
   1481 	GLuint _buffer;
   1482 };
   1483 
   1484 template <class api>
   1485 struct CBufferMapRange : public DrawIndirectBase
   1486 {
   1487 	virtual std::string Title()
   1488 	{
   1489 		return "Check functions: glMapRangeBuffer, glUnmapBuffer and getParameteriv";
   1490 	}
   1491 
   1492 	virtual std::string Purpose()
   1493 	{
   1494 		return "Verify that glMapRangeBuffer, glUnmapBuffer and getParameteriv accepts GL_DRAW_INDIRECT_BUFFER enum";
   1495 	}
   1496 
   1497 	virtual std::string Method()
   1498 	{
   1499 		return "Bind non-zero buffer and check that binding point is set to correct value";
   1500 	}
   1501 
   1502 	virtual std::string PassCriteria()
   1503 	{
   1504 		return "1. Create buffer" NL "2. Bind buffer" NL "3. Set data" NL "4. Map buffer using glMapBufferRange" NL
   1505 			   "5. Check state" NL "6. Verify mapped buffer" NL "7. Unmap buffer" NL "8. Check state";
   1506 	}
   1507 
   1508 	virtual long Run()
   1509 	{
   1510 		DIResult result;
   1511 
   1512 		glGenBuffers(1, &_buffer);
   1513 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer);
   1514 
   1515 		CDataArray dataRef;
   1516 		int		   dataWidth, dataHeight;
   1517 		getDataSize(dataWidth, dataHeight);
   1518 		DataGen<unsigned int>(dataRef, dataWidth, dataHeight, 30, 50);
   1519 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), &dataRef[0],
   1520 					 GL_DYNAMIC_DRAW);
   1521 
   1522 		result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0));
   1523 
   1524 		void* buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)),
   1525 									 GL_MAP_READ_BIT);
   1526 		if (buf == 0)
   1527 		{
   1528 			result.error() << "glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_MAP_READ_BIT) returned NULL";
   1529 		}
   1530 
   1531 		if (buf)
   1532 		{
   1533 			result.sub_result(BufferCheck(dataRef, dataWidth, dataHeight, buf, dataWidth, dataHeight));
   1534 
   1535 			result.sub_result(StateValidate<api>(GL_TRUE, GL_READ_ONLY, GL_MAP_READ_BIT, 0,
   1536 												 (GLsizeiptr)(dataRef.size() * sizeof(unsigned int))));
   1537 
   1538 			if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE)
   1539 			{
   1540 				result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE";
   1541 			}
   1542 			buf = 0;
   1543 
   1544 			result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0));
   1545 		}
   1546 
   1547 		buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataRef.size() / 2 * sizeof(unsigned int)),
   1548 							   GL_MAP_WRITE_BIT);
   1549 		if (buf == 0)
   1550 		{
   1551 			result.error() << "glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, GL_MAP_WRITE_BIT) returned NULL";
   1552 		}
   1553 
   1554 		if (buf)
   1555 		{
   1556 			result.sub_result(BufferCheck(dataRef, dataWidth, dataHeight / 2, buf, dataWidth, dataHeight / 2));
   1557 
   1558 			result.sub_result(StateValidate<api>(GL_TRUE, GL_WRITE_ONLY, GL_MAP_WRITE_BIT, 0,
   1559 												 (GLsizeiptr)(dataRef.size() / 2 * sizeof(unsigned int))));
   1560 
   1561 			if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE)
   1562 			{
   1563 				result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE";
   1564 			}
   1565 			buf = 0;
   1566 
   1567 			result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0));
   1568 		}
   1569 
   1570 		buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, (GLintptr)(dataRef.size() / 4 * sizeof(unsigned int)),
   1571 							   (GLsizeiptr)(dataRef.size() / 2 * sizeof(unsigned int)), GL_MAP_WRITE_BIT);
   1572 		if (buf == 0)
   1573 		{
   1574 			result.error() << "glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, GL_MAP_WRITE_BIT) returned NULL";
   1575 		}
   1576 
   1577 		if (buf)
   1578 		{
   1579 			result.sub_result(
   1580 				BufferCheck(dataRef, dataWidth, dataHeight / 2, buf, dataWidth, dataHeight / 2, dataHeight / 4));
   1581 
   1582 			result.sub_result(StateValidate<api>(GL_TRUE, GL_WRITE_ONLY, GL_MAP_WRITE_BIT,
   1583 												 (GLintptr)(dataRef.size() / 4 * sizeof(unsigned int)),
   1584 												 (GLsizeiptr)(dataRef.size() / 2 * sizeof(unsigned int))));
   1585 
   1586 			if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE)
   1587 			{
   1588 				result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE";
   1589 			}
   1590 			buf = 0;
   1591 
   1592 			result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0));
   1593 		}
   1594 
   1595 		return result.code();
   1596 	}
   1597 
   1598 	virtual long Cleanup()
   1599 	{
   1600 		glDeleteBuffers(1, &_buffer);
   1601 		return BindingPointCheck<api>(0);
   1602 	}
   1603 
   1604 private:
   1605 	GLuint _buffer;
   1606 };
   1607 
   1608 template <class api>
   1609 struct CBufferFlushMappedRange : public DrawIndirectBase
   1610 {
   1611 	virtual std::string Title()
   1612 	{
   1613 		return "Check functions: glFlushMappedBufferRange";
   1614 	}
   1615 
   1616 	virtual std::string Purpose()
   1617 	{
   1618 		return "Verify that glFlushMappedBufferRange and getParameteriv accepts GL_DRAW_INDIRECT_BUFFER enum";
   1619 	}
   1620 
   1621 	virtual std::string Method()
   1622 	{
   1623 		return "1. Create buffer" NL "2. Bind buffer" NL "3. Set data" NL
   1624 			   "4. Map buffer with GL_MAP_FLUSH_EXPLICIT_BIT flag" NL "5. Check state" NL "6. Modify mapped buffer" NL
   1625 			   "7. Flush buffer" NL "8. Unmap buffer" NL "9. Check state" NL "10. Verify buffer";
   1626 	}
   1627 
   1628 	virtual std::string PassCriteria()
   1629 	{
   1630 		return "The test will pass if no OpenGL errors reported";
   1631 	}
   1632 
   1633 	virtual long Run()
   1634 	{
   1635 		DIResult result;
   1636 
   1637 		glGenBuffers(1, &_buffer);
   1638 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer);
   1639 
   1640 		CDataArray dataRef;
   1641 		int		   dataWidth, dataHeight;
   1642 		getDataSize(dataWidth, dataHeight);
   1643 		DataGen<unsigned int>(dataRef, dataWidth, dataHeight, 1, 1000);
   1644 
   1645 		CDataArray dataRef2;
   1646 		DataGen<unsigned int>(dataRef2, dataWidth, dataHeight, 1000, 2000);
   1647 
   1648 		const int halfSize	= dataHeight / 2 * dataWidth;
   1649 		const int quarterSize = dataHeight / 4 * dataWidth;
   1650 
   1651 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef.size() * sizeof(unsigned int)), &dataRef[0],
   1652 					 GL_DYNAMIC_DRAW);
   1653 
   1654 		result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0));
   1655 
   1656 		void* buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, quarterSize * sizeof(unsigned int),
   1657 									 halfSize * sizeof(unsigned int), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
   1658 
   1659 		if (buf == 0)
   1660 		{
   1661 			result.error() << "glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, GL_MAP_WRITE_BIT) returned NULL";
   1662 		}
   1663 
   1664 		if (buf)
   1665 		{
   1666 			result.sub_result(StateValidate<api>(GL_TRUE, GL_WRITE_ONLY, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT,
   1667 												 quarterSize * sizeof(unsigned int), halfSize * sizeof(unsigned int)));
   1668 
   1669 			memcpy(buf, &dataRef2[quarterSize], halfSize * sizeof(unsigned int));
   1670 			glFlushMappedBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, halfSize * sizeof(unsigned int));
   1671 
   1672 			if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) == GL_FALSE)
   1673 			{
   1674 				result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE";
   1675 			}
   1676 			buf = 0;
   1677 
   1678 			result.sub_result(StateValidate<api>(GL_FALSE, GL_READ_WRITE, 0, 0, 0));
   1679 		}
   1680 
   1681 		CDataArray dataTest(dataWidth * dataHeight, 0);
   1682 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1683 							  &dataTest[0]);
   1684 
   1685 		result.sub_result(DataCompare(dataRef, dataWidth, dataHeight / 4, dataTest, dataWidth, dataHeight / 4));
   1686 
   1687 		result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight / 2, dataTest, dataWidth, dataHeight / 2,
   1688 									  dataHeight / 4, dataHeight / 4));
   1689 
   1690 		result.sub_result(DataCompare(dataRef, dataWidth, dataHeight / 4, dataTest, dataWidth, dataHeight / 4,
   1691 									  dataHeight * 3 / 4, dataHeight * 3 / 4));
   1692 
   1693 		return result.code();
   1694 	}
   1695 
   1696 	virtual long Cleanup()
   1697 	{
   1698 		glDeleteBuffers(1, &_buffer);
   1699 		return BindingPointCheck<api>(0);
   1700 	}
   1701 
   1702 private:
   1703 	GLuint _buffer;
   1704 };
   1705 
   1706 template <class api>
   1707 struct CBufferBindRange : public DrawIndirectBase
   1708 {
   1709 	virtual std::string Title()
   1710 	{
   1711 		return "Check functions: glBindBufferRange";
   1712 	}
   1713 
   1714 	virtual std::string Purpose()
   1715 	{
   1716 		return "Verify that glBindBufferRange accepts GL_DRAW_INDIRECT_BUFFER enum";
   1717 	}
   1718 
   1719 	virtual std::string Method()
   1720 	{
   1721 		return "1. Create buffer" NL "2. Bind buffer using glBindBufferRange" NL "3. Set data" NL "4. Verify buffer";
   1722 	}
   1723 
   1724 	virtual std::string PassCriteria()
   1725 	{
   1726 		return "The test will pass if no OpenGL errors reported";
   1727 	}
   1728 
   1729 	virtual long Run()
   1730 	{
   1731 		DIResult result;
   1732 
   1733 		glGenBuffers(1, &_buffer);
   1734 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffer);
   1735 
   1736 		CDataArray dataRef;
   1737 		int		   dataWidth, dataHeight;
   1738 		getDataSize(dataWidth, dataHeight);
   1739 		DataGen<unsigned int>(dataRef, dataWidth, dataHeight, 1, 100);
   1740 		glBufferData(GL_DRAW_INDIRECT_BUFFER, dataRef.size() * sizeof(unsigned int), &dataRef[0], GL_DYNAMIC_DRAW);
   1741 
   1742 		CDataArray dataTest(dataWidth * dataHeight, 0);
   1743 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, dataTest.size() * sizeof(unsigned int), &dataTest[0]);
   1744 		result.sub_result(DataCompare(dataRef, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1745 
   1746 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
   1747 		result.sub_result(BindingPointCheck<api>(0));
   1748 
   1749 		glBindBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, _buffer, 0, dataTest.size() * sizeof(unsigned int) / 4);
   1750 		result.sub_result(BindingPointCheck<api>(_buffer));
   1751 
   1752 		CDataArray dataRef2;
   1753 		DataGen<unsigned int>(dataRef2, dataWidth, dataHeight / 2, 10, 15);
   1754 		glBufferData(GL_DRAW_INDIRECT_BUFFER, dataRef2.size() * sizeof(unsigned int) / 4, &dataRef2[0],
   1755 					 GL_DYNAMIC_DRAW);
   1756 
   1757 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, dataTest.size() * sizeof(unsigned int), &dataTest[0]);
   1758 		result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight / 4, dataTest, dataWidth, dataHeight / 4));
   1759 		result.sub_result(DataCompare(dataRef, dataWidth, dataHeight * 3 / 4, dataTest, dataWidth, dataHeight * 3 / 4,
   1760 									  dataHeight / 4, dataHeight / 4));
   1761 
   1762 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
   1763 		result.sub_result(BindingPointCheck<api>(0));
   1764 
   1765 		glBindBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, _buffer, dataTest.size() * sizeof(unsigned int) / 4,
   1766 						  dataTest.size() * sizeof(unsigned int) / 4);
   1767 		result.sub_result(BindingPointCheck<api>(_buffer));
   1768 
   1769 		glBufferData(GL_DRAW_INDIRECT_BUFFER, dataRef2.size() * sizeof(unsigned int) / 2,
   1770 					 &dataRef2[dataRef2.size() / 2], GL_DYNAMIC_DRAW);
   1771 		result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight / 2, dataTest, dataWidth, dataHeight / 2));
   1772 		result.sub_result(DataCompare(dataRef, dataWidth, dataHeight / 2, dataTest, dataWidth, dataHeight / 2,
   1773 									  dataHeight / 2, dataHeight / 2));
   1774 
   1775 		return result.code();
   1776 	}
   1777 
   1778 	virtual long Cleanup()
   1779 	{
   1780 		glDeleteBuffers(1, &_buffer);
   1781 
   1782 		return BindingPointCheck<api>(0);
   1783 	}
   1784 
   1785 private:
   1786 	GLuint _buffer;
   1787 };
   1788 
   1789 template <class api>
   1790 struct CBufferBindBase : public DrawIndirectBase
   1791 {
   1792 	virtual std::string Title()
   1793 	{
   1794 		return "Check functions: glBindBufferBase";
   1795 	}
   1796 
   1797 	virtual std::string Purpose()
   1798 	{
   1799 		return "Verify that glBindBufferBase accepts GL_DRAW_INDIRECT_BUFFER enum";
   1800 	}
   1801 
   1802 	virtual std::string Method()
   1803 	{
   1804 		return "1. Create buffer" NL "2. Bind buffer using glBindBufferBase" NL "3. Set data" NL "4. Verify buffer";
   1805 	}
   1806 
   1807 	virtual std::string PassCriteria()
   1808 	{
   1809 		return "The test will pass if no OpenGL errors reported";
   1810 	}
   1811 
   1812 	virtual long Run()
   1813 	{
   1814 		DIResult result;
   1815 
   1816 		glGenBuffers(2, _buffers);
   1817 
   1818 		int dataWidth, dataHeight;
   1819 		getDataSize(dataWidth, dataHeight);
   1820 		CDataArray dataTest(dataWidth * dataHeight, 0);
   1821 
   1822 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[0]);
   1823 		CDataArray dataRef1;
   1824 		DataGen<unsigned int>(dataRef1, dataWidth, dataHeight, 1, 100);
   1825 		glBufferData(GL_DRAW_INDIRECT_BUFFER, dataRef1.size() * sizeof(unsigned int), &dataRef1[0], GL_DYNAMIC_DRAW);
   1826 
   1827 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
   1828 		result.sub_result(BindingPointCheck<api>(0));
   1829 
   1830 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, dataTest.size() * sizeof(unsigned int), &dataTest[0]);
   1831 		result.sub_result(DataCompare(dataRef1, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1832 		result.sub_result(BindingPointCheck<api>(_buffers[0]));
   1833 
   1834 		glBindBufferBase(GL_DRAW_INDIRECT_BUFFER, 0, _buffers[1]);
   1835 		result.sub_result(BindingPointCheck<api>(_buffers[1]));
   1836 
   1837 		CDataArray dataRef2;
   1838 		DataGen<unsigned int>(dataRef2, dataWidth, dataHeight, 50, 70);
   1839 		glBufferData(GL_DRAW_INDIRECT_BUFFER, dataRef2.size() * sizeof(unsigned int), &dataRef2[0], GL_DYNAMIC_DRAW);
   1840 
   1841 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, dataTest.size() * sizeof(unsigned int), &dataTest[0]);
   1842 		result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1843 
   1844 		result.sub_result(BindingPointCheck<api>(_buffers[1]));
   1845 
   1846 		return result.code();
   1847 	}
   1848 
   1849 	virtual long Cleanup()
   1850 	{
   1851 		glDeleteBuffers(2, _buffers);
   1852 		return BindingPointCheck<api>(0);
   1853 	}
   1854 
   1855 private:
   1856 	GLuint _buffers[2];
   1857 };
   1858 
   1859 template <class api>
   1860 struct CBufferCopySubData : public DrawIndirectBase
   1861 {
   1862 	virtual std::string Title()
   1863 	{
   1864 		return "Check functions: glCopyBufferSubData";
   1865 	}
   1866 
   1867 	virtual std::string Purpose()
   1868 	{
   1869 		return "Verify that glCopyBufferSubData accepts GL_DRAW_INDIRECT_BUFFER enum";
   1870 	}
   1871 
   1872 	virtual std::string Method()
   1873 	{
   1874 		return "1. Create buffer" NL "2. Bind buffer" NL "3. Set data" NL "4. Verify buffer" NL
   1875 			   "5. Modify buffer using glCopyBufferSubData" NL "6. Verify buffer";
   1876 	}
   1877 
   1878 	virtual std::string PassCriteria()
   1879 	{
   1880 		return "The test will pass if no OpenGL errors reported";
   1881 	}
   1882 
   1883 	virtual long Run()
   1884 	{
   1885 		DIResult result;
   1886 		int		 dataWidth, dataHeight;
   1887 		getDataSize(dataWidth, dataHeight);
   1888 		CDataArray dataTest(dataWidth * dataHeight, 0);
   1889 
   1890 		glGenBuffers(2, _buffers);
   1891 		glBindBuffer(GL_ARRAY_BUFFER, _buffers[0]);
   1892 
   1893 		CDataArray dataRef1;
   1894 		DataGen<unsigned int>(dataRef1, dataWidth, dataHeight, 1, 100);
   1895 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(dataRef1.size() * sizeof(unsigned int)), &dataRef1[0],
   1896 					 GL_DYNAMIC_DRAW);
   1897 
   1898 		GetBufferSubData<api>(GL_ARRAY_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), &dataTest[0]);
   1899 		result.sub_result(DataCompare(dataRef1, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1900 
   1901 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _buffers[1]);
   1902 
   1903 		CDataArray dataRef2;
   1904 		DataGen<unsigned int>(dataRef2, dataWidth, dataHeight, 10, 30);
   1905 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef2.size() * sizeof(unsigned int)), &dataRef2[0],
   1906 					 GL_DYNAMIC_DRAW);
   1907 
   1908 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1909 							  &dataTest[0]);
   1910 		result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1911 
   1912 		glCopyBufferSubData(GL_ARRAY_BUFFER, GL_DRAW_INDIRECT_BUFFER, 0, 0,
   1913 							(GLsizeiptr)(dataTest.size() * sizeof(unsigned int)));
   1914 
   1915 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1916 							  &dataTest[0]);
   1917 		result.sub_result(DataCompare(dataRef1, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1918 
   1919 		glBufferData(GL_DRAW_INDIRECT_BUFFER, (GLsizeiptr)(dataRef2.size() * sizeof(unsigned int)), &dataRef2[0],
   1920 					 GL_DYNAMIC_DRAW);
   1921 
   1922 		GetBufferSubData<api>(GL_DRAW_INDIRECT_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)),
   1923 							  &dataTest[0]);
   1924 		result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1925 
   1926 		glCopyBufferSubData(GL_DRAW_INDIRECT_BUFFER, GL_ARRAY_BUFFER, 0, 0,
   1927 							(GLsizeiptr)(dataTest.size() * sizeof(unsigned int)));
   1928 
   1929 		GetBufferSubData<api>(GL_ARRAY_BUFFER, 0, (GLsizeiptr)(dataTest.size() * sizeof(unsigned int)), &dataTest[0]);
   1930 		result.sub_result(DataCompare(dataRef2, dataWidth, dataHeight, dataTest, dataWidth, dataHeight));
   1931 
   1932 		return result.code();
   1933 	}
   1934 
   1935 	virtual long Cleanup()
   1936 	{
   1937 		glDeleteBuffers(2, _buffers);
   1938 		return BindingPointCheck<api>(0);
   1939 	}
   1940 
   1941 private:
   1942 	GLuint _buffers[2];
   1943 };
   1944 
   1945 class CBasicVertexDef : public DrawIndirectBase
   1946 {
   1947 public:
   1948 	virtual long Setup()
   1949 	{
   1950 		glClear(GL_COLOR_BUFFER_BIT);
   1951 		return NO_ERROR;
   1952 	}
   1953 
   1954 	template <typename api>
   1955 	long Run()
   1956 	{
   1957 		CColorArray coords;
   1958 		PrimitiveGen(_primitiveType, _drawSizeX, _drawSizeY, coords);
   1959 
   1960 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   1961 		if (!_program)
   1962 		{
   1963 			return ERROR;
   1964 		}
   1965 		glUseProgram(_program);
   1966 
   1967 		glGenBuffers(1, &_vbo);
   1968 		glBindBuffer(GL_ARRAY_BUFFER, _vbo);
   1969 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STATIC_DRAW);
   1970 
   1971 		glGenVertexArrays(1, &_vao);
   1972 		glBindVertexArray(_vao);
   1973 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   1974 		glEnableVertexAttribArray(0);
   1975 
   1976 		DrawArraysIndirectCommand   indirectArrays   = { 0, 0, 0, 0 };
   1977 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   1978 
   1979 		CElementArray elements(coords.size(), 0);
   1980 		for (size_t i = 0; i < elements.size(); ++i)
   1981 		{
   1982 			elements[i] = static_cast<GLuint>(i);
   1983 		}
   1984 
   1985 		switch (_drawFunc)
   1986 		{
   1987 		case DRAW_ARRAYS:
   1988 		{
   1989 			indirectArrays.count			  = static_cast<GLuint>(coords.size());
   1990 			indirectArrays.primCount		  = 1;
   1991 			indirectArrays.first			  = 0;
   1992 			indirectArrays.reservedMustBeZero = 0;
   1993 
   1994 			{
   1995 				GLuint buffer;
   1996 				glGenBuffers(1, &buffer);
   1997 				glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer);
   1998 				glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectArrays), &indirectArrays, GL_STATIC_DRAW);
   1999 				glDrawArraysIndirect(_primitiveType, 0);
   2000 				glDeleteBuffers(1, &buffer);
   2001 			}
   2002 		}
   2003 		break;
   2004 		case DRAW_ELEMENTS:
   2005 		{
   2006 			indirectElements.count				= static_cast<GLuint>(coords.size());
   2007 			indirectElements.primCount			= 1;
   2008 			indirectElements.firstIndex			= 0;
   2009 			indirectElements.baseVertex			= 0;
   2010 			indirectElements.reservedMustBeZero = 0;
   2011 
   2012 			glGenBuffers(1, &_ebo);
   2013 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   2014 			glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   2015 						 GL_STATIC_DRAW);
   2016 
   2017 			{
   2018 				GLuint buffer;
   2019 				glGenBuffers(1, &buffer);
   2020 				glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer);
   2021 				glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectElements), &indirectElements, GL_STATIC_DRAW);
   2022 				glDrawElementsIndirect(_primitiveType, GL_UNSIGNED_INT, 0);
   2023 				glDeleteBuffers(1, &buffer);
   2024 			}
   2025 		}
   2026 		break;
   2027 		default:
   2028 			throw std::runtime_error("Unknown draw function!");
   2029 			break;
   2030 		}
   2031 
   2032 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   2033 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   2034 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   2035 
   2036 		DIResult result;
   2037 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   2038 										 getWindowHeight()));
   2039 
   2040 		return result.code();
   2041 	}
   2042 
   2043 	virtual long Cleanup()
   2044 	{
   2045 		glDisableVertexAttribArray(0);
   2046 		glBindBuffer(GL_ARRAY_BUFFER, 0);
   2047 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
   2048 		glBindVertexArray(0);
   2049 		glUseProgram(0);
   2050 
   2051 		if (_vao)
   2052 		{
   2053 			glDeleteVertexArrays(1, &_vao);
   2054 		}
   2055 		if (_vbo)
   2056 		{
   2057 			glDeleteBuffers(1, &_vbo);
   2058 		}
   2059 		if (_ebo)
   2060 		{
   2061 			glDeleteBuffers(1, &_ebo);
   2062 		}
   2063 		if (_program)
   2064 		{
   2065 			glDeleteProgram(_program);
   2066 		}
   2067 
   2068 		return NO_ERROR;
   2069 	}
   2070 
   2071 	CBasicVertexDef(TDrawFunction drawFunc, GLenum primitiveType, unsigned int drawSizeX, unsigned int drawSizeY)
   2072 		: _drawFunc(drawFunc)
   2073 		, _primitiveType(primitiveType)
   2074 		, _drawSizeX(drawSizeX)
   2075 		, _drawSizeY(drawSizeY)
   2076 		, _vao(0)
   2077 		, _vbo(0)
   2078 		, _ebo(0)
   2079 		, _program(0)
   2080 	{
   2081 	}
   2082 
   2083 private:
   2084 	TDrawFunction _drawFunc;
   2085 	GLenum		  _primitiveType;
   2086 	unsigned int  _drawSizeX;
   2087 	unsigned int  _drawSizeY;
   2088 
   2089 	GLuint _vao;
   2090 	GLuint _vbo, _ebo;
   2091 	GLuint _program;
   2092 
   2093 	CBasicVertexDef()
   2094 	{
   2095 	}
   2096 };
   2097 
   2098 class CBasicVertexInstancingDef : public DrawIndirectBase
   2099 {
   2100 public:
   2101 	virtual long Setup()
   2102 	{
   2103 		glClear(GL_COLOR_BUFFER_BIT);
   2104 		return NO_ERROR;
   2105 	}
   2106 
   2107 	template <typename api>
   2108 	long Run()
   2109 	{
   2110 		CColorArray coords;
   2111 		PrimitiveGen(GL_TRIANGLES, _drawSizeX, _drawSizeY, coords);
   2112 
   2113 		CColorArray coords_instanced(4);
   2114 		coords_instanced[0] = tcu::Vec4(0.5, 0.5, 0.0, 0.0);
   2115 		coords_instanced[1] = tcu::Vec4(-0.5, 0.5, 0.0, 0.0);
   2116 		coords_instanced[2] = tcu::Vec4(-0.5, -0.5, 0.0, 0.0);
   2117 		coords_instanced[3] = tcu::Vec4(0.5, -0.5, 0.0, 0.0);
   2118 
   2119 		CColorArray colors_instanced(2);
   2120 		colors_instanced[0] = tcu::Vec4(1.0, 0.0, 0.0, 1.0);
   2121 		colors_instanced[1] = tcu::Vec4(0.0, 1.0, 0.0, 1.0);
   2122 
   2123 		_program = CreateProgram(Vsh<api>(), "", Fsh<api>(), true);
   2124 		if (!_program)
   2125 		{
   2126 			return ERROR;
   2127 		}
   2128 		glUseProgram(_program);
   2129 
   2130 		glGenBuffers(1, &_vbo);
   2131 		glBindBuffer(GL_ARRAY_BUFFER, _vbo);
   2132 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0]) +
   2133 												   coords_instanced.size() * sizeof(coords_instanced[0]) +
   2134 												   colors_instanced.size() * sizeof(colors_instanced[0])),
   2135 					 NULL, GL_STATIC_DRAW);
   2136 
   2137 		const size_t coords_offset			 = 0;
   2138 		const size_t coords_instanced_offset = coords_offset + coords.size() * sizeof(coords[0]);
   2139 		const size_t colors_instanced_offset =
   2140 			coords_instanced_offset + coords_instanced.size() * sizeof(coords_instanced[0]);
   2141 
   2142 		glBufferSubData(GL_ARRAY_BUFFER, coords_offset, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0]);
   2143 		glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)coords_instanced_offset,
   2144 						(GLsizeiptr)(coords_instanced.size() * sizeof(coords_instanced[0])), &coords_instanced[0]);
   2145 		glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)colors_instanced_offset,
   2146 						(GLsizeiptr)(colors_instanced.size() * sizeof(colors_instanced[0])), &colors_instanced[0]);
   2147 
   2148 		glGenVertexArrays(1, &_vao);
   2149 		glBindVertexArray(_vao);
   2150 
   2151 		//i_vertex (coords)
   2152 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(coords_offset));
   2153 		glEnableVertexAttribArray(0);
   2154 
   2155 		//i_vertex_instanced (coords_instanced)
   2156 		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(coords_instanced_offset));
   2157 		glEnableVertexAttribArray(1);
   2158 		glVertexAttribDivisor(1, 1);
   2159 
   2160 		//i_vertex_color_instanced (color_instanced)
   2161 		glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(colors_instanced_offset));
   2162 		glEnableVertexAttribArray(2);
   2163 		glVertexAttribDivisor(2, 3);
   2164 
   2165 		DrawArraysIndirectCommand   indirectArrays   = { 0, 0, 0, 0 };
   2166 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   2167 
   2168 		CElementArray elements(coords.size(), 0);
   2169 		for (size_t i = 0; i < elements.size(); ++i)
   2170 		{
   2171 			elements[i] = static_cast<GLuint>(i);
   2172 		}
   2173 
   2174 		switch (_drawFunc)
   2175 		{
   2176 		case DRAW_ARRAYS:
   2177 		{
   2178 			indirectArrays.count			  = static_cast<GLuint>(coords.size());
   2179 			indirectArrays.primCount		  = 4;
   2180 			indirectArrays.first			  = 0;
   2181 			indirectArrays.reservedMustBeZero = 0;
   2182 
   2183 			{
   2184 				GLuint buffer;
   2185 				glGenBuffers(1, &buffer);
   2186 				glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer);
   2187 				glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectArrays), &indirectArrays, GL_STATIC_DRAW);
   2188 				glDrawArraysIndirect(GL_TRIANGLES, 0);
   2189 				glDeleteBuffers(1, &buffer);
   2190 			}
   2191 		}
   2192 		break;
   2193 		case DRAW_ELEMENTS:
   2194 		{
   2195 			indirectElements.count				= static_cast<GLuint>(coords.size());
   2196 			indirectElements.primCount			= 4;
   2197 			indirectElements.firstIndex			= 0;
   2198 			indirectElements.baseVertex			= 0;
   2199 			indirectElements.reservedMustBeZero = 0;
   2200 
   2201 			glGenBuffers(1, &_ebo);
   2202 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   2203 			glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   2204 						 GL_STATIC_DRAW);
   2205 
   2206 			{
   2207 				GLuint buffer;
   2208 				glGenBuffers(1, &buffer);
   2209 				glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer);
   2210 				glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectElements), &indirectElements, GL_STATIC_DRAW);
   2211 				glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   2212 				glDeleteBuffers(1, &buffer);
   2213 			}
   2214 		}
   2215 		break;
   2216 		default:
   2217 			throw std::runtime_error("Unknown draw function!");
   2218 			break;
   2219 		}
   2220 
   2221 		CColorArray bufferRef1(getWindowWidth() / 2 * getWindowHeight() / 2, colors_instanced[0]);
   2222 		CColorArray bufferRef2(getWindowWidth() / 2 * getWindowHeight() / 2, colors_instanced[1]);
   2223 
   2224 		CColorArray bufferTest(getWindowWidth() / 2 * getWindowHeight() / 2, tcu::Vec4(0.0f));
   2225 		DIResult	result;
   2226 
   2227 		ReadPixelsFloat<api>(0, 0, getWindowWidth() / 2, getWindowHeight() / 2, &bufferTest[0]);
   2228 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef1,
   2229 										 getWindowWidth() / 2, getWindowHeight() / 2));
   2230 
   2231 		ReadPixelsFloat<api>((getWindowWidth() + 1) / 2, 0, getWindowWidth() / 2, getWindowHeight() / 2,
   2232 							 &bufferTest[0]);
   2233 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef2,
   2234 										 getWindowWidth() / 2, getWindowHeight() / 2));
   2235 
   2236 		ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth() / 2, getWindowHeight() / 2,
   2237 							 &bufferTest[0]);
   2238 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef1,
   2239 										 getWindowWidth() / 2, getWindowHeight() / 2));
   2240 
   2241 		ReadPixelsFloat<api>((getWindowWidth() + 1) / 2, (getWindowHeight() + 1) / 2, getWindowWidth() / 2,
   2242 							 getWindowHeight() / 2, &bufferTest[0]);
   2243 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef1,
   2244 										 getWindowWidth() / 2, getWindowHeight() / 2));
   2245 
   2246 		return result.code();
   2247 	}
   2248 
   2249 	virtual long Cleanup()
   2250 	{
   2251 		glDisableVertexAttribArray(0);
   2252 		glBindBuffer(GL_ARRAY_BUFFER, 0);
   2253 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
   2254 		glBindVertexArray(0);
   2255 		glUseProgram(0);
   2256 
   2257 		if (_vao)
   2258 		{
   2259 			glDeleteVertexArrays(1, &_vao);
   2260 		}
   2261 		if (_vbo)
   2262 		{
   2263 			glDeleteBuffers(1, &_vbo);
   2264 		}
   2265 		if (_ebo)
   2266 		{
   2267 			glDeleteBuffers(1, &_ebo);
   2268 		}
   2269 		if (_program)
   2270 		{
   2271 			glDeleteProgram(_program);
   2272 		}
   2273 
   2274 		return NO_ERROR;
   2275 	}
   2276 
   2277 	template <typename api>
   2278 	std::string Vsh()
   2279 	{
   2280 		return api::glslVer() + NL
   2281 			   "layout(location = 0) in vec4 i_vertex;" NL "layout(location = 1) in vec4 i_vertex_instanced;" NL
   2282 			   "layout(location = 2) in vec4 i_vertex_color_instanced;" NL "out vec4 vertex_color_instanced;" NL
   2283 			   "void main()" NL "{" NL "    gl_Position = vec4(i_vertex.xyz * .5, 1.0) + i_vertex_instanced;" NL
   2284 			   "    vertex_color_instanced = i_vertex_color_instanced;" NL "}";
   2285 	}
   2286 
   2287 	template <typename api>
   2288 	std::string Fsh()
   2289 	{
   2290 		return api::glslVer() + NL "precision highp float; " NL "in  vec4 vertex_color_instanced;" NL
   2291 								   "out vec4 outColor;" NL "void main() {" NL "  outColor = vertex_color_instanced;" NL
   2292 								   "}";
   2293 	}
   2294 
   2295 	CBasicVertexInstancingDef(TDrawFunction drawFunc)
   2296 		: _drawFunc(drawFunc), _drawSizeX(2), _drawSizeY(2), _vao(0), _vbo(0), _ebo(0), _program(0)
   2297 	{
   2298 	}
   2299 
   2300 private:
   2301 	TDrawFunction _drawFunc;
   2302 	unsigned int  _drawSizeX;
   2303 	unsigned int  _drawSizeY;
   2304 
   2305 	GLuint _vao;
   2306 	GLuint _vbo, _ebo;
   2307 	GLuint _program;
   2308 
   2309 	CBasicVertexInstancingDef()
   2310 	{
   2311 	}
   2312 };
   2313 
   2314 template <typename api>
   2315 class CVBODrawArraysSingle : public CBasicVertexDef
   2316 {
   2317 public:
   2318 	virtual std::string Title()
   2319 	{
   2320 		return "VBO: Single primitive using glDrawArraysIndirect";
   2321 	}
   2322 
   2323 	virtual std::string Purpose()
   2324 	{
   2325 		return "Verify that the vertex attributes can be sourced from VBO for glDrawArraysIndirect";
   2326 	}
   2327 
   2328 	virtual std::string Method()
   2329 	{
   2330 		return "1. Define a primitive using VBO" NL "2. Draw primitive using glDrawArraysIndirect" NL
   2331 			   "3. Verify results";
   2332 	}
   2333 
   2334 	virtual std::string PassCriteria()
   2335 	{
   2336 		return "The test will pass if no OpenGL errors reported";
   2337 	}
   2338 
   2339 	CVBODrawArraysSingle() : CBasicVertexDef(DRAW_ARRAYS, GL_TRIANGLES, 1, 1)
   2340 	{
   2341 	}
   2342 	virtual long Run()
   2343 	{
   2344 		return CBasicVertexDef::Run<api>();
   2345 	}
   2346 };
   2347 
   2348 template <typename api>
   2349 class CVBODrawArraysMany : public CBasicVertexDef
   2350 {
   2351 public:
   2352 	virtual std::string Title()
   2353 	{
   2354 		return "VBO: Many primitives using glDrawArraysIndirect";
   2355 	}
   2356 
   2357 	virtual std::string Purpose()
   2358 	{
   2359 		return "Verify that the vertex attributes can be sourced from VBO for glDrawArraysIndirect";
   2360 	}
   2361 
   2362 	virtual std::string Method()
   2363 	{
   2364 		return "1. Define primitives using VBO" NL "2. Draw primitive using glDrawArraysIndirect" NL
   2365 			   "3. Verify results";
   2366 	}
   2367 
   2368 	virtual std::string PassCriteria()
   2369 	{
   2370 		return "The test will pass if no OpenGL errors reported";
   2371 	}
   2372 
   2373 	CVBODrawArraysMany() : CBasicVertexDef(DRAW_ARRAYS, GL_TRIANGLES, 8, 8)
   2374 	{
   2375 	}
   2376 	virtual long Run()
   2377 	{
   2378 		return CBasicVertexDef::Run<api>();
   2379 	}
   2380 };
   2381 
   2382 template <typename api>
   2383 class CVBODrawArraysInstancing : public CBasicVertexInstancingDef
   2384 {
   2385 public:
   2386 	virtual std::string Title()
   2387 	{
   2388 		return "VBO: Single primitive using glDrawArraysIndirect, multiple instances";
   2389 	}
   2390 
   2391 	virtual std::string Purpose()
   2392 	{
   2393 		return "Verify that the vertex attributes can be sourced from VBO for glDrawArraysIndirect";
   2394 	}
   2395 
   2396 	virtual std::string Method()
   2397 	{
   2398 		return "1. Define a primitive using VBO" NL "2. Draw primitive using glDrawArraysIndirect" NL
   2399 			   "3. Verify results";
   2400 	}
   2401 
   2402 	virtual std::string PassCriteria()
   2403 	{
   2404 		return "The test will pass if no OpenGL errors reported";
   2405 	}
   2406 
   2407 	CVBODrawArraysInstancing() : CBasicVertexInstancingDef(DRAW_ARRAYS)
   2408 	{
   2409 	}
   2410 	virtual long Run()
   2411 	{
   2412 		return CBasicVertexInstancingDef::Run<api>();
   2413 	}
   2414 };
   2415 
   2416 class CBasicXFBPausedDef : public DrawIndirectBase
   2417 {
   2418 public:
   2419 	virtual long Setup()
   2420 	{
   2421 		glClear(GL_COLOR_BUFFER_BIT);
   2422 		return NO_ERROR;
   2423 	}
   2424 
   2425 	template <typename api>
   2426 	long Run()
   2427 	{
   2428 		CColorArray coords;
   2429 		PrimitiveGen(GL_TRIANGLES, _drawSizeX, _drawSizeY, coords);
   2430 
   2431 		_program = CreateProgram(Vsh<api>(), "", shaders::fshSimple<api>(), false);
   2432 
   2433 		const GLchar* varyings[] = { "dataOut" };
   2434 		glTransformFeedbackVaryings(_program, 1, varyings, GL_INTERLEAVED_ATTRIBS);
   2435 		glLinkProgram(_program);
   2436 		if (!CheckProgram(_program))
   2437 		{
   2438 			return ERROR;
   2439 		}
   2440 		glUseProgram(_program);
   2441 
   2442 		glGenBuffers(1, &_vbo);
   2443 		glBindBuffer(GL_ARRAY_BUFFER, _vbo);
   2444 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STATIC_DRAW);
   2445 
   2446 		glGenVertexArrays(1, &_vao);
   2447 		glBindVertexArray(_vao);
   2448 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   2449 		glEnableVertexAttribArray(0);
   2450 
   2451 		DrawArraysIndirectCommand   indirectArrays   = { 0, 0, 0, 0 };
   2452 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   2453 
   2454 		CElementArray elements(coords.size(), 0);
   2455 		for (size_t i = 0; i < elements.size(); ++i)
   2456 		{
   2457 			elements[i] = static_cast<GLuint>(i);
   2458 		}
   2459 
   2460 		glGenTransformFeedbacks(1, &_xfo);
   2461 		glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, _xfo);
   2462 
   2463 		glGenBuffers(1, &_xfbo);
   2464 		glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, _xfbo);
   2465 		glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024, NULL, GL_STATIC_DRAW);
   2466 		glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, _xfbo);
   2467 
   2468 		glBeginTransformFeedback(GL_TRIANGLES);
   2469 		glPauseTransformFeedback();
   2470 
   2471 		switch (_drawFunc)
   2472 		{
   2473 		case DRAW_ARRAYS:
   2474 		{
   2475 			indirectArrays.count			  = static_cast<GLuint>(coords.size());
   2476 			indirectArrays.primCount		  = 1;
   2477 			indirectArrays.first			  = 0;
   2478 			indirectArrays.reservedMustBeZero = 0;
   2479 
   2480 			{
   2481 				GLuint buffer;
   2482 				glGenBuffers(1, &buffer);
   2483 				glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer);
   2484 				glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectArrays), &indirectArrays, GL_STATIC_DRAW);
   2485 				glDrawArraysIndirect(GL_TRIANGLES, 0);
   2486 				glDeleteBuffers(1, &buffer);
   2487 			}
   2488 		}
   2489 		break;
   2490 		case DRAW_ELEMENTS:
   2491 		{
   2492 			indirectElements.count				= static_cast<GLuint>(coords.size());
   2493 			indirectElements.primCount			= 1;
   2494 			indirectElements.firstIndex			= 0;
   2495 			indirectElements.baseVertex			= 0;
   2496 			indirectElements.reservedMustBeZero = 0;
   2497 
   2498 			glGenBuffers(1, &_ebo);
   2499 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   2500 			glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   2501 						 GL_STATIC_DRAW);
   2502 
   2503 			{
   2504 				GLuint buffer;
   2505 				glGenBuffers(1, &buffer);
   2506 				glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer);
   2507 				glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectElements), &indirectElements, GL_STATIC_DRAW);
   2508 				glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   2509 				glDeleteBuffers(1, &buffer);
   2510 			}
   2511 		}
   2512 
   2513 		break;
   2514 		default:
   2515 			throw std::runtime_error("Unknown draw function!");
   2516 			break;
   2517 		}
   2518 
   2519 		glResumeTransformFeedback();
   2520 		glEndTransformFeedback();
   2521 
   2522 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   2523 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   2524 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   2525 
   2526 		DIResult result;
   2527 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   2528 										 getWindowHeight()));
   2529 
   2530 		return result.code();
   2531 	}
   2532 
   2533 	virtual long Cleanup()
   2534 	{
   2535 		glDisableVertexAttribArray(0);
   2536 		glBindBuffer(GL_ARRAY_BUFFER, 0);
   2537 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
   2538 		glBindVertexArray(0);
   2539 		glUseProgram(0);
   2540 
   2541 		if (_vao)
   2542 		{
   2543 			glDeleteVertexArrays(1, &_vao);
   2544 		}
   2545 		if (_vbo)
   2546 		{
   2547 			glDeleteBuffers(1, &_vbo);
   2548 		}
   2549 		if (_ebo)
   2550 		{
   2551 			glDeleteBuffers(1, &_ebo);
   2552 		}
   2553 		if (_xfbo)
   2554 		{
   2555 			glDeleteBuffers(1, &_xfbo);
   2556 		}
   2557 		if (_program)
   2558 		{
   2559 			glDeleteProgram(_program);
   2560 		}
   2561 		if (_xfo)
   2562 		{
   2563 			glDeleteTransformFeedbacks(1, &_xfo);
   2564 		}
   2565 
   2566 		return NO_ERROR;
   2567 	}
   2568 
   2569 	template <typename api>
   2570 	std::string Vsh()
   2571 	{
   2572 		return api::glslVer() + NL "in vec4 i_vertex;" NL "out vec4 dataOut;" NL "void main()" NL "{" NL
   2573 								   "    gl_Position = i_vertex;" NL "    dataOut = i_vertex;" NL "}";
   2574 	}
   2575 
   2576 	CBasicXFBPausedDef(TDrawFunction drawFunc)
   2577 		: _drawFunc(drawFunc), _drawSizeX(2), _drawSizeY(2), _vao(0), _vbo(0), _ebo(0), _xfbo(0), _program(0), _xfo(0)
   2578 	{
   2579 	}
   2580 
   2581 private:
   2582 	TDrawFunction _drawFunc;
   2583 	unsigned int  _drawSizeX;
   2584 	unsigned int  _drawSizeY;
   2585 
   2586 	GLuint _vao;
   2587 	GLuint _vbo, _ebo, _xfbo;
   2588 	GLuint _program;
   2589 	GLuint _xfo;
   2590 
   2591 	CBasicXFBPausedDef()
   2592 	{
   2593 	}
   2594 };
   2595 
   2596 template <typename api>
   2597 class CVBODrawArraysXFBPaused : public CBasicXFBPausedDef
   2598 {
   2599 public:
   2600 	virtual std::string Title()
   2601 	{
   2602 		return "VBO: glDrawArraysIndirect, in paused transform feedback operation";
   2603 	}
   2604 
   2605 	virtual std::string Purpose()
   2606 	{
   2607 		return "Verify  glDrawArraysIndirect works, if XFB is active and paused";
   2608 	}
   2609 
   2610 	virtual std::string Method()
   2611 	{
   2612 		return "1. Define a primitive using VBO" NL "2. Draw primitive using glDrawArraysIndirect" NL
   2613 			   "3. Verify results";
   2614 	}
   2615 
   2616 	virtual std::string PassCriteria()
   2617 	{
   2618 		return "The test will pass if no OpenGL errors reported";
   2619 	}
   2620 
   2621 	CVBODrawArraysXFBPaused() : CBasicXFBPausedDef(DRAW_ARRAYS)
   2622 	{
   2623 	}
   2624 	virtual long Run()
   2625 	{
   2626 		return CBasicXFBPausedDef::Run<api>();
   2627 	}
   2628 };
   2629 
   2630 template <typename api>
   2631 class CVBODrawElementsSingle : public CBasicVertexDef
   2632 {
   2633 public:
   2634 	virtual std::string Title()
   2635 	{
   2636 		return "VBO: Single primitive using glDrawElementsIndirect";
   2637 	}
   2638 
   2639 	virtual std::string Purpose()
   2640 	{
   2641 		return "Verify that the vertex attributes can be sourced from VBO for glDrawElementsIndirect";
   2642 	}
   2643 
   2644 	virtual std::string Method()
   2645 	{
   2646 		return "1. Define a primitive using VBO" NL "2. Draw primitive using glDrawElementsIndirect" NL
   2647 			   "3. Verify results";
   2648 	}
   2649 
   2650 	virtual std::string PassCriteria()
   2651 	{
   2652 		return "The test will pass if no OpenGL errors reported";
   2653 	}
   2654 
   2655 	CVBODrawElementsSingle() : CBasicVertexDef(DRAW_ELEMENTS, GL_TRIANGLES, 1, 1)
   2656 	{
   2657 	}
   2658 	virtual long Run()
   2659 	{
   2660 		return CBasicVertexDef::Run<api>();
   2661 	}
   2662 };
   2663 
   2664 template <typename api>
   2665 class CVBODrawElementsMany : public CBasicVertexDef
   2666 {
   2667 public:
   2668 	virtual std::string Title()
   2669 	{
   2670 		return "VBO: Many primitives using glDrawElementsIndirect";
   2671 	}
   2672 
   2673 	virtual std::string Purpose()
   2674 	{
   2675 		return "Verify that the vertex attributes can be sourced from VBO for glDrawElementsIndirect";
   2676 	}
   2677 
   2678 	virtual std::string Method()
   2679 	{
   2680 		return "1. Define primitives using VBO" NL "2. Draw primitive using glDrawElementsIndirect" NL
   2681 			   "3. Verify results";
   2682 	}
   2683 
   2684 	virtual std::string PassCriteria()
   2685 	{
   2686 		return "The test will pass if no OpenGL errors reported";
   2687 	}
   2688 
   2689 	CVBODrawElementsMany() : CBasicVertexDef(DRAW_ELEMENTS, GL_TRIANGLES, 8, 8)
   2690 	{
   2691 	}
   2692 
   2693 	virtual long Run()
   2694 	{
   2695 		return CBasicVertexDef::Run<api>();
   2696 	}
   2697 };
   2698 
   2699 template <typename api>
   2700 class CVBODrawElementsInstancing : public CBasicVertexInstancingDef
   2701 {
   2702 public:
   2703 	virtual std::string Title()
   2704 	{
   2705 		return "VBO: Single primitive using glDrawElementsIndirect, multiple instances";
   2706 	}
   2707 
   2708 	virtual std::string Purpose()
   2709 	{
   2710 		return "Verify that the vertex attributes can be sourced from VBO for glDrawElementsIndirect";
   2711 	}
   2712 
   2713 	virtual std::string Method()
   2714 	{
   2715 		return "1. Define a primitive using VBO" NL "2. Draw primitive using glDrawElementsIndirect" NL
   2716 			   "3. Verify results";
   2717 	}
   2718 
   2719 	virtual std::string PassCriteria()
   2720 	{
   2721 		return "The test will pass if no OpenGL errors reported";
   2722 	}
   2723 
   2724 	CVBODrawElementsInstancing() : CBasicVertexInstancingDef(DRAW_ELEMENTS)
   2725 	{
   2726 	}
   2727 	virtual long Run()
   2728 	{
   2729 		return CBasicVertexInstancingDef::Run<api>();
   2730 	}
   2731 };
   2732 
   2733 template <typename api>
   2734 class CVBODrawElementsXFBPaused : public CBasicXFBPausedDef
   2735 {
   2736 public:
   2737 	virtual std::string Title()
   2738 	{
   2739 		return "VBO: glDrawElementsIndirect, in paused transform feedback operation";
   2740 	}
   2741 
   2742 	virtual std::string Purpose()
   2743 	{
   2744 		return "Verify  glDrawElementsIndirect works, if XFB is active and paused";
   2745 	}
   2746 
   2747 	virtual std::string Method()
   2748 	{
   2749 		return "1. Define a primitive using VBO" NL "2. Draw primitive using glDrawArraysIndirect" NL
   2750 			   "3. Verify results";
   2751 	}
   2752 
   2753 	virtual std::string PassCriteria()
   2754 	{
   2755 		return "The test will pass if no OpenGL errors reported";
   2756 	}
   2757 
   2758 	CVBODrawElementsXFBPaused() : CBasicXFBPausedDef(DRAW_ELEMENTS)
   2759 	{
   2760 	}
   2761 	virtual long Run()
   2762 	{
   2763 		return CBasicXFBPausedDef::Run<api>();
   2764 	}
   2765 };
   2766 
   2767 template <typename api>
   2768 class CBufferIndirectDrawArraysSimple : public DrawIndirectBase
   2769 {
   2770 public:
   2771 	virtual std::string Title()
   2772 	{
   2773 		return "Indirect buffer glDrawArraysIndirect: many primitives simple";
   2774 	}
   2775 
   2776 	virtual std::string Purpose()
   2777 	{
   2778 		return "Verify that it is possible to draw primitives with specified indirect structure" NL "in a buffer";
   2779 	}
   2780 
   2781 	virtual std::string Method()
   2782 	{
   2783 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   2784 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   2785 	}
   2786 
   2787 	virtual std::string PassCriteria()
   2788 	{
   2789 		return "The test will pass if no OpenGL errors reported";
   2790 	}
   2791 
   2792 	virtual long Setup()
   2793 	{
   2794 		glClear(GL_COLOR_BUFFER_BIT);
   2795 		return NO_ERROR;
   2796 	}
   2797 
   2798 	virtual long Run()
   2799 	{
   2800 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   2801 		if (!_program)
   2802 		{
   2803 			return ERROR;
   2804 		}
   2805 		glUseProgram(_program);
   2806 
   2807 		CColorArray coords;
   2808 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   2809 
   2810 		glGenVertexArrays(1, &_vao);
   2811 		glBindVertexArray(_vao);
   2812 
   2813 		glGenBuffers(1, &_buffer);
   2814 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   2815 
   2816 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   2817 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   2818 		glEnableVertexAttribArray(0);
   2819 
   2820 		DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 };
   2821 		indirectArrays.count					 = static_cast<GLuint>(coords.size());
   2822 		indirectArrays.primCount				 = 1;
   2823 		indirectArrays.first					 = 0;
   2824 		indirectArrays.reservedMustBeZero		 = 0;
   2825 
   2826 		glGenBuffers(1, &_bufferIndirect);
   2827 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   2828 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW);
   2829 
   2830 		glDrawArraysIndirect(GL_TRIANGLES, 0);
   2831 
   2832 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   2833 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   2834 
   2835 		DIResult result;
   2836 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   2837 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   2838 										 getWindowHeight()));
   2839 
   2840 		return result.code();
   2841 	}
   2842 
   2843 	virtual long Cleanup()
   2844 	{
   2845 		glDisableVertexAttribArray(0);
   2846 		glUseProgram(0);
   2847 		glDeleteProgram(_program);
   2848 		glDeleteVertexArrays(1, &_vao);
   2849 		glDeleteBuffers(1, &_buffer);
   2850 		glDeleteBuffers(1, &_bufferIndirect);
   2851 		return NO_ERROR;
   2852 	}
   2853 
   2854 private:
   2855 	GLuint _program;
   2856 	GLuint _vao, _buffer, _bufferIndirect;
   2857 };
   2858 
   2859 template <typename api>
   2860 class CBufferIndirectDrawArraysNoFirst : public DrawIndirectBase
   2861 {
   2862 public:
   2863 	virtual std::string Title()
   2864 	{
   2865 		return "Indirect buffer glDrawArraysIndirect: non-zero 'first' argument";
   2866 	}
   2867 
   2868 	virtual std::string Purpose()
   2869 	{
   2870 		return "Verify that it is possible to draw primitives with specified non-zero 'first' argument" NL
   2871 			   "in indirect buffer";
   2872 	}
   2873 
   2874 	virtual std::string Method()
   2875 	{
   2876 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   2877 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   2878 	}
   2879 
   2880 	virtual std::string PassCriteria()
   2881 	{
   2882 		return "The test will pass if no OpenGL errors reported";
   2883 	}
   2884 
   2885 	virtual long Setup()
   2886 	{
   2887 		glClear(GL_COLOR_BUFFER_BIT);
   2888 		return NO_ERROR;
   2889 	}
   2890 
   2891 	virtual long Run()
   2892 	{
   2893 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   2894 		if (!_program)
   2895 		{
   2896 			return ERROR;
   2897 		}
   2898 		glUseProgram(_program);
   2899 
   2900 		CColorArray coords;
   2901 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   2902 
   2903 		glGenVertexArrays(1, &_vao);
   2904 		glBindVertexArray(_vao);
   2905 
   2906 		glGenBuffers(1, &_buffer);
   2907 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   2908 
   2909 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   2910 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   2911 		glEnableVertexAttribArray(0);
   2912 
   2913 		DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 };
   2914 		indirectArrays.count					 = static_cast<GLuint>(coords.size()) / 2;
   2915 		indirectArrays.primCount				 = 1;
   2916 		indirectArrays.first					 = static_cast<GLuint>(coords.size()) / 2;
   2917 		indirectArrays.reservedMustBeZero		 = 0;
   2918 
   2919 		glGenBuffers(1, &_bufferIndirect);
   2920 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   2921 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW);
   2922 
   2923 		glDrawArraysIndirect(GL_TRIANGLES, 0);
   2924 
   2925 		CColorArray bufferRef1(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
   2926 		CColorArray bufferRef2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   2927 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   2928 
   2929 		DIResult result;
   2930 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]);
   2931 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef1,
   2932 										 getWindowWidth(), getWindowHeight() / 2));
   2933 
   2934 		ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]);
   2935 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef2,
   2936 										 getWindowWidth(), getWindowHeight() / 2));
   2937 
   2938 		return result.code();
   2939 	}
   2940 
   2941 	virtual long Cleanup()
   2942 	{
   2943 		glDisableVertexAttribArray(0);
   2944 		glUseProgram(0);
   2945 		glDeleteProgram(_program);
   2946 		glDeleteVertexArrays(1, &_vao);
   2947 		glDeleteBuffers(1, &_buffer);
   2948 		glDeleteBuffers(1, &_bufferIndirect);
   2949 		return NO_ERROR;
   2950 	}
   2951 
   2952 private:
   2953 	GLuint _program;
   2954 	GLuint _vao, _buffer, _bufferIndirect;
   2955 };
   2956 
   2957 template <typename api>
   2958 class CBufferIndirectDrawArraysOffset : public DrawIndirectBase
   2959 {
   2960 public:
   2961 	virtual std::string Title()
   2962 	{
   2963 		return "Indirect buffer glDrawArraysIndirect: offset as a function parameter";
   2964 	}
   2965 
   2966 	virtual std::string Purpose()
   2967 	{
   2968 		return "Verify that it is possible to draw primitives with offset as a function parameter";
   2969 	}
   2970 
   2971 	virtual std::string Method()
   2972 	{
   2973 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   2974 			   "3. Draw primitives using glDrawArraysIndirect with offset" NL "4. Verify results";
   2975 	}
   2976 
   2977 	virtual std::string PassCriteria()
   2978 	{
   2979 		return "The test will pass if no OpenGL errors reported";
   2980 	}
   2981 
   2982 	virtual long Setup()
   2983 	{
   2984 		glClear(GL_COLOR_BUFFER_BIT);
   2985 		return NO_ERROR;
   2986 	}
   2987 
   2988 	virtual long Run()
   2989 	{
   2990 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   2991 		if (!_program)
   2992 		{
   2993 			return ERROR;
   2994 		}
   2995 		glUseProgram(_program);
   2996 
   2997 		CColorArray coords;
   2998 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   2999 
   3000 		glGenVertexArrays(1, &_vao);
   3001 		glBindVertexArray(_vao);
   3002 
   3003 		glGenBuffers(1, &_buffer);
   3004 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   3005 
   3006 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   3007 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   3008 		glEnableVertexAttribArray(0);
   3009 
   3010 		DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 };
   3011 		indirectArrays.count					 = static_cast<GLuint>(coords.size());
   3012 		indirectArrays.primCount				 = 1;
   3013 		indirectArrays.first					 = 0;
   3014 		indirectArrays.reservedMustBeZero		 = 0;
   3015 
   3016 		glGenBuffers(1, &_bufferIndirect);
   3017 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   3018 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand) * 3, NULL, GL_STATIC_DRAW);
   3019 		glBufferSubData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), sizeof(DrawArraysIndirectCommand),
   3020 						&indirectArrays);
   3021 		glDrawArraysIndirect(GL_TRIANGLES, (void*)sizeof(DrawArraysIndirectCommand));
   3022 
   3023 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   3024 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   3025 
   3026 		DIResult result;
   3027 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   3028 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   3029 										 getWindowHeight()));
   3030 
   3031 		return result.code();
   3032 	}
   3033 
   3034 	virtual long Cleanup()
   3035 	{
   3036 		glDisableVertexAttribArray(0);
   3037 		glUseProgram(0);
   3038 		glDeleteProgram(_program);
   3039 		glDeleteVertexArrays(1, &_vao);
   3040 		glDeleteBuffers(1, &_buffer);
   3041 		glDeleteBuffers(1, &_bufferIndirect);
   3042 		return NO_ERROR;
   3043 	}
   3044 
   3045 private:
   3046 	GLuint _program;
   3047 	GLuint _vao, _buffer, _bufferIndirect;
   3048 };
   3049 
   3050 template <typename api>
   3051 class CBufferIndirectDrawElementsSimple : public DrawIndirectBase
   3052 {
   3053 public:
   3054 	virtual std::string Title()
   3055 	{
   3056 		return "Indirect buffer glDrawElementsIndirect: many primitives simple";
   3057 	}
   3058 
   3059 	virtual std::string Purpose()
   3060 	{
   3061 		return "Verify that it is possible to draw primitives with specified indirect structure" NL "in a buffer";
   3062 	}
   3063 
   3064 	virtual std::string Method()
   3065 	{
   3066 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   3067 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   3068 	}
   3069 
   3070 	virtual std::string PassCriteria()
   3071 	{
   3072 		return "The test will pass if no OpenGL errors reported";
   3073 	}
   3074 
   3075 	virtual long Setup()
   3076 	{
   3077 		glClear(GL_COLOR_BUFFER_BIT);
   3078 		return NO_ERROR;
   3079 	}
   3080 
   3081 	virtual long Run()
   3082 	{
   3083 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   3084 		if (!_program)
   3085 		{
   3086 			return ERROR;
   3087 		}
   3088 		glUseProgram(_program);
   3089 
   3090 		CColorArray coords;
   3091 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   3092 
   3093 		glGenVertexArrays(1, &_vao);
   3094 		glBindVertexArray(_vao);
   3095 
   3096 		glGenBuffers(1, &_buffer);
   3097 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   3098 
   3099 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   3100 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   3101 		glEnableVertexAttribArray(0);
   3102 
   3103 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   3104 		indirectElements.count						 = static_cast<GLuint>(coords.size());
   3105 		indirectElements.primCount					 = 1;
   3106 		indirectElements.baseVertex					 = 0;
   3107 		indirectElements.firstIndex					 = 0;
   3108 		indirectElements.reservedMustBeZero			 = 0;
   3109 
   3110 		CElementArray elements(coords.size(), 0);
   3111 		for (size_t i = 0; i < elements.size(); ++i)
   3112 		{
   3113 			elements[i] = static_cast<GLuint>(i);
   3114 		}
   3115 
   3116 		glGenBuffers(1, &_bufferIndirect);
   3117 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   3118 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   3119 
   3120 		glGenBuffers(1, &_ebo);
   3121 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   3122 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   3123 					 GL_STATIC_DRAW);
   3124 
   3125 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   3126 
   3127 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   3128 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   3129 
   3130 		DIResult result;
   3131 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   3132 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   3133 										 getWindowHeight()));
   3134 
   3135 		return result.code();
   3136 	}
   3137 
   3138 	virtual long Cleanup()
   3139 	{
   3140 		glDisableVertexAttribArray(0);
   3141 		glUseProgram(0);
   3142 		glDeleteProgram(_program);
   3143 		glDeleteVertexArrays(1, &_vao);
   3144 		glDeleteBuffers(1, &_buffer);
   3145 		glDeleteBuffers(1, &_bufferIndirect);
   3146 		glDeleteBuffers(1, &_ebo);
   3147 		return NO_ERROR;
   3148 	}
   3149 
   3150 private:
   3151 	GLuint _program;
   3152 	GLuint _vao, _buffer, _bufferIndirect, _ebo;
   3153 };
   3154 
   3155 template <typename api>
   3156 class CBufferIndirectDrawElementsNoFirstIndex : public DrawIndirectBase
   3157 {
   3158 public:
   3159 	virtual std::string Title()
   3160 	{
   3161 		return "Indirect buffer glDrawElementsIndirect: non-zero first index";
   3162 	}
   3163 
   3164 	virtual std::string Purpose()
   3165 	{
   3166 		return "Verify that it is possible to draw primitives with non-zero first index" NL "in indirect buffer";
   3167 	}
   3168 
   3169 	virtual std::string Method()
   3170 	{
   3171 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   3172 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   3173 	}
   3174 
   3175 	virtual std::string PassCriteria()
   3176 	{
   3177 		return "The test will pass if no OpenGL errors reported";
   3178 	}
   3179 
   3180 	virtual long Setup()
   3181 	{
   3182 		glClear(GL_COLOR_BUFFER_BIT);
   3183 		return NO_ERROR;
   3184 	}
   3185 
   3186 	virtual long Run()
   3187 	{
   3188 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   3189 		if (!_program)
   3190 		{
   3191 			return ERROR;
   3192 		}
   3193 		glUseProgram(_program);
   3194 
   3195 		CColorArray coords;
   3196 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   3197 
   3198 		glGenVertexArrays(1, &_vao);
   3199 		glBindVertexArray(_vao);
   3200 
   3201 		glGenBuffers(1, &_buffer);
   3202 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   3203 
   3204 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   3205 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   3206 		glEnableVertexAttribArray(0);
   3207 
   3208 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   3209 		indirectElements.count						 = static_cast<GLuint>(coords.size()) / 2;
   3210 		indirectElements.primCount					 = 1;
   3211 		indirectElements.baseVertex					 = 0;
   3212 		indirectElements.firstIndex					 = static_cast<GLuint>(coords.size()) / 2;
   3213 		indirectElements.reservedMustBeZero			 = 0;
   3214 
   3215 		CElementArray elements(coords.size(), 0);
   3216 		for (size_t i = 0; i < elements.size(); ++i)
   3217 		{
   3218 			elements[i] = static_cast<GLuint>(i);
   3219 		}
   3220 
   3221 		glGenBuffers(1, &_bufferIndirect);
   3222 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   3223 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   3224 
   3225 		glGenBuffers(1, &_ebo);
   3226 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   3227 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   3228 					 GL_STATIC_DRAW);
   3229 
   3230 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   3231 
   3232 		CColorArray bufferRef1(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
   3233 		CColorArray bufferRef2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   3234 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   3235 
   3236 		DIResult result;
   3237 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]);
   3238 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef1,
   3239 										 getWindowWidth(), getWindowHeight() / 2));
   3240 
   3241 		ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]);
   3242 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef2,
   3243 										 getWindowWidth(), getWindowHeight() / 2));
   3244 
   3245 		return result.code();
   3246 	}
   3247 
   3248 	virtual long Cleanup()
   3249 	{
   3250 		glDisableVertexAttribArray(0);
   3251 		glUseProgram(0);
   3252 		glDeleteProgram(_program);
   3253 		glDeleteVertexArrays(1, &_vao);
   3254 		glDeleteBuffers(1, &_buffer);
   3255 		glDeleteBuffers(1, &_ebo);
   3256 		glDeleteBuffers(1, &_bufferIndirect);
   3257 		return NO_ERROR;
   3258 	}
   3259 
   3260 private:
   3261 	GLuint _program;
   3262 	GLuint _vao, _buffer, _bufferIndirect, _ebo;
   3263 };
   3264 
   3265 template <typename api>
   3266 class CBufferIndirectDrawElementsNoBasevertex : public DrawIndirectBase
   3267 {
   3268 public:
   3269 	virtual std::string Title()
   3270 	{
   3271 		return "Indirect buffer glDrawElementsIndirect: non-zero base vertex";
   3272 	}
   3273 
   3274 	virtual std::string Purpose()
   3275 	{
   3276 		return "Verify that it is possible to draw primitives with non-zero base vertex" NL "in indirect buffer";
   3277 	}
   3278 
   3279 	virtual std::string Method()
   3280 	{
   3281 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   3282 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   3283 	}
   3284 
   3285 	virtual std::string PassCriteria()
   3286 	{
   3287 		return "The test will pass if no OpenGL errors reported";
   3288 	}
   3289 
   3290 	virtual long Setup()
   3291 	{
   3292 		glClear(GL_COLOR_BUFFER_BIT);
   3293 		return NO_ERROR;
   3294 	}
   3295 
   3296 	virtual long Run()
   3297 	{
   3298 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   3299 		if (!_program)
   3300 		{
   3301 			return ERROR;
   3302 		}
   3303 		glUseProgram(_program);
   3304 
   3305 		CColorArray coords;
   3306 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   3307 
   3308 		glGenVertexArrays(1, &_vao);
   3309 		glBindVertexArray(_vao);
   3310 
   3311 		glGenBuffers(1, &_buffer);
   3312 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   3313 
   3314 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   3315 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   3316 		glEnableVertexAttribArray(0);
   3317 
   3318 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   3319 		indirectElements.count						 = static_cast<GLuint>(coords.size()) / 2;
   3320 		indirectElements.primCount					 = 1;
   3321 		indirectElements.baseVertex					 = static_cast<GLint>(coords.size()) / 2;
   3322 		indirectElements.firstIndex					 = 0;
   3323 		indirectElements.reservedMustBeZero			 = 0;
   3324 
   3325 		CElementArray elements(coords.size(), 0);
   3326 		for (size_t i = 0; i < elements.size(); ++i)
   3327 		{
   3328 			elements[i] = static_cast<GLuint>(i);
   3329 		}
   3330 
   3331 		glGenBuffers(1, &_bufferIndirect);
   3332 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   3333 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   3334 
   3335 		glGenBuffers(1, &_ebo);
   3336 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   3337 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   3338 					 GL_STATIC_DRAW);
   3339 
   3340 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   3341 
   3342 		CColorArray bufferRef1(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
   3343 		CColorArray bufferRef2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   3344 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   3345 
   3346 		DIResult result;
   3347 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]);
   3348 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef1,
   3349 										 getWindowWidth(), getWindowHeight() / 2));
   3350 
   3351 		ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]);
   3352 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef2,
   3353 										 getWindowWidth(), getWindowHeight() / 2));
   3354 
   3355 		return result.code();
   3356 	}
   3357 
   3358 	virtual long Cleanup()
   3359 	{
   3360 		glDisableVertexAttribArray(0);
   3361 		glUseProgram(0);
   3362 		glDeleteProgram(_program);
   3363 		glDeleteVertexArrays(1, &_vao);
   3364 		glDeleteBuffers(1, &_buffer);
   3365 		glDeleteBuffers(1, &_ebo);
   3366 		glDeleteBuffers(1, &_bufferIndirect);
   3367 		return NO_ERROR;
   3368 	}
   3369 
   3370 private:
   3371 	GLuint _program;
   3372 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   3373 };
   3374 
   3375 template <typename api>
   3376 class CBufferIndirectDrawElementsOffset : public DrawIndirectBase
   3377 {
   3378 public:
   3379 	virtual std::string Title()
   3380 	{
   3381 		return "Indirect buffer glDrawElementsIndirect: offset as a function parameter";
   3382 	}
   3383 
   3384 	virtual std::string Purpose()
   3385 	{
   3386 		return "Verify that it is possible to draw primitives with offset as a function parameter";
   3387 	}
   3388 
   3389 	virtual std::string Method()
   3390 	{
   3391 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   3392 			   "3. Draw primitives using glDrawElementsIndirect with offset" NL "4. Verify results";
   3393 	}
   3394 
   3395 	virtual std::string PassCriteria()
   3396 	{
   3397 		return "The test will pass if no OpenGL errors reported";
   3398 	}
   3399 
   3400 	virtual long Setup()
   3401 	{
   3402 		glClear(GL_COLOR_BUFFER_BIT);
   3403 		return NO_ERROR;
   3404 	}
   3405 
   3406 	virtual long Run()
   3407 	{
   3408 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   3409 		if (!_program)
   3410 		{
   3411 			return ERROR;
   3412 		}
   3413 		glUseProgram(_program);
   3414 
   3415 		CColorArray coords;
   3416 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   3417 
   3418 		glGenVertexArrays(1, &_vao);
   3419 		glBindVertexArray(_vao);
   3420 
   3421 		glGenBuffers(1, &_buffer);
   3422 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   3423 
   3424 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   3425 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   3426 		glEnableVertexAttribArray(0);
   3427 
   3428 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   3429 		indirectElements.count						 = static_cast<GLuint>(coords.size());
   3430 		indirectElements.primCount					 = 1;
   3431 		indirectElements.baseVertex					 = 0;
   3432 		indirectElements.firstIndex					 = 0;
   3433 		indirectElements.reservedMustBeZero			 = 0;
   3434 
   3435 		CElementArray elements(coords.size(), 0);
   3436 		for (size_t i = 0; i < elements.size(); ++i)
   3437 		{
   3438 			elements[i] = static_cast<GLuint>(i);
   3439 		}
   3440 
   3441 		glGenBuffers(1, &_bufferIndirect);
   3442 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   3443 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand) * 3, NULL, GL_STATIC_DRAW);
   3444 		glBufferSubData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand),
   3445 						sizeof(DrawElementsIndirectCommand), &indirectElements);
   3446 
   3447 		glGenBuffers(1, &_ebo);
   3448 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   3449 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   3450 					 GL_STATIC_DRAW);
   3451 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, (void*)sizeof(DrawElementsIndirectCommand));
   3452 
   3453 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   3454 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   3455 
   3456 		DIResult result;
   3457 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   3458 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   3459 										 getWindowHeight()));
   3460 
   3461 		return result.code();
   3462 	}
   3463 
   3464 	virtual long Cleanup()
   3465 	{
   3466 		glDisableVertexAttribArray(0);
   3467 		glUseProgram(0);
   3468 		glDeleteProgram(_program);
   3469 		glDeleteVertexArrays(1, &_vao);
   3470 		glDeleteBuffers(1, &_buffer);
   3471 		glDeleteBuffers(1, &_ebo);
   3472 		glDeleteBuffers(1, &_bufferIndirect);
   3473 		return NO_ERROR;
   3474 	}
   3475 
   3476 private:
   3477 	GLuint _program;
   3478 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   3479 };
   3480 
   3481 class CBasicVertexIDsDef : public DrawIndirectBase
   3482 {
   3483 public:
   3484 	virtual long Setup()
   3485 	{
   3486 		glClear(GL_COLOR_BUFFER_BIT);
   3487 		return NO_ERROR;
   3488 	}
   3489 
   3490 	template <typename api>
   3491 	long Run()
   3492 	{
   3493 		CColorArray coords;
   3494 		PrimitiveGen(GL_TRIANGLES, _drawSizeX, _drawSizeY, coords);
   3495 
   3496 		CColorArray coords_instanced(4);
   3497 		coords_instanced[0] = tcu::Vec4(0.5, 0.5, 0.0, 0.0);
   3498 		coords_instanced[1] = tcu::Vec4(-0.5, 0.5, 0.0, 0.0);
   3499 		coords_instanced[2] = tcu::Vec4(-0.5, -0.5, 0.0, 0.0);
   3500 		coords_instanced[3] = tcu::Vec4(0.5, -0.5, 0.0, 0.0);
   3501 
   3502 		std::vector<glw::GLfloat> ref_VertexId(coords.size());
   3503 		for (size_t i = 0; i < ref_VertexId.size(); i++)
   3504 		{
   3505 			ref_VertexId[i] = glw::GLfloat(i);
   3506 		}
   3507 
   3508 		std::vector<glw::GLfloat> ref_InstanceId(4);
   3509 		for (size_t i = 0; i < ref_InstanceId.size(); i++)
   3510 		{
   3511 			ref_InstanceId[i] = glw::GLfloat(i);
   3512 		}
   3513 
   3514 		_program = CreateProgram(Vsh<api>(), "", Fsh<api>(), true);
   3515 		if (!_program)
   3516 		{
   3517 			return ERROR;
   3518 		}
   3519 		glUseProgram(_program);
   3520 
   3521 		glGenBuffers(1, &_vbo);
   3522 		glBindBuffer(GL_ARRAY_BUFFER, _vbo);
   3523 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0]) +
   3524 												   coords_instanced.size() * sizeof(coords_instanced[0]) +
   3525 												   ref_VertexId.size() * sizeof(ref_VertexId[0]) +
   3526 												   ref_InstanceId.size() * sizeof(ref_InstanceId[0])),
   3527 					 NULL, GL_STATIC_DRAW);
   3528 
   3529 		const size_t coords_offset			 = 0;
   3530 		const size_t coords_instanced_offset = coords_offset + coords.size() * sizeof(coords[0]);
   3531 		const size_t ref_VertexId_offset =
   3532 			coords_instanced_offset + coords_instanced.size() * sizeof(coords_instanced[0]);
   3533 		const size_t ref_InstanceId_offset = ref_VertexId_offset + ref_VertexId.size() * sizeof(ref_VertexId[0]);
   3534 
   3535 		glBufferSubData(GL_ARRAY_BUFFER, coords_offset, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0]);
   3536 		glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)coords_instanced_offset,
   3537 						(GLsizeiptr)(coords_instanced.size() * sizeof(coords_instanced[0])), &coords_instanced[0]);
   3538 		glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)ref_VertexId_offset,
   3539 						(GLsizeiptr)(ref_VertexId.size() * sizeof(ref_VertexId[0])), &ref_VertexId[0]);
   3540 		glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)ref_InstanceId_offset,
   3541 						(GLsizeiptr)(ref_InstanceId.size() * sizeof(ref_InstanceId[0])), &ref_InstanceId[0]);
   3542 
   3543 		glGenVertexArrays(1, &_vao);
   3544 		glBindVertexArray(_vao);
   3545 
   3546 		//i_vertex (coords)
   3547 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(coords_offset));
   3548 		glEnableVertexAttribArray(0);
   3549 
   3550 		//i_vertex_instanced (coords_instanced)
   3551 		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(coords_instanced_offset));
   3552 		glEnableVertexAttribArray(1);
   3553 		glVertexAttribDivisor(1, 1);
   3554 
   3555 		//i_ref_VertexId
   3556 		glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(ref_VertexId_offset));
   3557 		glEnableVertexAttribArray(2);
   3558 		//i_ref_InstanceId
   3559 		glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<glw::GLvoid*>(ref_InstanceId_offset));
   3560 		glEnableVertexAttribArray(3);
   3561 		glVertexAttribDivisor(3, 1);
   3562 
   3563 		DrawArraysIndirectCommand   indirectArrays   = { 0, 0, 0, 0 };
   3564 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   3565 
   3566 		CElementArray elements(coords.size(), 0);
   3567 		for (size_t i = 0; i < elements.size(); ++i)
   3568 		{
   3569 			elements[i] = static_cast<GLuint>(i);
   3570 		}
   3571 
   3572 		switch (_drawFunc)
   3573 		{
   3574 		case DRAW_ARRAYS:
   3575 		{
   3576 			indirectArrays.count			  = static_cast<GLuint>(coords.size());
   3577 			indirectArrays.primCount		  = 4;
   3578 			indirectArrays.first			  = 0;
   3579 			indirectArrays.reservedMustBeZero = 0;
   3580 
   3581 			{
   3582 				GLuint buffer;
   3583 				glGenBuffers(1, &buffer);
   3584 				glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer);
   3585 				glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectArrays), &indirectArrays, GL_STATIC_DRAW);
   3586 				glDrawArraysIndirect(GL_TRIANGLES, 0);
   3587 				glDeleteBuffers(1, &buffer);
   3588 			}
   3589 		}
   3590 		break;
   3591 		case DRAW_ELEMENTS:
   3592 		{
   3593 			indirectElements.count				= static_cast<GLuint>(coords.size());
   3594 			indirectElements.primCount			= 4;
   3595 			indirectElements.firstIndex			= 0;
   3596 			indirectElements.baseVertex			= 0;
   3597 			indirectElements.reservedMustBeZero = 0;
   3598 
   3599 			glGenBuffers(1, &_ebo);
   3600 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   3601 			glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   3602 						 GL_STATIC_DRAW);
   3603 
   3604 			{
   3605 				GLuint buffer;
   3606 				glGenBuffers(1, &buffer);
   3607 				glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer);
   3608 				glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(indirectElements), &indirectElements, GL_STATIC_DRAW);
   3609 				glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   3610 				glDeleteBuffers(1, &buffer);
   3611 			}
   3612 		}
   3613 		break;
   3614 		default:
   3615 			throw std::runtime_error("Unknown draw function!");
   3616 			break;
   3617 		}
   3618 
   3619 		CColorArray bufferRef1(getWindowWidth() / 2 * getWindowHeight() / 2, tcu::Vec4(0.0f, 1.0f, 0.5f, 0.0f));
   3620 		CColorArray bufferRef2(getWindowWidth() / 2 * getWindowHeight() / 2, tcu::Vec4(0.0f, 1.0f, 0.75f, 0.0f));
   3621 		CColorArray bufferRef3(getWindowWidth() / 2 * getWindowHeight() / 2, tcu::Vec4(0.0f, 1.0f, 0.25f, 0.0f));
   3622 		CColorArray bufferRef4(getWindowWidth() / 2 * getWindowHeight() / 2, tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f));
   3623 
   3624 		CColorArray bufferTest(getWindowWidth() / 2 * getWindowHeight() / 2, tcu::Vec4(0.0f));
   3625 		DIResult	result;
   3626 
   3627 		ReadPixelsFloat<api>(0, 0, getWindowWidth() / 2, getWindowHeight() / 2, &bufferTest[0]);
   3628 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef1,
   3629 										 getWindowWidth() / 2, getWindowHeight() / 2));
   3630 
   3631 		ReadPixelsFloat<api>((getWindowWidth() + 1) / 2, 0, getWindowWidth() / 2, getWindowHeight() / 2,
   3632 							 &bufferTest[0]);
   3633 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef2,
   3634 										 getWindowWidth() / 2, getWindowHeight() / 2));
   3635 
   3636 		ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth() / 2, getWindowHeight() / 2,
   3637 							 &bufferTest[0]);
   3638 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef3,
   3639 										 getWindowWidth() / 2, getWindowHeight() / 2));
   3640 
   3641 		ReadPixelsFloat<api>((getWindowWidth() + 1) / 2, (getWindowHeight() + 1) / 2, getWindowWidth() / 2,
   3642 							 getWindowHeight() / 2, &bufferTest[0]);
   3643 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth() / 2, getWindowHeight() / 2, bufferRef4,
   3644 										 getWindowWidth() / 2, getWindowHeight() / 2));
   3645 
   3646 		return result.code();
   3647 	}
   3648 
   3649 	virtual long Cleanup()
   3650 	{
   3651 		glDisableVertexAttribArray(0);
   3652 		glBindBuffer(GL_ARRAY_BUFFER, 0);
   3653 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
   3654 		glBindVertexArray(0);
   3655 		glUseProgram(0);
   3656 
   3657 		if (_vao)
   3658 		{
   3659 			glDeleteVertexArrays(1, &_vao);
   3660 		}
   3661 		if (_vbo)
   3662 		{
   3663 			glDeleteBuffers(1, &_vbo);
   3664 		}
   3665 		if (_ebo)
   3666 		{
   3667 			glDeleteBuffers(1, &_ebo);
   3668 		}
   3669 		if (_program)
   3670 		{
   3671 			glDeleteProgram(_program);
   3672 		}
   3673 
   3674 		return NO_ERROR;
   3675 	}
   3676 
   3677 	template <typename api>
   3678 	std::string Vsh()
   3679 	{
   3680 		return api::glslVer() + NL
   3681 			   "layout(location = 0) in vec4 i_vertex;" NL "layout(location = 1) in vec4 i_vertex_instanced;" NL
   3682 			   "layout(location = 2) in float i_ref_VertexId;" NL "layout(location = 3) in float i_ref_InstanceId;" NL
   3683 			   "out vec4 val_Result;" NL "void main()" NL "{" NL
   3684 			   "    gl_Position = vec4(i_vertex.xyz * .5, 1.0) + i_vertex_instanced;" NL
   3685 			   "    if ( gl_VertexID == int(i_ref_VertexId + .5) && gl_InstanceID == int(i_ref_InstanceId + .5)) {" NL
   3686 			   "        val_Result = vec4(0.0, 1.0, float(gl_InstanceID) / 4.0, 1.0);" NL "    } else {" NL
   3687 			   "        val_Result = vec4(1.0, 0.0, 0.0, 1.0);" NL "    }" NL "}";
   3688 	}
   3689 
   3690 	template <typename api>
   3691 	std::string Fsh()
   3692 	{
   3693 		return api::glslVer() + NL "precision highp float; " NL "in vec4 val_Result;" NL "out vec4 outColor;" NL
   3694 								   "void main() {" NL "  outColor = val_Result;" NL "}";
   3695 	}
   3696 
   3697 	CBasicVertexIDsDef(TDrawFunction drawFunc)
   3698 		: _drawFunc(drawFunc), _drawSizeX(2), _drawSizeY(2), _vao(0), _vbo(0), _ebo(0), _program(0)
   3699 	{
   3700 	}
   3701 
   3702 private:
   3703 	TDrawFunction _drawFunc;
   3704 	unsigned int  _drawSizeX;
   3705 	unsigned int  _drawSizeY;
   3706 
   3707 	GLuint _vao;
   3708 	GLuint _vbo, _ebo;
   3709 	GLuint _program;
   3710 
   3711 	CBasicVertexIDsDef()
   3712 	{
   3713 	}
   3714 };
   3715 
   3716 template <typename api>
   3717 class CBufferIndirectDrawArraysVertexIds : public CBasicVertexIDsDef
   3718 {
   3719 public:
   3720 	virtual std::string Title()
   3721 	{
   3722 		return "Indirect buffer glDrawArraysIndirect: all non-zero arguments, verify vertex ids";
   3723 	}
   3724 
   3725 	virtual std::string Purpose()
   3726 	{
   3727 		return "Verify that it is possible to draw primitives with all non-zero arguments" NL "in indirect buffer";
   3728 	}
   3729 
   3730 	virtual std::string Method()
   3731 	{
   3732 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   3733 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   3734 	}
   3735 
   3736 	virtual std::string PassCriteria()
   3737 	{
   3738 		return "The test will pass if no OpenGL errors reported";
   3739 	}
   3740 
   3741 	virtual long Run()
   3742 	{
   3743 		return CBasicVertexIDsDef::Run<api>();
   3744 	}
   3745 
   3746 	CBufferIndirectDrawArraysVertexIds() : CBasicVertexIDsDef(DRAW_ARRAYS)
   3747 	{
   3748 	}
   3749 };
   3750 
   3751 template <typename api>
   3752 class CBufferIndirectDrawElementsVertexIds : public CBasicVertexIDsDef
   3753 {
   3754 public:
   3755 	virtual std::string Title()
   3756 	{
   3757 		return "Indirect buffer glDrawElementsIndirect: all non-zero arguments, verify vertex ids";
   3758 	}
   3759 
   3760 	virtual std::string Purpose()
   3761 	{
   3762 		return "Verify that it is possible to draw primitives with all non-zero arguments" NL "in indirect buffer";
   3763 	}
   3764 
   3765 	virtual std::string Method()
   3766 	{
   3767 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   3768 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   3769 	}
   3770 
   3771 	virtual std::string PassCriteria()
   3772 	{
   3773 		return "The test will pass if no OpenGL errors reported";
   3774 	}
   3775 
   3776 	virtual long Run()
   3777 	{
   3778 		return CBasicVertexIDsDef::Run<api>();
   3779 	}
   3780 
   3781 	CBufferIndirectDrawElementsVertexIds() : CBasicVertexIDsDef(DRAW_ELEMENTS)
   3782 	{
   3783 	}
   3784 };
   3785 
   3786 template <typename api>
   3787 class CIndicesDataTypeUnsignedShort : public DrawIndirectBase
   3788 {
   3789 public:
   3790 	virtual std::string Title()
   3791 	{
   3792 		return "glDrawElementsIndirect indices data type: unsigned short";
   3793 	}
   3794 
   3795 	virtual std::string Purpose()
   3796 	{
   3797 		return "Verify that unsigned short indices are accepted by glDrawElementsIndirect";
   3798 	}
   3799 
   3800 	virtual std::string Method()
   3801 	{
   3802 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL "3. Create element buffer" NL
   3803 			   "4. Draw primitives using glDrawElementsIndirect" NL "5. Verify results";
   3804 	}
   3805 
   3806 	virtual std::string PassCriteria()
   3807 	{
   3808 		return "The test will pass if no OpenGL errors reported";
   3809 	}
   3810 
   3811 	virtual long Setup()
   3812 	{
   3813 		glClear(GL_COLOR_BUFFER_BIT);
   3814 		return NO_ERROR;
   3815 	}
   3816 
   3817 	virtual long Run()
   3818 	{
   3819 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   3820 		if (!_program)
   3821 		{
   3822 			return ERROR;
   3823 		}
   3824 		glUseProgram(_program);
   3825 
   3826 		CColorArray coords;
   3827 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   3828 
   3829 		glGenVertexArrays(1, &_vao);
   3830 		glBindVertexArray(_vao);
   3831 
   3832 		glGenBuffers(1, &_buffer);
   3833 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   3834 
   3835 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   3836 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   3837 		glEnableVertexAttribArray(0);
   3838 
   3839 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   3840 		indirectElements.count						 = static_cast<GLuint>(coords.size()) / 2;
   3841 		indirectElements.primCount					 = 1;
   3842 		indirectElements.baseVertex					 = -static_cast<GLint>(coords.size()) / 4;
   3843 		indirectElements.firstIndex					 = static_cast<GLuint>(coords.size()) / 4;
   3844 		indirectElements.reservedMustBeZero			 = 0;
   3845 
   3846 		std::vector<GLushort> elements(coords.size(), 0);
   3847 		for (size_t i = 0; i < elements.size(); ++i)
   3848 		{
   3849 			elements[i] = static_cast<GLushort>(i);
   3850 		}
   3851 
   3852 		glGenBuffers(1, &_bufferIndirect);
   3853 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   3854 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), NULL, GL_STATIC_DRAW);
   3855 		glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawElementsIndirectCommand), &indirectElements);
   3856 
   3857 		glGenBuffers(1, &_ebo);
   3858 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   3859 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   3860 					 GL_STATIC_DRAW);
   3861 
   3862 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, 0);
   3863 
   3864 		CColorArray bufferRef1(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
   3865 		CColorArray bufferRef2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   3866 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   3867 
   3868 		DIResult result;
   3869 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]);
   3870 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef2,
   3871 										 getWindowWidth(), getWindowHeight() / 2));
   3872 
   3873 		ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]);
   3874 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef1,
   3875 										 getWindowWidth(), getWindowHeight() / 2));
   3876 
   3877 		return result.code();
   3878 	}
   3879 
   3880 	virtual long Cleanup()
   3881 	{
   3882 		glDisableVertexAttribArray(0);
   3883 		glUseProgram(0);
   3884 		glDeleteProgram(_program);
   3885 		glDeleteVertexArrays(1, &_vao);
   3886 		glDeleteBuffers(1, &_buffer);
   3887 		glDeleteBuffers(1, &_ebo);
   3888 		glDeleteBuffers(1, &_bufferIndirect);
   3889 		return NO_ERROR;
   3890 	}
   3891 
   3892 private:
   3893 	GLuint _program;
   3894 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   3895 };
   3896 
   3897 template <typename api>
   3898 class CIndicesDataTypeUnsignedByte : public DrawIndirectBase
   3899 {
   3900 public:
   3901 	virtual std::string Title()
   3902 	{
   3903 		return "glDrawElementsIndirect indices data type: unsigned byte";
   3904 	}
   3905 
   3906 	virtual std::string Purpose()
   3907 	{
   3908 		return "Verify that unsigned byte indices are accepted by glDrawElementsIndirect";
   3909 	}
   3910 
   3911 	virtual std::string Method()
   3912 	{
   3913 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL "3. Create element buffer" NL
   3914 			   "4. Draw primitives using glDrawElementsIndirect" NL "5. Verify results";
   3915 	}
   3916 
   3917 	virtual std::string PassCriteria()
   3918 	{
   3919 		return "The test will pass if no OpenGL errors reported";
   3920 	}
   3921 
   3922 	virtual long Setup()
   3923 	{
   3924 		glClear(GL_COLOR_BUFFER_BIT);
   3925 		return NO_ERROR;
   3926 	}
   3927 
   3928 	virtual long Run()
   3929 	{
   3930 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   3931 		if (!_program)
   3932 		{
   3933 			return ERROR;
   3934 		}
   3935 		glUseProgram(_program);
   3936 
   3937 		CColorArray coords;
   3938 		PrimitiveGen(GL_TRIANGLES, 2, 2, coords);
   3939 
   3940 		glGenVertexArrays(1, &_vao);
   3941 		glBindVertexArray(_vao);
   3942 
   3943 		glGenBuffers(1, &_buffer);
   3944 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   3945 
   3946 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   3947 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   3948 		glEnableVertexAttribArray(0);
   3949 
   3950 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   3951 		indirectElements.count						 = static_cast<GLuint>(coords.size()) / 2;
   3952 		indirectElements.primCount					 = 1;
   3953 		indirectElements.baseVertex					 = -static_cast<GLint>(coords.size()) / 4;
   3954 		indirectElements.firstIndex					 = static_cast<GLuint>(coords.size()) / 4;
   3955 		indirectElements.reservedMustBeZero			 = 0;
   3956 
   3957 		std::vector<GLubyte> elements(coords.size(), 0);
   3958 		for (size_t i = 0; i < elements.size(); ++i)
   3959 		{
   3960 			elements[i] = static_cast<GLubyte>(i);
   3961 		}
   3962 
   3963 		glGenBuffers(1, &_bufferIndirect);
   3964 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   3965 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), NULL, GL_STATIC_DRAW);
   3966 		glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawElementsIndirectCommand), &indirectElements);
   3967 
   3968 		glGenBuffers(1, &_ebo);
   3969 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   3970 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   3971 					 GL_STATIC_DRAW);
   3972 
   3973 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_BYTE, 0);
   3974 
   3975 		CColorArray bufferRef1(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
   3976 		CColorArray bufferRef2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   3977 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   3978 
   3979 		DIResult result;
   3980 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]);
   3981 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef2,
   3982 										 getWindowWidth(), getWindowHeight() / 2));
   3983 
   3984 		ReadPixelsFloat<api>(0, (getWindowHeight() + 1) / 2, getWindowWidth(), getWindowHeight() / 2, &bufferTest[0]);
   3985 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight() / 2, bufferRef1,
   3986 										 getWindowWidth(), getWindowHeight() / 2));
   3987 
   3988 		return result.code();
   3989 	}
   3990 
   3991 	virtual long Cleanup()
   3992 	{
   3993 		glDisableVertexAttribArray(0);
   3994 		glUseProgram(0);
   3995 		glDeleteProgram(_program);
   3996 		glDeleteVertexArrays(1, &_vao);
   3997 		glDeleteBuffers(1, &_buffer);
   3998 		glDeleteBuffers(1, &_ebo);
   3999 		glDeleteBuffers(1, &_bufferIndirect);
   4000 		return NO_ERROR;
   4001 	}
   4002 
   4003 private:
   4004 	GLuint _program;
   4005 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   4006 };
   4007 
   4008 class CPrimitiveMode : public DrawIndirectBase
   4009 {
   4010 public:
   4011 	template <typename api>
   4012 	bool IsGeometryShaderSupported()
   4013 	{
   4014 		if (api::isES())
   4015 		{
   4016 			const glu::ContextInfo& info = m_context.getContextInfo();
   4017 			const glu::ContextType& type = m_context.getRenderContext().getType();
   4018 
   4019 			/* ES 3.2+ included geometry shaders into the core */
   4020 			if (glu::contextSupports(type, glu::ApiType(3, 2, glu::PROFILE_ES)))
   4021 			{
   4022 				return true;
   4023 			}
   4024 			/* ES 3.1 may be able to support geometry shaders via extensions */
   4025 			else if ((glu::contextSupports(type, glu::ApiType(3, 1, glu::PROFILE_ES))) &&
   4026 					 ((true == info.isExtensionSupported("GL_EXT_geometry_shader")) ||
   4027 					  (true == info.isExtensionSupported("GL_OES_geometry_shader"))))
   4028 			{
   4029 				return true;
   4030 			}
   4031 			else
   4032 			{
   4033 				OutputNotSupported("Geometry shader is not supported\n");
   4034 				return false;
   4035 			}
   4036 		}
   4037 		else
   4038 		{
   4039 			return true;
   4040 		}
   4041 	}
   4042 	virtual long Setup()
   4043 	{
   4044 		_sizeX = getWindowWidth();
   4045 		_sizeY = getWindowHeight();
   4046 		if (_primitiveType != GL_TRIANGLE_STRIP && _primitiveType != GL_TRIANGLE_STRIP_ADJACENCY &&
   4047 			_primitiveType != GL_TRIANGLES && _primitiveType != GL_TRIANGLES_ADJACENCY &&
   4048 			_primitiveType != GL_TRIANGLE_FAN)
   4049 		{
   4050 			_sizeX &= (-4);
   4051 			_sizeY &= (-4);
   4052 		}
   4053 		if ((int)_drawSizeX < 0 || (int)_drawSizeY < 0)
   4054 		{
   4055 			//no PrimitiveGen dimensions given. assume same dimensions as rendered image^
   4056 			_drawSizeX = _sizeX;
   4057 			_drawSizeY = _sizeY;
   4058 			if (_primitiveType == GL_POINTS)
   4059 			{
   4060 				//clamp vertex number (and rendering size) for points to max. 10000
   4061 				_sizeX = _drawSizeX = std::min(_drawSizeX, 100u);
   4062 				_sizeY = _drawSizeY = std::min(_drawSizeY, 100u);
   4063 			}
   4064 		}
   4065 
   4066 		glClear(GL_COLOR_BUFFER_BIT);
   4067 		return NO_ERROR;
   4068 	}
   4069 
   4070 	template <typename api>
   4071 	long Run(bool pointMode = false)
   4072 	{
   4073 
   4074 		glClear(GL_COLOR_BUFFER_BIT);
   4075 
   4076 		_program = CreateProgram(pointMode ? shaders::vshSimple_point<api>() : shaders::vshSimple<api>(), "",
   4077 								 shaders::fshSimple<api>(), true);
   4078 		if (!_program)
   4079 		{
   4080 			return ERROR;
   4081 		}
   4082 		glUseProgram(_program);
   4083 
   4084 		CColorArray coords;
   4085 		PrimitiveGen(_primitiveType, _drawSizeX, _drawSizeY, coords);
   4086 
   4087 		glGenVertexArrays(1, &_vao);
   4088 		glBindVertexArray(_vao);
   4089 
   4090 		glGenBuffers(1, &_buffer);
   4091 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   4092 
   4093 		CColorArray padding(10, tcu::Vec4(0.0f));
   4094 
   4095 		glBufferData(GL_ARRAY_BUFFER,
   4096 					 (GLsizeiptr)(coords.size() * (sizeof(coords[0])) + padding.size() * (sizeof(padding[0]))), NULL,
   4097 					 GL_STREAM_DRAW);
   4098 		glBufferSubData(GL_ARRAY_BUFFER, 0, (GLsizeiptr)(padding.size() * (sizeof(padding[0]))), &padding[0]);
   4099 		glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)(padding.size() * (sizeof(padding[0]))),
   4100 						(GLsizeiptr)(coords.size() * (sizeof(coords[0]))), &coords[0]);
   4101 
   4102 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   4103 		glEnableVertexAttribArray(0);
   4104 
   4105 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   4106 		DrawArraysIndirectCommand   indirectArrays   = { 0, 0, 0, 0 };
   4107 
   4108 		CElementArray elements(coords.size(), 0);
   4109 		for (size_t i = 0; i < elements.size(); ++i)
   4110 		{
   4111 			elements[i] = static_cast<GLuint>(i);
   4112 		}
   4113 
   4114 		glGenBuffers(1, &_bufferIndirect);
   4115 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   4116 
   4117 		switch (_drawFunc)
   4118 		{
   4119 		case DRAW_ARRAYS:
   4120 		{
   4121 			indirectArrays.count			  = static_cast<GLuint>(coords.size()) / 2;
   4122 			indirectArrays.primCount		  = 1;
   4123 			indirectArrays.first			  = 10;
   4124 			indirectArrays.reservedMustBeZero = 0;
   4125 
   4126 			glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), NULL, GL_STATIC_DRAW);
   4127 			glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawArraysIndirectCommand), &indirectArrays);
   4128 
   4129 			glDrawArraysIndirect(_primitiveType, 0);
   4130 		}
   4131 		break;
   4132 		case DRAW_ELEMENTS:
   4133 		{
   4134 			indirectElements.count				= static_cast<GLuint>(coords.size()) / 2;
   4135 			indirectElements.primCount			= 1;
   4136 			indirectElements.baseVertex			= 7;
   4137 			indirectElements.firstIndex			= 3;
   4138 			indirectElements.reservedMustBeZero = 0;
   4139 
   4140 			glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), NULL, GL_STATIC_DRAW);
   4141 			glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawElementsIndirectCommand), &indirectElements);
   4142 
   4143 			glGenBuffers(1, &_ebo);
   4144 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   4145 			glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   4146 						 GL_STATIC_DRAW);
   4147 
   4148 			glDrawElementsIndirect(_primitiveType, GL_UNSIGNED_INT, 0);
   4149 		}
   4150 		break;
   4151 		default:
   4152 			throw std::runtime_error("Unknown draw function!");
   4153 			break;
   4154 		}
   4155 
   4156 		CColorArray bufferRef1(_sizeX * _sizeY / 2, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
   4157 		CColorArray bufferRef2(_sizeX * _sizeY / 2, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   4158 		CColorArray bufferTest(_sizeX * _sizeY, tcu::Vec4(0.0f));
   4159 
   4160 		DIResult result;
   4161 		ReadPixelsFloat<api>(0, (_sizeY + 1) / 2, _sizeX, _sizeY / 2, &bufferTest[0]);
   4162 		result.sub_result(BuffersCompare(bufferTest, _sizeX, _sizeY / 2, bufferRef1, _sizeX, _sizeY / 2));
   4163 
   4164 		switch (_primitiveType)
   4165 		{
   4166 		case GL_TRIANGLES_ADJACENCY:
   4167 		case GL_TRIANGLE_STRIP_ADJACENCY:
   4168 		{
   4169 			CColorArray bufferRef3(_sizeX * _sizeY / 16, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
   4170 			CColorArray bufferRef4(_sizeX * _sizeY / 8, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   4171 			CColorArray bufferRef5(_sizeX * _sizeY / 4, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
   4172 
   4173 			CColorArray bufferTest3(_sizeX * _sizeY / 16, tcu::Vec4(0.0f));
   4174 			CColorArray bufferTest4(_sizeX * _sizeY / 8, tcu::Vec4(0.0f));
   4175 			CColorArray bufferTest5(_sizeX * _sizeY / 4, tcu::Vec4(0.0f));
   4176 
   4177 			ReadPixelsFloat<api>(0, (_sizeY + 3) / 4, _sizeX / 4, _sizeY / 4, &bufferTest3[0]);
   4178 			result.sub_result(BuffersCompare(bufferTest3, _sizeX / 4, _sizeY / 4, bufferRef3, _sizeX / 4, _sizeY / 4));
   4179 
   4180 			ReadPixelsFloat<api>((_sizeX + 3) / 4, (_sizeY + 3) / 4, _sizeX / 2, _sizeY / 4, &bufferTest4[0]);
   4181 			result.sub_result(BuffersCompare(bufferTest4, _sizeX / 2, _sizeY / 4, bufferRef4, _sizeX / 2, _sizeY / 4));
   4182 
   4183 			ReadPixelsFloat<api>((_sizeX * 3 + 3) / 4, (_sizeY + 3) / 4, _sizeX / 4, _sizeY / 4, &bufferTest3[0]);
   4184 			result.sub_result(BuffersCompare(bufferTest3, _sizeX / 4, _sizeY / 4, bufferRef3, _sizeX / 4, _sizeY / 4));
   4185 
   4186 			ReadPixelsFloat<api>(0, 0, _sizeX, _sizeY / 4, &bufferTest5[0]);
   4187 			result.sub_result(BuffersCompare(bufferTest5, _sizeX, _sizeY / 4, bufferRef5, _sizeX, _sizeY / 4));
   4188 		}
   4189 		break;
   4190 		default:
   4191 		{
   4192 			ReadPixelsFloat<api>(0, 0, _sizeX, _sizeY / 2, &bufferTest[0]);
   4193 			result.sub_result(BuffersCompare(bufferTest, _sizeX, _sizeY / 2, bufferRef2, _sizeX, _sizeY / 2));
   4194 		}
   4195 		break;
   4196 		}
   4197 
   4198 		return result.code();
   4199 	}
   4200 
   4201 	virtual long Cleanup()
   4202 	{
   4203 		glDisableVertexAttribArray(0);
   4204 		glUseProgram(0);
   4205 		glDeleteProgram(_program);
   4206 		glDeleteVertexArrays(1, &_vao);
   4207 		glDeleteBuffers(1, &_buffer);
   4208 		glDeleteBuffers(1, &_ebo);
   4209 		glDeleteBuffers(1, &_bufferIndirect);
   4210 		return NO_ERROR;
   4211 	}
   4212 
   4213 	CPrimitiveMode(TDrawFunction drawFunc, GLenum primitiveType, unsigned int sizeX = -1, unsigned sizeY = -1)
   4214 		: _drawFunc(drawFunc)
   4215 		, _primitiveType(primitiveType)
   4216 		, _drawSizeX(sizeX)
   4217 		, _drawSizeY(sizeY)
   4218 		, _sizeX(0)
   4219 		, _sizeY(0)
   4220 		, _program(0)
   4221 		, _vao(0)
   4222 		, _buffer(0)
   4223 		, _ebo(0)
   4224 		, _bufferIndirect(0)
   4225 	{
   4226 	}
   4227 
   4228 private:
   4229 	TDrawFunction _drawFunc;
   4230 	GLenum		  _primitiveType;
   4231 	unsigned int  _drawSizeX, _drawSizeY; //dims for primitive generator
   4232 	unsigned int  _sizeX, _sizeY;		  //rendering size
   4233 	GLuint		  _program;
   4234 	GLuint		  _vao, _buffer, _ebo, _bufferIndirect;
   4235 
   4236 	CPrimitiveMode();
   4237 };
   4238 
   4239 template <typename api>
   4240 class CModeDrawArraysPoints : public CPrimitiveMode
   4241 {
   4242 public:
   4243 	virtual std::string Title()
   4244 	{
   4245 		return "glDrawArraysIndirect mode: GL_POINTS";
   4246 	}
   4247 
   4248 	virtual std::string Purpose()
   4249 	{
   4250 		return "Verify that glDrawArraysIndirect with GL_POINTS works correctly";
   4251 	}
   4252 
   4253 	virtual std::string Method()
   4254 	{
   4255 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4256 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   4257 	}
   4258 
   4259 	virtual std::string PassCriteria()
   4260 	{
   4261 		return "The test will pass if no OpenGL errors reported";
   4262 	}
   4263 
   4264 	CModeDrawArraysPoints() : CPrimitiveMode(DRAW_ARRAYS, GL_POINTS)
   4265 	{
   4266 	}
   4267 
   4268 	virtual long Run()
   4269 	{
   4270 		return CPrimitiveMode::Run<api>(true);
   4271 	}
   4272 };
   4273 
   4274 template <typename api>
   4275 class CModeDrawArraysLines : public CPrimitiveMode
   4276 {
   4277 public:
   4278 	virtual std::string Title()
   4279 	{
   4280 		return "glDrawArraysIndirect mode: GL_LINES";
   4281 	}
   4282 
   4283 	virtual std::string Purpose()
   4284 	{
   4285 		return "Verify that glDrawArraysIndirect with GL_LINES works correctly";
   4286 	}
   4287 
   4288 	virtual std::string Method()
   4289 	{
   4290 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4291 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   4292 	}
   4293 
   4294 	virtual std::string PassCriteria()
   4295 	{
   4296 		return "The test will pass if no OpenGL errors reported";
   4297 	}
   4298 
   4299 	CModeDrawArraysLines() : CPrimitiveMode(DRAW_ARRAYS, GL_LINES)
   4300 	{
   4301 	}
   4302 
   4303 	virtual long Run()
   4304 	{
   4305 		return CPrimitiveMode::Run<api>();
   4306 	}
   4307 };
   4308 
   4309 template <typename api>
   4310 class CModeDrawArraysLineStrip : public CPrimitiveMode
   4311 {
   4312 public:
   4313 	virtual std::string Title()
   4314 	{
   4315 		return "glDrawArraysIndirect mode: GL_LINE_STRIP";
   4316 	}
   4317 
   4318 	virtual std::string Purpose()
   4319 	{
   4320 		return "Verify that glDrawArraysIndirect with GL_LINE_STRIP works correctly";
   4321 	}
   4322 
   4323 	virtual std::string Method()
   4324 	{
   4325 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4326 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   4327 	}
   4328 
   4329 	virtual std::string PassCriteria()
   4330 	{
   4331 		return "The test will pass if no OpenGL errors reported";
   4332 	}
   4333 
   4334 	CModeDrawArraysLineStrip() : CPrimitiveMode(DRAW_ARRAYS, GL_LINE_STRIP)
   4335 	{
   4336 	}
   4337 	virtual long Run()
   4338 	{
   4339 		return CPrimitiveMode::Run<api>();
   4340 	}
   4341 };
   4342 
   4343 template <typename api>
   4344 class CModeDrawArraysLineLoop : public CPrimitiveMode
   4345 {
   4346 public:
   4347 	virtual std::string Title()
   4348 	{
   4349 		return "glDrawArraysIndirect mode: GL_LINE_LOOP";
   4350 	}
   4351 
   4352 	virtual std::string Purpose()
   4353 	{
   4354 		return "Verify that glDrawArraysIndirect with GL_LINE_LOOP works correctly";
   4355 	}
   4356 
   4357 	virtual std::string Method()
   4358 	{
   4359 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4360 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   4361 	}
   4362 
   4363 	virtual std::string PassCriteria()
   4364 	{
   4365 		return "The test will pass if no OpenGL errors reported";
   4366 	}
   4367 
   4368 	CModeDrawArraysLineLoop() : CPrimitiveMode(DRAW_ARRAYS, GL_LINE_LOOP)
   4369 	{
   4370 	}
   4371 
   4372 	virtual long Run()
   4373 	{
   4374 		return CPrimitiveMode::Run<api>();
   4375 	}
   4376 };
   4377 
   4378 template <typename api>
   4379 class CModeDrawArraysTriangleStrip : public CPrimitiveMode
   4380 {
   4381 public:
   4382 	virtual std::string Title()
   4383 	{
   4384 		return "glDrawArraysIndirect mode: GL_TRIANGLE_STRIP";
   4385 	}
   4386 
   4387 	virtual std::string Purpose()
   4388 	{
   4389 		return "Verify that glDrawArraysIndirect with GL_TRIANGLE_STRIP works correctly";
   4390 	}
   4391 
   4392 	virtual std::string Method()
   4393 	{
   4394 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4395 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   4396 	}
   4397 
   4398 	virtual std::string PassCriteria()
   4399 	{
   4400 		return "The test will pass if no OpenGL errors reported";
   4401 	}
   4402 
   4403 	CModeDrawArraysTriangleStrip() : CPrimitiveMode(DRAW_ARRAYS, GL_TRIANGLE_STRIP, 2, 2)
   4404 	{
   4405 	}
   4406 
   4407 	virtual long Run()
   4408 	{
   4409 		return CPrimitiveMode::Run<api>();
   4410 	}
   4411 };
   4412 
   4413 template <typename api>
   4414 class CModeDrawArraysTriangleFan : public CPrimitiveMode
   4415 {
   4416 public:
   4417 	virtual std::string Title()
   4418 	{
   4419 		return "glDrawArraysIndirect mode: GL_TRIANGLE_FAN";
   4420 	}
   4421 
   4422 	virtual std::string Purpose()
   4423 	{
   4424 		return "Verify that glDrawArraysIndirect with GL_TRIANGLE_FAN works correctly";
   4425 	}
   4426 
   4427 	virtual std::string Method()
   4428 	{
   4429 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4430 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   4431 	}
   4432 
   4433 	virtual std::string PassCriteria()
   4434 	{
   4435 		return "The test will pass if no OpenGL errors reported";
   4436 	}
   4437 
   4438 	CModeDrawArraysTriangleFan() : CPrimitiveMode(DRAW_ARRAYS, GL_TRIANGLE_FAN, 2, 2)
   4439 	{
   4440 	}
   4441 
   4442 	virtual long Run()
   4443 	{
   4444 		return CPrimitiveMode::Run<api>();
   4445 	}
   4446 };
   4447 
   4448 template <typename api>
   4449 class CModeDrawArraysLinesAdjacency : public CPrimitiveMode
   4450 {
   4451 public:
   4452 	virtual std::string Title()
   4453 	{
   4454 		return "glDrawArraysIndirect mode: GL_LINES_ADJACENCY";
   4455 	}
   4456 
   4457 	virtual std::string Purpose()
   4458 	{
   4459 		return "Verify that glDrawArraysIndirect with GL_LINES_ADJACENCY works correctly";
   4460 	}
   4461 
   4462 	virtual std::string Method()
   4463 	{
   4464 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4465 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   4466 	}
   4467 
   4468 	virtual std::string PassCriteria()
   4469 	{
   4470 		return "The test will pass if no OpenGL errors reported";
   4471 	}
   4472 
   4473 	CModeDrawArraysLinesAdjacency() : CPrimitiveMode(DRAW_ARRAYS, GL_LINES_ADJACENCY)
   4474 	{
   4475 	}
   4476 
   4477 	virtual long Run()
   4478 	{
   4479 		if (!IsGeometryShaderSupported<api>())
   4480 			return NOT_SUPPORTED;
   4481 		return CPrimitiveMode::Run<api>();
   4482 	}
   4483 };
   4484 
   4485 template <typename api>
   4486 class CModeDrawArraysLineStripAdjacency : public CPrimitiveMode
   4487 {
   4488 public:
   4489 	virtual std::string Title()
   4490 	{
   4491 		return "glDrawArraysIndirect mode: GL_LINE_STRIP_ADJACENCY";
   4492 	}
   4493 
   4494 	virtual std::string Purpose()
   4495 	{
   4496 		return "Verify that glDrawArraysIndirect with GL_LINE_STRIP_ADJACENCY works correctly";
   4497 	}
   4498 
   4499 	virtual std::string Method()
   4500 	{
   4501 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4502 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   4503 	}
   4504 
   4505 	virtual std::string PassCriteria()
   4506 	{
   4507 		return "The test will pass if no OpenGL errors reported";
   4508 	}
   4509 
   4510 	CModeDrawArraysLineStripAdjacency() : CPrimitiveMode(DRAW_ARRAYS, GL_LINE_STRIP_ADJACENCY)
   4511 	{
   4512 	}
   4513 
   4514 	virtual long Run()
   4515 	{
   4516 		if (!IsGeometryShaderSupported<api>())
   4517 			return NOT_SUPPORTED;
   4518 		return CPrimitiveMode::Run<api>();
   4519 	}
   4520 };
   4521 
   4522 template <typename api>
   4523 class CModeDrawArraysTrianglesAdjacency : public CPrimitiveMode
   4524 {
   4525 public:
   4526 	virtual std::string Title()
   4527 	{
   4528 		return "glDrawArraysIndirect mode: GL_TRIANGLES_ADJACENCY";
   4529 	}
   4530 
   4531 	virtual std::string Purpose()
   4532 	{
   4533 		return "Verify that glDrawArraysIndirect with GL_TRIANGLES_ADJACENCY works correctly";
   4534 	}
   4535 
   4536 	virtual std::string Method()
   4537 	{
   4538 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4539 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   4540 	}
   4541 
   4542 	virtual std::string PassCriteria()
   4543 	{
   4544 		return "The test will pass if no OpenGL errors reported";
   4545 	}
   4546 
   4547 	CModeDrawArraysTrianglesAdjacency() : CPrimitiveMode(DRAW_ARRAYS, GL_TRIANGLES_ADJACENCY, 4, 4)
   4548 	{
   4549 	}
   4550 
   4551 	virtual long Run()
   4552 	{
   4553 		if (!IsGeometryShaderSupported<api>())
   4554 			return NOT_SUPPORTED;
   4555 		return CPrimitiveMode::Run<api>();
   4556 	}
   4557 };
   4558 
   4559 template <typename api>
   4560 class CModeDrawArraysTriangleStripAdjacency : public CPrimitiveMode
   4561 {
   4562 public:
   4563 	virtual std::string Title()
   4564 	{
   4565 		return "glDrawArraysIndirect mode: GL_TRIANGLE_STRIP_ADJACENCY";
   4566 	}
   4567 
   4568 	virtual std::string Purpose()
   4569 	{
   4570 		return "Verify that glDrawArraysIndirect with GL_TRIANGLE_STRIP_ADJACENCY works correctly";
   4571 	}
   4572 
   4573 	virtual std::string Method()
   4574 	{
   4575 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4576 			   "3. Draw primitives using glDrawArraysIndirect" NL "4. Verify results";
   4577 	}
   4578 
   4579 	virtual std::string PassCriteria()
   4580 	{
   4581 		return "The test will pass if no OpenGL errors reported";
   4582 	}
   4583 
   4584 	CModeDrawArraysTriangleStripAdjacency() : CPrimitiveMode(DRAW_ARRAYS, GL_TRIANGLE_STRIP_ADJACENCY, 4, 4)
   4585 	{
   4586 	}
   4587 	virtual long Run()
   4588 	{
   4589 		if (!IsGeometryShaderSupported<api>())
   4590 			return NOT_SUPPORTED;
   4591 		return CPrimitiveMode::Run<api>();
   4592 	}
   4593 };
   4594 
   4595 template <typename api>
   4596 class CModeDrawElementsPoints : public CPrimitiveMode
   4597 {
   4598 public:
   4599 	virtual std::string Title()
   4600 	{
   4601 		return "glDrawElementsIndirect mode: GL_POINTS";
   4602 	}
   4603 
   4604 	virtual std::string Purpose()
   4605 	{
   4606 		return "Verify that glDrawElementsIndirect with GL_POINTS works correctly";
   4607 	}
   4608 
   4609 	virtual std::string Method()
   4610 	{
   4611 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4612 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   4613 	}
   4614 
   4615 	virtual std::string PassCriteria()
   4616 	{
   4617 		return "The test will pass if no OpenGL errors reported";
   4618 	}
   4619 
   4620 	CModeDrawElementsPoints() : CPrimitiveMode(DRAW_ELEMENTS, GL_POINTS)
   4621 	{
   4622 	}
   4623 
   4624 	virtual long Run()
   4625 	{
   4626 		return CPrimitiveMode::Run<api>(true);
   4627 	}
   4628 };
   4629 
   4630 template <typename api>
   4631 class CModeDrawElementsLines : public CPrimitiveMode
   4632 {
   4633 public:
   4634 	virtual std::string Title()
   4635 	{
   4636 		return "glDrawElementsIndirect mode: GL_LINES";
   4637 	}
   4638 
   4639 	virtual std::string Purpose()
   4640 	{
   4641 		return "Verify that glDrawElementsIndirect with GL_LINES works correctly";
   4642 	}
   4643 
   4644 	virtual std::string Method()
   4645 	{
   4646 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4647 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   4648 	}
   4649 
   4650 	virtual std::string PassCriteria()
   4651 	{
   4652 		return "The test will pass if no OpenGL errors reported";
   4653 	}
   4654 
   4655 	CModeDrawElementsLines() : CPrimitiveMode(DRAW_ELEMENTS, GL_LINES)
   4656 	{
   4657 	}
   4658 	virtual long Run()
   4659 	{
   4660 		return CPrimitiveMode::Run<api>();
   4661 	}
   4662 };
   4663 
   4664 template <typename api>
   4665 class CModeDrawElementsLineStrip : public CPrimitiveMode
   4666 {
   4667 public:
   4668 	virtual std::string Title()
   4669 	{
   4670 		return "glDrawElementsIndirect mode: GL_LINE_STRIP";
   4671 	}
   4672 
   4673 	virtual std::string Purpose()
   4674 	{
   4675 		return "Verify that glDrawElementsIndirect with GL_LINE_STRIP works correctly";
   4676 	}
   4677 
   4678 	virtual std::string Method()
   4679 	{
   4680 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4681 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   4682 	}
   4683 
   4684 	virtual std::string PassCriteria()
   4685 	{
   4686 		return "The test will pass if no OpenGL errors reported";
   4687 	}
   4688 
   4689 	CModeDrawElementsLineStrip() : CPrimitiveMode(DRAW_ELEMENTS, GL_LINE_STRIP)
   4690 	{
   4691 	}
   4692 	virtual long Run()
   4693 	{
   4694 		return CPrimitiveMode::Run<api>();
   4695 	}
   4696 };
   4697 
   4698 template <typename api>
   4699 class CModeDrawElementsLineLoop : public CPrimitiveMode
   4700 {
   4701 public:
   4702 	virtual std::string Title()
   4703 	{
   4704 		return "glDrawElementsIndirect mode: GL_LINE_LOOP";
   4705 	}
   4706 
   4707 	virtual std::string Purpose()
   4708 	{
   4709 		return "Verify that glDrawElementsIndirect with GL_LINE_LOOP works correctly";
   4710 	}
   4711 
   4712 	virtual std::string Method()
   4713 	{
   4714 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4715 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   4716 	}
   4717 
   4718 	virtual std::string PassCriteria()
   4719 	{
   4720 		return "The test will pass if no OpenGL errors reported";
   4721 	}
   4722 
   4723 	CModeDrawElementsLineLoop() : CPrimitiveMode(DRAW_ELEMENTS, GL_LINE_LOOP)
   4724 	{
   4725 	}
   4726 	virtual long Run()
   4727 	{
   4728 		return CPrimitiveMode::Run<api>();
   4729 	}
   4730 };
   4731 
   4732 template <typename api>
   4733 class CModeDrawElementsTriangleStrip : public CPrimitiveMode
   4734 {
   4735 public:
   4736 	virtual std::string Title()
   4737 	{
   4738 		return "glDrawElementsIndirect mode: GL_TRIANGLE_STRIP";
   4739 	}
   4740 
   4741 	virtual std::string Purpose()
   4742 	{
   4743 		return "Verify that glDrawElementsIndirect with GL_TRIANGLE_STRIP works correctly";
   4744 	}
   4745 
   4746 	virtual std::string Method()
   4747 	{
   4748 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4749 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   4750 	}
   4751 
   4752 	virtual std::string PassCriteria()
   4753 	{
   4754 		return "The test will pass if no OpenGL errors reported";
   4755 	}
   4756 
   4757 	CModeDrawElementsTriangleStrip() : CPrimitiveMode(DRAW_ELEMENTS, GL_TRIANGLE_STRIP, 2, 2)
   4758 	{
   4759 	}
   4760 	virtual long Run()
   4761 	{
   4762 		return CPrimitiveMode::Run<api>();
   4763 	}
   4764 };
   4765 
   4766 template <typename api>
   4767 class CModeDrawElementsTriangleFan : public CPrimitiveMode
   4768 {
   4769 public:
   4770 	virtual std::string Title()
   4771 	{
   4772 		return "glDrawElementsIndirect mode: GL_TRIANGLE_FAN";
   4773 	}
   4774 
   4775 	virtual std::string Purpose()
   4776 	{
   4777 		return "Verify that glDrawElementsIndirect with GL_TRIANGLE_FAN works correctly";
   4778 	}
   4779 
   4780 	virtual std::string Method()
   4781 	{
   4782 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4783 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   4784 	}
   4785 
   4786 	virtual std::string PassCriteria()
   4787 	{
   4788 		return "The test will pass if no OpenGL errors reported";
   4789 	}
   4790 
   4791 	CModeDrawElementsTriangleFan() : CPrimitiveMode(DRAW_ELEMENTS, GL_TRIANGLE_FAN, 2, 2)
   4792 	{
   4793 	}
   4794 	virtual long Run()
   4795 	{
   4796 		return CPrimitiveMode::Run<api>();
   4797 	}
   4798 };
   4799 
   4800 template <typename api>
   4801 class CModeDrawElementsLinesAdjacency : public CPrimitiveMode
   4802 {
   4803 public:
   4804 	virtual std::string Title()
   4805 	{
   4806 		return "glDrawElementsIndirect mode: GL_LINES_ADJACENCY";
   4807 	}
   4808 
   4809 	virtual std::string Purpose()
   4810 	{
   4811 		return "Verify that glDrawElementsIndirect with GL_LINES_ADJACENCY works correctly";
   4812 	}
   4813 
   4814 	virtual std::string Method()
   4815 	{
   4816 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4817 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   4818 	}
   4819 
   4820 	virtual std::string PassCriteria()
   4821 	{
   4822 		return "The test will pass if no OpenGL errors reported";
   4823 	}
   4824 
   4825 	CModeDrawElementsLinesAdjacency() : CPrimitiveMode(DRAW_ELEMENTS, GL_LINES_ADJACENCY)
   4826 	{
   4827 	}
   4828 	virtual long Run()
   4829 	{
   4830 		if (!IsGeometryShaderSupported<api>())
   4831 			return NOT_SUPPORTED;
   4832 		return CPrimitiveMode::Run<api>();
   4833 	}
   4834 };
   4835 
   4836 template <typename api>
   4837 class CModeDrawElementsLineStripAdjacency : public CPrimitiveMode
   4838 {
   4839 public:
   4840 	virtual std::string Title()
   4841 	{
   4842 		return "glDrawElementsIndirect mode: GL_LINE_STRIP_ADJACENCY";
   4843 	}
   4844 
   4845 	virtual std::string Purpose()
   4846 	{
   4847 		return "Verify that glDrawElementsIndirect with GL_LINE_STRIP_ADJACENCY works correctly";
   4848 	}
   4849 
   4850 	virtual std::string Method()
   4851 	{
   4852 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4853 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   4854 	}
   4855 
   4856 	virtual std::string PassCriteria()
   4857 	{
   4858 		return "The test will pass if no OpenGL errors reported";
   4859 	}
   4860 
   4861 	CModeDrawElementsLineStripAdjacency() : CPrimitiveMode(DRAW_ELEMENTS, GL_LINE_STRIP_ADJACENCY)
   4862 	{
   4863 	}
   4864 	virtual long Run()
   4865 	{
   4866 		if (!IsGeometryShaderSupported<api>())
   4867 			return NOT_SUPPORTED;
   4868 		return CPrimitiveMode::Run<api>();
   4869 	}
   4870 };
   4871 
   4872 template <typename api>
   4873 class CModeDrawElementsTrianglesAdjacency : public CPrimitiveMode
   4874 {
   4875 public:
   4876 	virtual std::string Title()
   4877 	{
   4878 		return "glDrawElementsIndirect mode: GL_TRIANGLES_ADJACENCY";
   4879 	}
   4880 
   4881 	virtual std::string Purpose()
   4882 	{
   4883 		return "Verify that glDrawElementsIndirect with GL_TRIANGLES_ADJACENCY works correctly";
   4884 	}
   4885 
   4886 	virtual std::string Method()
   4887 	{
   4888 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4889 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   4890 	}
   4891 
   4892 	virtual std::string PassCriteria()
   4893 	{
   4894 		return "The test will pass if no OpenGL errors reported";
   4895 	}
   4896 
   4897 	CModeDrawElementsTrianglesAdjacency() : CPrimitiveMode(DRAW_ELEMENTS, GL_TRIANGLES_ADJACENCY, 4, 4)
   4898 	{
   4899 	}
   4900 	virtual long Run()
   4901 	{
   4902 		if (!IsGeometryShaderSupported<api>())
   4903 			return NOT_SUPPORTED;
   4904 		return CPrimitiveMode::Run<api>();
   4905 	}
   4906 };
   4907 
   4908 template <typename api>
   4909 class CModeDrawElementsTriangleStripAdjacency : public CPrimitiveMode
   4910 {
   4911 public:
   4912 	virtual std::string Title()
   4913 	{
   4914 		return "glDrawElementsIndirect mode: GL_TRIANGLE_STRIP_ADJACENCY";
   4915 	}
   4916 
   4917 	virtual std::string Purpose()
   4918 	{
   4919 		return "Verify that glDrawElementsIndirect with GL_TRIANGLE_STRIP_ADJACENCY works correctly";
   4920 	}
   4921 
   4922 	virtual std::string Method()
   4923 	{
   4924 		return "1. Create and fill VBO" NL "2. Create indirect buffer" NL
   4925 			   "3. Draw primitives using glDrawElementsIndirect" NL "4. Verify results";
   4926 	}
   4927 
   4928 	virtual std::string PassCriteria()
   4929 	{
   4930 		return "The test will pass if no OpenGL errors reported";
   4931 	}
   4932 
   4933 	CModeDrawElementsTriangleStripAdjacency() : CPrimitiveMode(DRAW_ELEMENTS, GL_TRIANGLE_STRIP_ADJACENCY, 4, 4)
   4934 	{
   4935 	}
   4936 	virtual long Run()
   4937 	{
   4938 		if (!IsGeometryShaderSupported<api>())
   4939 			return NOT_SUPPORTED;
   4940 		return CPrimitiveMode::Run<api>();
   4941 	}
   4942 };
   4943 
   4944 class CTransformFeedback : public DrawIndirectBase
   4945 {
   4946 public:
   4947 	virtual long Setup()
   4948 	{
   4949 		glClear(GL_COLOR_BUFFER_BIT);
   4950 		return NO_ERROR;
   4951 	}
   4952 
   4953 	template <typename api>
   4954 	long Run()
   4955 	{
   4956 		CColorArray coords;
   4957 		PrimitiveGen(GL_TRIANGLE_STRIP, 8, 8, coords);
   4958 
   4959 		glClear(GL_COLOR_BUFFER_BIT);
   4960 
   4961 		_program				 = CreateProgram(Vsh<api>(), "", shaders::fshSimple<api>(), false);
   4962 		const GLchar* varyings[] = { "dataOut" };
   4963 		glTransformFeedbackVaryings(_program, 1, varyings, GL_INTERLEAVED_ATTRIBS);
   4964 		glLinkProgram(_program);
   4965 		if (!CheckProgram(_program))
   4966 		{
   4967 			return ERROR;
   4968 		}
   4969 		glUseProgram(_program);
   4970 
   4971 		glGenBuffers(1, &_vbo);
   4972 		glBindBuffer(GL_ARRAY_BUFFER, _vbo);
   4973 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STATIC_DRAW);
   4974 
   4975 		glGenBuffers(1, &_ubo);
   4976 		glBindBuffer(GL_UNIFORM_BUFFER, _ubo);
   4977 		glBufferData(GL_UNIFORM_BUFFER, 4 * 5 * sizeof(GLuint), NULL, GL_STATIC_DRAW);
   4978 		glBindBufferBase(GL_UNIFORM_BUFFER, glGetUniformBlockIndex(_program, "BLOCK"), _ubo);
   4979 		std::vector<GLuint> uboData;
   4980 
   4981 		switch (_drawFunc)
   4982 		{
   4983 		case DRAW_ARRAYS:
   4984 		{
   4985 			uboData.resize(4 * 4, 0);
   4986 
   4987 			uboData[0]  = static_cast<GLuint>(coords.size()); //count
   4988 			uboData[4]  = 1;								  //primcount
   4989 			uboData[8]  = 0;								  //first
   4990 			uboData[12] = 0;								  //mbz
   4991 		}
   4992 		break;
   4993 		case DRAW_ELEMENTS:
   4994 		{
   4995 			uboData.resize(4 * 5, 0);
   4996 			uboData[0]  = static_cast<GLuint>(coords.size()); //count
   4997 			uboData[4]  = 1;								  //primcount
   4998 			uboData[8]  = 0;								  //firstindex
   4999 			uboData[12] = 0;								  //basevertex
   5000 			uboData[16] = 0;								  //mbz
   5001 		}
   5002 		break;
   5003 		default:
   5004 			throw std::runtime_error("Unknown draw function!");
   5005 			break;
   5006 		}
   5007 		glBufferSubData(GL_UNIFORM_BUFFER, 0, (GLsizeiptr)(uboData.size() * sizeof(uboData[0])), &uboData[0]);
   5008 
   5009 		glGenVertexArrays(1, &_vao);
   5010 		glBindVertexArray(_vao);
   5011 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   5012 		glEnableVertexAttribArray(0);
   5013 
   5014 		CElementArray elements(coords.size(), 0);
   5015 		for (size_t i = 0; i < elements.size(); ++i)
   5016 		{
   5017 			elements[i] = static_cast<GLuint>(i);
   5018 		}
   5019 
   5020 		glGenBuffers(1, &_ebo);
   5021 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   5022 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   5023 					 GL_STATIC_DRAW);
   5024 
   5025 		glGenBuffers(1, &_bufferIndirect);
   5026 
   5027 		glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, _bufferIndirect);
   5028 		GLuint zeroes[] = { 0, 0, 0, 0, 0 };
   5029 		glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(zeroes), zeroes, GL_DYNAMIC_DRAW);
   5030 		glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, _bufferIndirect);
   5031 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   5032 
   5033 		glEnable(GL_RASTERIZER_DISCARD);
   5034 		glBeginTransformFeedback(GL_POINTS);
   5035 		glDrawArrays(GL_POINTS, 0, 5);
   5036 		glEndTransformFeedback();
   5037 		glDisable(GL_RASTERIZER_DISCARD);
   5038 
   5039 		switch (_drawFunc)
   5040 		{
   5041 		case DRAW_ARRAYS:
   5042 			glDrawArraysIndirect(GL_TRIANGLES, 0);
   5043 			break;
   5044 		case DRAW_ELEMENTS:
   5045 			glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   5046 
   5047 			break;
   5048 		default:
   5049 			throw std::runtime_error("Unknown draw function!");
   5050 			break;
   5051 		}
   5052 
   5053 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   5054 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   5055 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   5056 
   5057 		DIResult result;
   5058 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   5059 										 getWindowHeight()));
   5060 
   5061 		return result.code();
   5062 	}
   5063 
   5064 	virtual long Cleanup()
   5065 	{
   5066 		glDisableVertexAttribArray(0);
   5067 		glBindBuffer(GL_ARRAY_BUFFER, 0);
   5068 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
   5069 		glBindVertexArray(0);
   5070 		glUseProgram(0);
   5071 
   5072 		if (_vao)
   5073 		{
   5074 			glDeleteVertexArrays(1, &_vao);
   5075 		}
   5076 		if (_vbo)
   5077 		{
   5078 			glDeleteBuffers(1, &_vbo);
   5079 		}
   5080 		if (_ebo)
   5081 		{
   5082 			glDeleteBuffers(1, &_ebo);
   5083 		}
   5084 		if (_ubo)
   5085 		{
   5086 			glDeleteBuffers(1, &_ubo);
   5087 		}
   5088 		if (_bufferIndirect)
   5089 		{
   5090 			glDeleteBuffers(1, &_bufferIndirect);
   5091 		}
   5092 		if (_program)
   5093 		{
   5094 			glDeleteProgram(_program);
   5095 		}
   5096 		return NO_ERROR;
   5097 	}
   5098 
   5099 	CTransformFeedback(TDrawFunction drawFunc)
   5100 		: _drawFunc(drawFunc), _program(0), _vao(0), _vbo(0), _ebo(0), _ubo(0), _bufferIndirect(0)
   5101 	{
   5102 	}
   5103 
   5104 private:
   5105 	TDrawFunction _drawFunc;
   5106 	GLuint		  _program;
   5107 	GLuint		  _vao, _vbo, _ebo, _ubo, _bufferIndirect;
   5108 
   5109 	CTransformFeedback();
   5110 
   5111 	template <typename api>
   5112 	std::string Vsh()
   5113 	{
   5114 		return api::glslVer() + NL "flat out highp uint dataOut;" NL "in vec4 i_vertex;" NL
   5115 								   "layout(std140) uniform  BLOCK {" NL " uint m[5];" NL "} b;" NL "void main() {" NL
   5116 								   "  dataOut = b.m[min(4, gl_VertexID)];" NL "    gl_Position = i_vertex;" NL "}";
   5117 	}
   5118 };
   5119 
   5120 template <typename api>
   5121 struct CTransformFeedbackArray : public CTransformFeedback
   5122 {
   5123 	virtual std::string Title()
   5124 	{
   5125 		return "Transform feedback: glDrawArrayIndirect";
   5126 	}
   5127 
   5128 	virtual std::string Purpose()
   5129 	{
   5130 		return "Verify that transform feedback works correctly with glDrawArrayIndirect";
   5131 	}
   5132 
   5133 	virtual std::string Method()
   5134 	{
   5135 		return "1. Create data" NL "2. Use data as input to glDrawArrayIndirect" NL "3. Verify results";
   5136 	}
   5137 
   5138 	virtual std::string PassCriteria()
   5139 	{
   5140 		return "The test will pass if no OpenGL errors reported";
   5141 	}
   5142 
   5143 	CTransformFeedbackArray() : CTransformFeedback(DRAW_ARRAYS)
   5144 	{
   5145 	}
   5146 
   5147 	virtual long Run()
   5148 	{
   5149 		return CTransformFeedback::Run<api>();
   5150 	}
   5151 };
   5152 
   5153 template <typename api>
   5154 struct CTransformFeedbackElements : public CTransformFeedback
   5155 {
   5156 	virtual std::string Title()
   5157 	{
   5158 		return "Transform feedback: glDrawElementsIndirect";
   5159 	}
   5160 
   5161 	virtual std::string Purpose()
   5162 	{
   5163 		return "Verify that transform feedback works correctly with glDrawElementsIndirect";
   5164 	}
   5165 
   5166 	virtual std::string Method()
   5167 	{
   5168 		return "1. Create data" NL "2. Use data as input to glDrawElementsIndirect" NL "3. Verify results";
   5169 	}
   5170 
   5171 	virtual std::string PassCriteria()
   5172 	{
   5173 		return "The test will pass if no OpenGL errors reported";
   5174 	}
   5175 
   5176 	CTransformFeedbackElements() : CTransformFeedback(DRAW_ELEMENTS)
   5177 	{
   5178 	}
   5179 
   5180 	virtual long Run()
   5181 	{
   5182 		return CTransformFeedback::Run<api>();
   5183 	}
   5184 };
   5185 
   5186 class CComputeBase : public DrawIndirectBase
   5187 {
   5188 public:
   5189 	virtual long Setup()
   5190 	{
   5191 		glClear(GL_COLOR_BUFFER_BIT);
   5192 		return NO_ERROR;
   5193 	}
   5194 
   5195 	template <typename api>
   5196 	long Run()
   5197 	{
   5198 
   5199 		int width, height;
   5200 		glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &width);
   5201 		glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &height);
   5202 
   5203 		width  = std::min(width, getWindowWidth());
   5204 		height = std::min(height, getWindowHeight());
   5205 
   5206 		glViewport(0, 0, width, height);
   5207 
   5208 		CColorArray coords(width * height, tcu::Vec4(0));
   5209 		CColorArray colors(width * height, tcu::Vec4(0));
   5210 
   5211 		_program = CreateProgram(Vsh<api>(), "", Fsh<api>(), false);
   5212 		glBindAttribLocation(_program, 0, "in_coords");
   5213 		glBindAttribLocation(_program, 1, "in_colors");
   5214 		glLinkProgram(_program);
   5215 		if (!CheckProgram(_program))
   5216 		{
   5217 			return ERROR;
   5218 		}
   5219 		glUseProgram(_program);
   5220 
   5221 		glGenVertexArrays(1, &_vao);
   5222 		glBindVertexArray(_vao);
   5223 
   5224 		glGenBuffers(1, &_bufferCoords);
   5225 		glBindBuffer(GL_ARRAY_BUFFER, _bufferCoords);
   5226 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), 0, GL_STREAM_DRAW);
   5227 
   5228 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), 0);
   5229 		glEnableVertexAttribArray(0);
   5230 
   5231 		glGenBuffers(1, &_bufferColors);
   5232 		glBindBuffer(GL_ARRAY_BUFFER, _bufferColors);
   5233 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(colors.size() * sizeof(colors[0])), 0, GL_STREAM_DRAW);
   5234 
   5235 		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), 0);
   5236 		glEnableVertexAttribArray(1);
   5237 
   5238 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   5239 		DrawArraysIndirectCommand   indirectArrays   = { 0, 0, 0, 0 };
   5240 
   5241 		CElementArray elements(width * height, 0);
   5242 		for (size_t i = 0; i < elements.size(); ++i)
   5243 		{
   5244 			elements[i] = static_cast<GLuint>(i);
   5245 		}
   5246 
   5247 		glGenBuffers(1, &_bufferIndirect);
   5248 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   5249 		switch (_drawFunc)
   5250 		{
   5251 		case DRAW_ARRAYS:
   5252 		{
   5253 			glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW);
   5254 		}
   5255 		break;
   5256 		case DRAW_ELEMENTS:
   5257 		{
   5258 			glGenBuffers(1, &_ebo);
   5259 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   5260 			glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   5261 						 GL_STATIC_DRAW);
   5262 
   5263 			glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements,
   5264 						 GL_STATIC_DRAW);
   5265 		}
   5266 		break;
   5267 		default:
   5268 			throw std::runtime_error("Unknown draw function!");
   5269 			break;
   5270 		}
   5271 
   5272 		_programCompute = CreateComputeProgram(Csh<api>(), false);
   5273 		glLinkProgram(_programCompute);
   5274 		if (!CheckProgram(_programCompute))
   5275 		{
   5276 			return ERROR;
   5277 		}
   5278 		glUseProgram(_programCompute);
   5279 		glUniform1ui(glGetUniformLocation(_programCompute, "width"), width);
   5280 		glUniform1ui(glGetUniformLocation(_programCompute, "height"), height);
   5281 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, _bufferCoords);
   5282 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, _bufferColors);
   5283 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, _bufferIndirect);
   5284 
   5285 		glDispatchCompute(width, height, 1);
   5286 		glMemoryBarrier(GL_COMMAND_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
   5287 
   5288 		glUseProgram(_program);
   5289 
   5290 		switch (_drawFunc)
   5291 		{
   5292 		case DRAW_ARRAYS:
   5293 		{
   5294 			glDrawArraysIndirect(GL_POINTS, 0);
   5295 		}
   5296 		break;
   5297 		case DRAW_ELEMENTS:
   5298 		{
   5299 			glDrawElementsIndirect(GL_POINTS, GL_UNSIGNED_INT, 0);
   5300 		}
   5301 		break;
   5302 		default:
   5303 			throw std::runtime_error("Unknown draw function!");
   5304 			break;
   5305 		}
   5306 
   5307 		CColorArray bufferRef1(width * height / 4, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
   5308 		CColorArray bufferRef2(width * height / 4, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f));
   5309 		CColorArray bufferRef3(width * height / 4, tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f));
   5310 		CColorArray bufferRef4(width * height / 4, tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f));
   5311 		CColorArray bufferTest(width * height / 4, tcu::Vec4(0.0f));
   5312 
   5313 		DIResult result;
   5314 		ReadPixelsFloat<api>(0, 0, width / 2, height / 2, &bufferTest[0]);
   5315 		result.sub_result(BuffersCompare(bufferTest, width / 2, height / 2, bufferRef1, width / 2, height / 2))
   5316 			<< "Region 0 verification failed";
   5317 
   5318 		ReadPixelsFloat<api>((width + 1) / 2, 0, width / 2, height / 2, &bufferTest[0]);
   5319 		result.sub_result(BuffersCompare(bufferTest, width / 2, height / 2, bufferRef2, width / 2, height / 2))
   5320 			<< "Region 1 verification failed";
   5321 
   5322 		ReadPixelsFloat<api>(0, (height + 1) / 2, width / 2, height / 2, &bufferTest[0]);
   5323 		result.sub_result(BuffersCompare(bufferTest, width / 2, height / 2, bufferRef3, width / 2, height / 2))
   5324 			<< "Region 2 verification failed";
   5325 
   5326 		ReadPixelsFloat<api>((width + 1) / 2, (height + 1) / 2, width / 2, height / 2, &bufferTest[0]);
   5327 		result.sub_result(BuffersCompare(bufferTest, width / 2, height / 2, bufferRef4, width / 2, height / 2))
   5328 			<< "Region 3 verification failed";
   5329 
   5330 		return result.code();
   5331 	}
   5332 
   5333 	virtual long Cleanup()
   5334 	{
   5335 		glDisableVertexAttribArray(1);
   5336 		glDisableVertexAttribArray(0);
   5337 		glDeleteProgram(_program);
   5338 		glDeleteProgram(_programCompute);
   5339 		glDeleteVertexArrays(1, &_vao);
   5340 		if (_ebo)
   5341 			glDeleteBuffers(1, &_ebo);
   5342 		glDeleteBuffers(1, &_bufferCoords);
   5343 		glDeleteBuffers(1, &_bufferColors);
   5344 		glDeleteBuffers(1, &_bufferIndirect);
   5345 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
   5346 		return NO_ERROR;
   5347 	}
   5348 	CComputeBase(TDrawFunction drawFunc)
   5349 		: _drawFunc(drawFunc)
   5350 		, _program(0)
   5351 		, _programCompute(0)
   5352 		, _vao(0)
   5353 		, _ebo(0)
   5354 		, _bufferCoords(0)
   5355 		, _bufferColors(0)
   5356 		, _bufferIndirect(0)
   5357 	{
   5358 	}
   5359 
   5360 private:
   5361 	CComputeBase();
   5362 	TDrawFunction _drawFunc;
   5363 
   5364 	template <typename api>
   5365 	std::string Vsh()
   5366 	{
   5367 		return api::glslVer() + NL "in vec4 in_coords;" NL "in vec4 in_colors;" NL "out vec4 colors;" NL
   5368 								   "void main() {" NL "  colors = in_colors;" NL "  gl_Position = in_coords;" NL
   5369 								   "#if defined(GL_ES)" NL "  gl_PointSize = 1.0;" NL "#endif" NL "}";
   5370 	}
   5371 
   5372 	template <typename api>
   5373 	std::string Fsh()
   5374 	{
   5375 		return api::glslVer() + NL "precision highp float;" NL "in vec4 colors;" NL "out vec4 outColor;" NL
   5376 								   "void main() {" NL "  outColor = colors;" NL "}";
   5377 	}
   5378 
   5379 	template <typename api>
   5380 	std::string Csh()
   5381 	{
   5382 		return api::glslVer(true) + NL "precision highp int;                                           " NL
   5383 									   "precision highp float;                                         " NL
   5384 									   "                                                               " NL
   5385 									   "layout(local_size_x = 1) in;                                   " NL
   5386 									   "layout(std430, binding = 0) buffer Vertices {                  " NL
   5387 									   "    vec4 vertices[];                                           " NL
   5388 									   "};                                                             " NL
   5389 									   "layout(std430, binding = 1) buffer Colors {                    " NL
   5390 									   "    vec4 colors[];                                             " NL
   5391 									   "};                                                             " NL
   5392 									   "layout(std430, binding = 2) buffer Indirect {                  " NL
   5393 									   "    uint indirect[4];                                          " NL
   5394 									   "};                                                             " NL
   5395 									   "                                                               " NL
   5396 									   "uniform uint height;                                           " NL
   5397 									   "uniform uint width;                                            " NL
   5398 									   "                                                               " NL
   5399 									   "void main() {                                                  " NL
   5400 									   "    uint w = gl_GlobalInvocationID.x;                          " NL
   5401 									   "    uint h = gl_GlobalInvocationID.y;                          " NL
   5402 									   "    float stepX = 2.0 / float(width);                          " NL
   5403 									   "    float stepY = 2.0 / float(height);                         " NL
   5404 									   "    float offsetX = -1.0 + stepX * float(w) + stepX / 2.0;     " NL
   5405 									   "    float offsetY = -1.0 + stepY * float(h) + stepY / 2.0;     " NL
   5406 									   "    uint arrayOffset = h * width + w;                          " NL
   5407 									   "    vertices[ arrayOffset ] = vec4(offsetX, offsetY, 0.0, 1.0);" NL
   5408 									   "    vec4 color = vec4(0.0, 0.0, 0.0, 1.0);                     " NL
   5409 									   "    if(w > (width / 2u - 1u)) {                                " NL
   5410 									   "        color = color + vec4(0.5, 0.0, 0.0, 0.0);              " NL
   5411 									   "    }                                                          " NL
   5412 									   "    if(h > (height / 2u - 1u)) {                               " NL
   5413 									   "        color = color + vec4(0.0, 0.5, 0.0, 0.0);              " NL
   5414 									   "    }                                                          " NL
   5415 									   "    colors[ arrayOffset ] = color;                             " NL
   5416 									   "    if(w == 0u && h == 0u) {                                   " NL
   5417 									   "        indirect[0] = width * height;                          " NL
   5418 									   "        indirect[1] =  1u;                                     " NL
   5419 									   "    }                                                          " NL
   5420 									   "}                                                              ";
   5421 	}
   5422 
   5423 	GLuint _program, _programCompute;
   5424 	GLuint _vao;
   5425 	GLuint _ebo;
   5426 	GLuint _bufferCoords;
   5427 	GLuint _bufferColors;
   5428 	GLuint _bufferIndirect;
   5429 };
   5430 
   5431 template <typename api>
   5432 struct CComputeShaderArray : public CComputeBase
   5433 {
   5434 	virtual std::string Title()
   5435 	{
   5436 		return "Compute Shader: glDrawArrayIndirect";
   5437 	}
   5438 
   5439 	virtual std::string Purpose()
   5440 	{
   5441 		return "Verify that data created by Compute Shader can be used as an input to glDrawArrayIndirect";
   5442 	}
   5443 
   5444 	virtual std::string Method()
   5445 	{
   5446 		return "1. Create data by Compute Shader" NL "2. Use data as input to glDrawArrayIndirect" NL
   5447 			   "3. Verify results";
   5448 	}
   5449 
   5450 	virtual std::string PassCriteria()
   5451 	{
   5452 		return "The test will pass if no OpenGL errors reported";
   5453 	}
   5454 
   5455 	CComputeShaderArray() : CComputeBase(DRAW_ARRAYS)
   5456 	{
   5457 	}
   5458 
   5459 	virtual long Run()
   5460 	{
   5461 		return CComputeBase::Run<api>();
   5462 	}
   5463 };
   5464 
   5465 template <typename api>
   5466 struct CComputeShaderElements : public CComputeBase
   5467 {
   5468 	virtual std::string Title()
   5469 	{
   5470 		return "Compute Shader: glDrawElementsIndirect";
   5471 	}
   5472 
   5473 	virtual std::string Purpose()
   5474 	{
   5475 		return "Verify that data created by Compute Shader can be used as an input to glDrawElementsIndirect";
   5476 	}
   5477 
   5478 	virtual std::string Method()
   5479 	{
   5480 		return "1. Create data by Compute Shader" NL "2. Use data as input to glDrawElementsIndirect" NL
   5481 			   "3. Verify results";
   5482 	}
   5483 
   5484 	virtual std::string PassCriteria()
   5485 	{
   5486 		return "The test will pass if no OpenGL errors reported";
   5487 	}
   5488 
   5489 	CComputeShaderElements() : CComputeBase(DRAW_ELEMENTS)
   5490 	{
   5491 	}
   5492 
   5493 	virtual long Run()
   5494 	{
   5495 		return CComputeBase::Run<api>();
   5496 	}
   5497 };
   5498 
   5499 template <typename api>
   5500 class CPrimitiveRestartElements : public DrawIndirectBase
   5501 {
   5502 public:
   5503 	virtual std::string Title()
   5504 	{
   5505 		return "Primitive restart - glDrawElementsIndirect";
   5506 	}
   5507 
   5508 	virtual std::string Purpose()
   5509 	{
   5510 		return "Verify that primitive restart works correctly with glDrawElementsIndirect";
   5511 	}
   5512 
   5513 	virtual std::string Method()
   5514 	{
   5515 		return "1. Define primitives using VBO" NL "2. Draw primitives using glDrawElementsIndirect" NL
   5516 			   "3. Verify results";
   5517 	}
   5518 
   5519 	virtual std::string PassCriteria()
   5520 	{
   5521 		return "The test will pass if no OpenGL errors reported";
   5522 	}
   5523 
   5524 	virtual long Setup()
   5525 	{
   5526 		glClear(GL_COLOR_BUFFER_BIT);
   5527 		return NO_ERROR;
   5528 	}
   5529 
   5530 	int PrimitiveRestartIndex();
   5531 
   5532 	void EnablePrimitiveRestart();
   5533 
   5534 	void DisablePrimitiveRestart();
   5535 
   5536 	virtual long Run()
   5537 	{
   5538 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   5539 		if (!_program)
   5540 		{
   5541 			return ERROR;
   5542 		}
   5543 		glUseProgram(_program);
   5544 
   5545 		CColorArray coords1;
   5546 		TriangleStipGen(coords1, -1.0f, 1.0f, -1.0, -0.5, 2);
   5547 
   5548 		CColorArray coords2;
   5549 		TriangleStipGen(coords2, -1.0f, 1.0f, 0.5, 1.0, 4);
   5550 
   5551 		glGenVertexArrays(1, &_vao);
   5552 		glBindVertexArray(_vao);
   5553 
   5554 		glGenBuffers(1, &_buffer);
   5555 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   5556 
   5557 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords1.size() + coords2.size()) * sizeof(coords1[0]), NULL,
   5558 					 GL_STREAM_DRAW);
   5559 		glBufferSubData(GL_ARRAY_BUFFER, 0, (GLsizeiptr)(coords1.size() * sizeof(coords1[0])), &coords1[0]);
   5560 		glBufferSubData(GL_ARRAY_BUFFER, (GLintptr)(coords1.size() * sizeof(coords1[0])),
   5561 						(GLsizeiptr)(coords2.size() * sizeof(coords2[0])), &coords2[0]);
   5562 		glVertexAttribPointer(0, sizeof(coords1[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords1[0]), 0);
   5563 		glEnableVertexAttribArray(0);
   5564 
   5565 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   5566 		indirectElements.count						 = static_cast<GLuint>(coords1.size() + coords2.size() + 1);
   5567 		indirectElements.primCount					 = static_cast<GLuint>((coords1.size() + coords2.size()) / 2);
   5568 
   5569 		CElementArray elements;
   5570 		for (size_t i = 0; i < coords1.size(); ++i)
   5571 		{
   5572 			elements.push_back(static_cast<GLuint>(i));
   5573 		}
   5574 
   5575 		elements.push_back(PrimitiveRestartIndex());
   5576 		for (size_t i = 0; i < coords2.size(); ++i)
   5577 		{
   5578 			elements.push_back(static_cast<GLuint>(coords1.size() + i));
   5579 		}
   5580 
   5581 		glGenBuffers(1, &_bufferIndirect);
   5582 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   5583 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   5584 
   5585 		glGenBuffers(1, &_ebo);
   5586 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   5587 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   5588 					 GL_STATIC_DRAW);
   5589 
   5590 		EnablePrimitiveRestart();
   5591 
   5592 		glDrawElementsIndirect(GL_TRIANGLE_STRIP, GL_UNSIGNED_INT, 0);
   5593 
   5594 		CColorArray bufferRef1(getWindowWidth() * getWindowHeight() / 4, tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   5595 		CColorArray bufferRef2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f));
   5596 		CColorArray bufferTest1(getWindowWidth() * getWindowHeight() / 4, tcu::Vec4(0.0f));
   5597 		CColorArray bufferTest2(getWindowWidth() * getWindowHeight() / 2, tcu::Vec4(0.0f));
   5598 
   5599 		DIResult result;
   5600 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight() / 4, &bufferTest1[0]);
   5601 		result.sub_result(BuffersCompare(bufferTest1, getWindowWidth(), getWindowHeight() / 4, bufferRef1,
   5602 										 getWindowWidth(), getWindowHeight() / 4));
   5603 
   5604 		ReadPixelsFloat<api>(0, (getWindowHeight() + 3) / 4, getWindowWidth(), getWindowHeight() / 2, &bufferTest2[0]);
   5605 		result.sub_result(BuffersCompare(bufferTest2, getWindowWidth(), getWindowHeight() / 2, bufferRef2,
   5606 										 getWindowWidth(), getWindowHeight() / 2));
   5607 
   5608 		ReadPixelsFloat<api>(0, (getWindowHeight() * 3 + 3) / 4, getWindowWidth(), getWindowHeight() / 4,
   5609 							 &bufferTest1[0]);
   5610 		result.sub_result(BuffersCompare(bufferTest1, getWindowWidth(), getWindowHeight() / 4, bufferRef1,
   5611 										 getWindowWidth(), getWindowHeight() / 4));
   5612 
   5613 		return result.code();
   5614 	}
   5615 
   5616 	virtual long Cleanup()
   5617 	{
   5618 
   5619 		DisablePrimitiveRestart();
   5620 		glDisableVertexAttribArray(0);
   5621 		glUseProgram(0);
   5622 		glDeleteProgram(_program);
   5623 		glDeleteVertexArrays(1, &_vao);
   5624 		glDeleteBuffers(1, &_buffer);
   5625 		glDeleteBuffers(1, &_ebo);
   5626 		glDeleteBuffers(1, &_bufferIndirect);
   5627 		return NO_ERROR;
   5628 	}
   5629 
   5630 private:
   5631 	void TriangleStipGen(CColorArray& coords, float widthStart, float widthEnd, float heightStart, float heightEnd,
   5632 						 unsigned int primNum)
   5633 	{
   5634 		float widthStep  = (widthEnd - widthStart) / static_cast<float>(primNum);
   5635 		float heightStep = (heightEnd - heightStart) / static_cast<float>(primNum);
   5636 		for (unsigned int i = 0; i < primNum; ++i)
   5637 		{
   5638 			float heightOffset = heightStart + heightStep * static_cast<float>(i);
   5639 			for (unsigned int j = 0; j < primNum; ++j)
   5640 			{
   5641 				float widthOffset = widthStart + widthStep * static_cast<float>(j);
   5642 
   5643 				coords.push_back(tcu::Vec4(widthOffset, heightOffset, 0.0f, 1.0f));
   5644 				coords.push_back(tcu::Vec4(widthOffset, heightOffset + heightStep, 0.0f, 1.0f));
   5645 				coords.push_back(tcu::Vec4(widthOffset + widthStep, heightOffset, 0.0f, 1.0f));
   5646 				coords.push_back(tcu::Vec4(widthOffset + widthStep, heightOffset + heightStep, 0.0f, 1.0f));
   5647 			}
   5648 		}
   5649 	}
   5650 	GLuint _program;
   5651 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   5652 };
   5653 
   5654 template <>
   5655 int CPrimitiveRestartElements<test_api::ES3>::PrimitiveRestartIndex()
   5656 {
   5657 	return 0xffffffff;
   5658 }
   5659 
   5660 template <>
   5661 int CPrimitiveRestartElements<test_api::GL>::PrimitiveRestartIndex()
   5662 {
   5663 	return 3432432;
   5664 }
   5665 
   5666 template <>
   5667 void CPrimitiveRestartElements<test_api::ES3>::DisablePrimitiveRestart()
   5668 {
   5669 	glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
   5670 }
   5671 
   5672 template <>
   5673 void CPrimitiveRestartElements<test_api::GL>::DisablePrimitiveRestart()
   5674 {
   5675 	glDisable(GL_PRIMITIVE_RESTART);
   5676 }
   5677 
   5678 template <>
   5679 void CPrimitiveRestartElements<test_api::ES3>::EnablePrimitiveRestart()
   5680 {
   5681 	glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
   5682 }
   5683 
   5684 template <>
   5685 void CPrimitiveRestartElements<test_api::GL>::EnablePrimitiveRestart()
   5686 {
   5687 	glPrimitiveRestartIndex(PrimitiveRestartIndex());
   5688 	glEnable(GL_PRIMITIVE_RESTART);
   5689 }
   5690 
   5691 template <typename api>
   5692 class CNonZeroReservedMustBeZeroArray : public DrawIndirectBase
   5693 {
   5694 	virtual std::string Title()
   5695 	{
   5696 		return "non-zero reservedMustBeZero - glDrawArrayIndirect";
   5697 	}
   5698 
   5699 	virtual std::string Purpose()
   5700 	{
   5701 		return "Verify that no driver crash occurred";
   5702 	}
   5703 
   5704 	virtual std::string Method()
   5705 	{
   5706 		return "Call glDrawArrayIndirect with non-zero ReservedMustBeZero";
   5707 	}
   5708 
   5709 	virtual std::string PassCriteria()
   5710 	{
   5711 		return "The test will pass if no OpenGL errors reported and no driver crash occurred";
   5712 	}
   5713 
   5714 	virtual long Setup()
   5715 	{
   5716 		glClear(GL_COLOR_BUFFER_BIT);
   5717 		return NO_ERROR;
   5718 	}
   5719 
   5720 	virtual long Run()
   5721 	{
   5722 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   5723 		if (!_program)
   5724 		{
   5725 			return ERROR;
   5726 		}
   5727 		glUseProgram(_program);
   5728 
   5729 		CColorArray coords;
   5730 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   5731 
   5732 		glGenVertexArrays(1, &_vao);
   5733 		glBindVertexArray(_vao);
   5734 
   5735 		glGenBuffers(1, &_buffer);
   5736 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   5737 
   5738 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   5739 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   5740 		glEnableVertexAttribArray(0);
   5741 
   5742 		DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 };
   5743 		indirectArrays.count					 = static_cast<GLuint>(coords.size());
   5744 		indirectArrays.primCount				 = 1;
   5745 		indirectArrays.first					 = 0;
   5746 		indirectArrays.reservedMustBeZero		 = 2312;
   5747 
   5748 		glGenBuffers(1, &_bufferIndirect);
   5749 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   5750 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW);
   5751 
   5752 		glDrawArraysIndirect(GL_TRIANGLES, 0);
   5753 
   5754 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   5755 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   5756 
   5757 		DIResult result;
   5758 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   5759 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   5760 										 getWindowHeight()));
   5761 
   5762 		return result.code();
   5763 	}
   5764 
   5765 	virtual long Cleanup()
   5766 	{
   5767 		glDisableVertexAttribArray(0);
   5768 		glUseProgram(0);
   5769 		glDeleteProgram(_program);
   5770 		glDeleteVertexArrays(1, &_vao);
   5771 		glDeleteBuffers(1, &_buffer);
   5772 		glDeleteBuffers(1, &_bufferIndirect);
   5773 		return NO_ERROR;
   5774 	}
   5775 
   5776 private:
   5777 	GLuint _program;
   5778 	GLuint _vao, _buffer, _bufferIndirect;
   5779 };
   5780 
   5781 template <typename api>
   5782 struct CNonZeroReservedMustBeZeroElements : public DrawIndirectBase
   5783 {
   5784 	virtual std::string Title()
   5785 	{
   5786 		return "non-zero reservedMustBeZero - glDrawElementsIndirect";
   5787 	}
   5788 
   5789 	virtual std::string Purpose()
   5790 	{
   5791 		return "Verify that no driver crash occurred";
   5792 	}
   5793 
   5794 	virtual std::string Method()
   5795 	{
   5796 		return "Call glDrawElementsIndirect with non-zero ReservedMustBeZero";
   5797 	}
   5798 
   5799 	virtual std::string PassCriteria()
   5800 	{
   5801 		return "The test will pass if no OpenGL errors reported and no driver crash occurred";
   5802 	}
   5803 
   5804 	virtual long Setup()
   5805 	{
   5806 		glClear(GL_COLOR_BUFFER_BIT);
   5807 		return NO_ERROR;
   5808 	}
   5809 
   5810 	virtual long Run()
   5811 	{
   5812 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   5813 		if (!_program)
   5814 		{
   5815 			return ERROR;
   5816 		}
   5817 		glUseProgram(_program);
   5818 
   5819 		CColorArray coords;
   5820 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   5821 
   5822 		glGenVertexArrays(1, &_vao);
   5823 		glBindVertexArray(_vao);
   5824 
   5825 		glGenBuffers(1, &_buffer);
   5826 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   5827 
   5828 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   5829 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   5830 		glEnableVertexAttribArray(0);
   5831 
   5832 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   5833 		indirectElements.count						 = static_cast<GLuint>(coords.size());
   5834 		indirectElements.primCount					 = 1;
   5835 		indirectElements.baseVertex					 = 0;
   5836 		indirectElements.firstIndex					 = 0;
   5837 		indirectElements.reservedMustBeZero			 = 1;
   5838 
   5839 		CElementArray elements(coords.size(), 0);
   5840 		for (size_t i = 0; i < elements.size(); ++i)
   5841 		{
   5842 			elements[i] = static_cast<GLuint>(i);
   5843 		}
   5844 
   5845 		glGenBuffers(1, &_bufferIndirect);
   5846 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   5847 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   5848 
   5849 		glGenBuffers(1, &_ebo);
   5850 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   5851 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   5852 					 GL_STATIC_DRAW);
   5853 
   5854 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   5855 
   5856 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.1f, 0.2f, 0.3f, 1.0f));
   5857 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   5858 
   5859 		DIResult result;
   5860 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   5861 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   5862 										 getWindowHeight()));
   5863 
   5864 		return result.code();
   5865 	}
   5866 
   5867 	virtual long Cleanup()
   5868 	{
   5869 		glDisableVertexAttribArray(0);
   5870 		glUseProgram(0);
   5871 		glDeleteProgram(_program);
   5872 		glDeleteVertexArrays(1, &_vao);
   5873 		glDeleteBuffers(1, &_buffer);
   5874 		glDeleteBuffers(1, &_ebo);
   5875 		glDeleteBuffers(1, &_bufferIndirect);
   5876 		return NO_ERROR;
   5877 	}
   5878 
   5879 private:
   5880 	GLuint _program;
   5881 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   5882 };
   5883 
   5884 template <typename api>
   5885 struct CNegativeZeroBufferArray : public DrawIndirectBase
   5886 {
   5887 	virtual std::string Title()
   5888 	{
   5889 		return "Negative: no indirect buffer/parameter - glDrawArrayIndirect";
   5890 	}
   5891 
   5892 	virtual std::string Purpose()
   5893 	{
   5894 		return "Verify that a driver sets error and no driver crash occurred";
   5895 	}
   5896 
   5897 	virtual std::string Method()
   5898 	{
   5899 		return "Call glDrawArrayIndirect";
   5900 	}
   5901 
   5902 	virtual std::string PassCriteria()
   5903 	{
   5904 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   5905 	}
   5906 
   5907 	virtual long Setup()
   5908 	{
   5909 		glClear(GL_COLOR_BUFFER_BIT);
   5910 		return NO_ERROR;
   5911 	}
   5912 
   5913 	virtual long Run()
   5914 	{
   5915 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   5916 		if (!_program)
   5917 		{
   5918 			return ERROR;
   5919 		}
   5920 		glUseProgram(_program);
   5921 
   5922 		CColorArray coords;
   5923 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   5924 
   5925 		glGenVertexArrays(1, &_vao);
   5926 		glBindVertexArray(_vao);
   5927 
   5928 		glGenBuffers(1, &_buffer);
   5929 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   5930 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   5931 
   5932 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   5933 		glEnableVertexAttribArray(0);
   5934 
   5935 		glDrawArraysIndirect(GL_TRIANGLES, 0);
   5936 		DIResult result;
   5937 		if (glGetError() != GL_INVALID_OPERATION)
   5938 		{
   5939 			result.error() << "Invalid error code returned by a driver";
   5940 		}
   5941 
   5942 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   5943 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   5944 
   5945 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   5946 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   5947 										 getWindowHeight()));
   5948 
   5949 		return result.code();
   5950 	}
   5951 
   5952 	virtual long Cleanup()
   5953 	{
   5954 		glDisableVertexAttribArray(0);
   5955 		glUseProgram(0);
   5956 		glDeleteProgram(_program);
   5957 		glDeleteVertexArrays(1, &_vao);
   5958 		glDeleteBuffers(1, &_buffer);
   5959 		return NO_ERROR;
   5960 	}
   5961 
   5962 private:
   5963 	GLuint _program;
   5964 	GLuint _vao, _buffer;
   5965 };
   5966 
   5967 template <typename api>
   5968 struct CNegativeZeroBufferElements : public DrawIndirectBase
   5969 {
   5970 	virtual std::string Title()
   5971 	{
   5972 		return "Negative: no indirect buffer/parameter - glDrawElementsIndirect";
   5973 	}
   5974 
   5975 	virtual std::string Purpose()
   5976 	{
   5977 		return "Verify that a driver sets error and no driver crash occurred";
   5978 	}
   5979 
   5980 	virtual std::string Method()
   5981 	{
   5982 		return "Call glDrawElementsIndirect";
   5983 	}
   5984 
   5985 	virtual std::string PassCriteria()
   5986 	{
   5987 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   5988 	}
   5989 
   5990 	virtual long Setup()
   5991 	{
   5992 		glClear(GL_COLOR_BUFFER_BIT);
   5993 		return NO_ERROR;
   5994 	}
   5995 
   5996 	virtual long Run()
   5997 	{
   5998 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   5999 		if (!_program)
   6000 		{
   6001 			return ERROR;
   6002 		}
   6003 		glUseProgram(_program);
   6004 
   6005 		CColorArray coords;
   6006 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   6007 
   6008 		glGenVertexArrays(1, &_vao);
   6009 		glBindVertexArray(_vao);
   6010 
   6011 		glGenBuffers(1, &_buffer);
   6012 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   6013 
   6014 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   6015 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   6016 		glEnableVertexAttribArray(0);
   6017 
   6018 		CElementArray elements(coords.size(), 0);
   6019 		for (size_t i = 0; i < elements.size(); ++i)
   6020 		{
   6021 			elements[i] = static_cast<GLuint>(i);
   6022 		}
   6023 
   6024 		glGenBuffers(1, &_ebo);
   6025 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   6026 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   6027 					 GL_STATIC_DRAW);
   6028 
   6029 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   6030 
   6031 		DIResult result;
   6032 		if (glGetError() != GL_INVALID_OPERATION)
   6033 		{
   6034 			result.error() << "Invalid error code returned by a driver";
   6035 		}
   6036 
   6037 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   6038 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   6039 
   6040 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   6041 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   6042 										 getWindowHeight()));
   6043 
   6044 		return result.code();
   6045 	}
   6046 
   6047 	virtual long Cleanup()
   6048 	{
   6049 		glDisableVertexAttribArray(0);
   6050 		glUseProgram(0);
   6051 		glDeleteProgram(_program);
   6052 		glDeleteVertexArrays(1, &_vao);
   6053 		glDeleteBuffers(1, &_buffer);
   6054 		glDeleteBuffers(1, &_ebo);
   6055 		return NO_ERROR;
   6056 	}
   6057 
   6058 private:
   6059 	GLuint _program;
   6060 	GLuint _vao, _buffer, _ebo;
   6061 };
   6062 
   6063 template <typename api>
   6064 struct CNegativeInvalidModeArray : public DrawIndirectBase
   6065 {
   6066 	virtual std::string Title()
   6067 	{
   6068 		return "Negative: invalid mode - glDrawArrayIndirect";
   6069 	}
   6070 
   6071 	virtual std::string Purpose()
   6072 	{
   6073 		return "Verify that a driver sets error and no driver crash occurred";
   6074 	}
   6075 
   6076 	virtual std::string Method()
   6077 	{
   6078 		return "Set invalid mode to glDrawArrayIndirect";
   6079 	}
   6080 
   6081 	virtual std::string PassCriteria()
   6082 	{
   6083 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   6084 	}
   6085 
   6086 	virtual long Setup()
   6087 	{
   6088 		glClear(GL_COLOR_BUFFER_BIT);
   6089 		return NO_ERROR;
   6090 	}
   6091 
   6092 	virtual long Run()
   6093 	{
   6094 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   6095 		if (!_program)
   6096 		{
   6097 			return ERROR;
   6098 		}
   6099 		glUseProgram(_program);
   6100 
   6101 		CColorArray coords;
   6102 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   6103 
   6104 		glGenVertexArrays(1, &_vao);
   6105 		glBindVertexArray(_vao);
   6106 
   6107 		glGenBuffers(1, &_buffer);
   6108 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   6109 
   6110 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   6111 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   6112 		glEnableVertexAttribArray(0);
   6113 
   6114 		DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 };
   6115 		indirectArrays.count					 = static_cast<GLuint>(coords.size());
   6116 		indirectArrays.primCount				 = 1;
   6117 
   6118 		glGenBuffers(1, &_bufferIndirect);
   6119 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   6120 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW);
   6121 
   6122 		glDrawArraysIndirect(GL_FLOAT, 0);
   6123 
   6124 		DIResult result;
   6125 		if (glGetError() != GL_INVALID_ENUM)
   6126 		{
   6127 			result.error() << "Invalid error code returned by a driver for GL_FLOAT as mode";
   6128 		}
   6129 
   6130 		glDrawArraysIndirect(GL_STATIC_DRAW, 0);
   6131 		if (glGetError() != GL_INVALID_ENUM)
   6132 		{
   6133 			result.error() << "Invalid error code returned by a driver for GL_STATIC_DRAW as mode";
   6134 		}
   6135 
   6136 		glDrawArraysIndirect(GL_DRAW_INDIRECT_BUFFER, 0);
   6137 		if (glGetError() != GL_INVALID_ENUM)
   6138 		{
   6139 			result.error() << "Invalid error code returned by a driver for GL_DRAW_INDIRECT_BUFFER as mode";
   6140 		}
   6141 
   6142 		glDrawArraysIndirect(GL_INVALID_ENUM, 0);
   6143 		if (glGetError() != GL_INVALID_ENUM)
   6144 		{
   6145 			result.error() << "Invalid error code returned by a driver for GL_INVALID_ENUM as mode";
   6146 		}
   6147 
   6148 		glDrawArraysIndirect(GL_COLOR_BUFFER_BIT, 0);
   6149 		if (glGetError() != GL_INVALID_ENUM)
   6150 		{
   6151 			result.error() << "Invalid error code returned by a driver for GL_COLOR_BUFFER_BIT as mode";
   6152 		}
   6153 
   6154 		glDrawArraysIndirect(GL_ARRAY_BUFFER, 0);
   6155 		if (glGetError() != GL_INVALID_ENUM)
   6156 		{
   6157 			result.error() << "Invalid error code returned by a driver for GL_ARRAY_BUFFER as mode";
   6158 		}
   6159 
   6160 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   6161 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   6162 
   6163 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   6164 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   6165 										 getWindowHeight()));
   6166 
   6167 		return result.code();
   6168 	}
   6169 
   6170 	virtual long Cleanup()
   6171 	{
   6172 		glDisableVertexAttribArray(0);
   6173 		glUseProgram(0);
   6174 		glDeleteProgram(_program);
   6175 		glDeleteVertexArrays(1, &_vao);
   6176 		glDeleteBuffers(1, &_buffer);
   6177 		glDeleteBuffers(1, &_bufferIndirect);
   6178 		return NO_ERROR;
   6179 	}
   6180 
   6181 private:
   6182 	GLuint _program;
   6183 	GLuint _vao, _buffer, _bufferIndirect;
   6184 };
   6185 
   6186 template <typename api>
   6187 struct CNegativeInvalidModeElements : public DrawIndirectBase
   6188 {
   6189 	virtual std::string Title()
   6190 	{
   6191 		return "Negative: invalid mode - glDrawElementsIndirect";
   6192 	}
   6193 
   6194 	virtual std::string Purpose()
   6195 	{
   6196 		return "Verify that a driver sets error and no driver crash occurred";
   6197 	}
   6198 
   6199 	virtual std::string Method()
   6200 	{
   6201 		return "Set invalid mode to glDrawElemenetsIndirect";
   6202 	}
   6203 
   6204 	virtual std::string PassCriteria()
   6205 	{
   6206 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   6207 	}
   6208 
   6209 	virtual long Setup()
   6210 	{
   6211 		glClear(GL_COLOR_BUFFER_BIT);
   6212 		return NO_ERROR;
   6213 	}
   6214 
   6215 	virtual long Run()
   6216 	{
   6217 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   6218 		if (!_program)
   6219 		{
   6220 			return ERROR;
   6221 		}
   6222 		glUseProgram(_program);
   6223 
   6224 		CColorArray coords;
   6225 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   6226 
   6227 		glGenVertexArrays(1, &_vao);
   6228 		glBindVertexArray(_vao);
   6229 
   6230 		glGenBuffers(1, &_buffer);
   6231 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   6232 
   6233 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   6234 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   6235 		glEnableVertexAttribArray(0);
   6236 
   6237 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   6238 		indirectElements.count						 = static_cast<GLuint>(coords.size());
   6239 		indirectElements.primCount					 = 1;
   6240 
   6241 		CElementArray elements(coords.size(), 0);
   6242 		for (size_t i = 0; i < elements.size(); ++i)
   6243 		{
   6244 			elements[i] = static_cast<GLuint>(i);
   6245 		}
   6246 
   6247 		glGenBuffers(1, &_bufferIndirect);
   6248 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   6249 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   6250 
   6251 		glGenBuffers(1, &_ebo);
   6252 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   6253 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   6254 					 GL_STATIC_DRAW);
   6255 
   6256 		DIResult result;
   6257 		glDrawElementsIndirect(GL_INVALID_ENUM, GL_UNSIGNED_INT, 0);
   6258 		if (glGetError() != GL_INVALID_ENUM)
   6259 		{
   6260 			result.error() << "Invalid error code returned by a driver for GL_FLOAT as mode";
   6261 		}
   6262 
   6263 		glDrawElementsIndirect(GL_UNSIGNED_INT, GL_UNSIGNED_INT, 0);
   6264 		if (glGetError() != GL_INVALID_ENUM)
   6265 		{
   6266 			result.error() << "Invalid error code returned by a driver for GL_UNSIGNED_INT as mode";
   6267 		}
   6268 
   6269 		glDrawElementsIndirect(GL_ELEMENT_ARRAY_BUFFER, GL_UNSIGNED_INT, 0);
   6270 		if (glGetError() != GL_INVALID_ENUM)
   6271 		{
   6272 			result.error() << "Invalid error code returned by a driver for GL_ELEMENT_ARRAY_BUFFER as mode";
   6273 		}
   6274 
   6275 		glDrawElementsIndirect(GL_FASTEST, GL_UNSIGNED_INT, 0);
   6276 		if (glGetError() != GL_INVALID_ENUM)
   6277 		{
   6278 			result.error() << "Invalid error code returned by a driver for GL_FASTEST as mode";
   6279 		}
   6280 
   6281 		glDrawElementsIndirect(GL_PACK_ALIGNMENT, GL_UNSIGNED_INT, 0);
   6282 		if (glGetError() != GL_INVALID_ENUM)
   6283 		{
   6284 			result.error() << "Invalid error code returned by a driver for GL_PACK_ALIGNMENT as mode";
   6285 		}
   6286 
   6287 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   6288 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   6289 
   6290 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   6291 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   6292 										 getWindowHeight()));
   6293 
   6294 		return result.code();
   6295 	}
   6296 
   6297 	virtual long Cleanup()
   6298 	{
   6299 		glDisableVertexAttribArray(0);
   6300 		glUseProgram(0);
   6301 		glDeleteProgram(_program);
   6302 		glDeleteVertexArrays(1, &_vao);
   6303 		glDeleteBuffers(1, &_buffer);
   6304 		glDeleteBuffers(1, &_ebo);
   6305 		glDeleteBuffers(1, &_bufferIndirect);
   6306 		return NO_ERROR;
   6307 	}
   6308 
   6309 private:
   6310 	GLuint _program;
   6311 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   6312 };
   6313 
   6314 template <typename api>
   6315 struct CNegativeNoVAOArrays : public DrawIndirectBase
   6316 {
   6317 	virtual std::string Title()
   6318 	{
   6319 		return "Negative: no VAO - glDrawArraysIndirect";
   6320 	}
   6321 
   6322 	virtual std::string Purpose()
   6323 	{
   6324 		return "Verify that a driver sets error and no driver crash occurred";
   6325 	}
   6326 
   6327 	virtual std::string Method()
   6328 	{
   6329 		return "Use glDrawArraysIndirect with default VAO";
   6330 	}
   6331 
   6332 	virtual std::string PassCriteria()
   6333 	{
   6334 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   6335 	}
   6336 
   6337 	virtual long Setup()
   6338 	{
   6339 		glClear(GL_COLOR_BUFFER_BIT);
   6340 		return NO_ERROR;
   6341 	}
   6342 
   6343 	virtual long Run()
   6344 	{
   6345 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   6346 		if (!_program)
   6347 		{
   6348 			return ERROR;
   6349 		}
   6350 		glUseProgram(_program);
   6351 
   6352 		CColorArray coords;
   6353 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   6354 
   6355 		glGenBuffers(1, &_buffer);
   6356 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   6357 
   6358 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   6359 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   6360 		glEnableVertexAttribArray(0);
   6361 
   6362 		DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 };
   6363 		indirectArrays.count					 = static_cast<GLuint>(coords.size());
   6364 		indirectArrays.primCount				 = 1;
   6365 
   6366 		glGenBuffers(1, &_bufferIndirect);
   6367 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   6368 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectArrays, GL_STATIC_DRAW);
   6369 
   6370 		DIResult result;
   6371 		glDrawArraysIndirect(GL_TRIANGLES, 0);
   6372 		if (glGetError() != GL_INVALID_OPERATION)
   6373 		{
   6374 			result.error() << "Invalid error code returned by a driver";
   6375 		}
   6376 
   6377 		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
   6378 			glDisableVertexAttribArray(0);
   6379 
   6380 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   6381 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   6382 
   6383 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   6384 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   6385 										 getWindowHeight()));
   6386 
   6387 		return result.code();
   6388 	}
   6389 
   6390 	virtual long Cleanup()
   6391 	{
   6392 
   6393 		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
   6394 			glDisableVertexAttribArray(0);
   6395 
   6396 		glUseProgram(0);
   6397 		glDeleteProgram(_program);
   6398 		glDeleteBuffers(1, &_buffer);
   6399 		glDeleteBuffers(1, &_bufferIndirect);
   6400 		return NO_ERROR;
   6401 	}
   6402 
   6403 private:
   6404 	GLuint _program;
   6405 	GLuint _buffer, _ebo, _bufferIndirect;
   6406 };
   6407 
   6408 template <typename api>
   6409 struct CNegativeNoVAOElements : public DrawIndirectBase
   6410 {
   6411 	virtual std::string Title()
   6412 	{
   6413 		return "Negative: no VAO - glDrawElementsIndirect";
   6414 	}
   6415 
   6416 	virtual std::string Purpose()
   6417 	{
   6418 		return "Verify that a driver sets error and no driver crash occurred";
   6419 	}
   6420 
   6421 	virtual std::string Method()
   6422 	{
   6423 		return "Use glDrawElemenetsIndirect with default VAO";
   6424 	}
   6425 
   6426 	virtual std::string PassCriteria()
   6427 	{
   6428 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   6429 	}
   6430 
   6431 	virtual long Setup()
   6432 	{
   6433 		glClear(GL_COLOR_BUFFER_BIT);
   6434 		return NO_ERROR;
   6435 	}
   6436 
   6437 	virtual long Run()
   6438 	{
   6439 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   6440 		if (!_program)
   6441 		{
   6442 			return ERROR;
   6443 		}
   6444 		glUseProgram(_program);
   6445 
   6446 		CColorArray coords;
   6447 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   6448 
   6449 		glGenBuffers(1, &_buffer);
   6450 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   6451 
   6452 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   6453 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   6454 		glEnableVertexAttribArray(0);
   6455 
   6456 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   6457 		indirectElements.count						 = static_cast<GLuint>(coords.size());
   6458 		indirectElements.primCount					 = 1;
   6459 
   6460 		CElementArray elements(coords.size(), 0);
   6461 		for (size_t i = 0; i < elements.size(); ++i)
   6462 		{
   6463 			elements[i] = static_cast<GLuint>(i);
   6464 		}
   6465 
   6466 		glGenBuffers(1, &_bufferIndirect);
   6467 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   6468 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   6469 
   6470 		glGenBuffers(1, &_ebo);
   6471 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   6472 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   6473 					 GL_STATIC_DRAW);
   6474 
   6475 		DIResult result;
   6476 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   6477 		if (glGetError() != GL_INVALID_OPERATION)
   6478 		{
   6479 			result.error() << "Invalid error code returned by a driver";
   6480 		}
   6481 
   6482 		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
   6483 			glDisableVertexAttribArray(0);
   6484 
   6485 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   6486 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   6487 
   6488 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   6489 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   6490 										 getWindowHeight()));
   6491 
   6492 		return result.code();
   6493 	}
   6494 
   6495 	virtual long Cleanup()
   6496 	{
   6497 		glUseProgram(0);
   6498 		glDeleteProgram(_program);
   6499 		glDeleteBuffers(1, &_buffer);
   6500 		glDeleteBuffers(1, &_ebo);
   6501 		glDeleteBuffers(1, &_bufferIndirect);
   6502 		return NO_ERROR;
   6503 	}
   6504 
   6505 private:
   6506 	GLuint _program;
   6507 	GLuint _buffer, _ebo, _bufferIndirect;
   6508 };
   6509 
   6510 template <typename api>
   6511 struct CNegativeNoVBOArrays : public DrawIndirectBase
   6512 {
   6513 	virtual std::string Title()
   6514 	{
   6515 		return "Negative: no VBO - glDrawArraysIndirect";
   6516 	}
   6517 
   6518 	virtual std::string Purpose()
   6519 	{
   6520 		return "Verify that a driver sets error and no driver crash occurred";
   6521 	}
   6522 
   6523 	virtual std::string Method()
   6524 	{
   6525 		return "Use glDrawArraysIndirect with enabled vertex array, that has no VBO bound";
   6526 	}
   6527 
   6528 	virtual std::string PassCriteria()
   6529 	{
   6530 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   6531 	}
   6532 
   6533 	virtual long Setup()
   6534 	{
   6535 		glClear(GL_COLOR_BUFFER_BIT);
   6536 		return NO_ERROR;
   6537 	}
   6538 
   6539 	virtual long Run()
   6540 	{
   6541 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   6542 		if (!_program)
   6543 		{
   6544 			return ERROR;
   6545 		}
   6546 		glUseProgram(_program);
   6547 
   6548 		CColorArray coords;
   6549 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   6550 
   6551 		glGenVertexArrays(1, &_vao);
   6552 		glBindVertexArray(_vao);
   6553 		glEnableVertexAttribArray(0);
   6554 
   6555 		DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 };
   6556 		indirectArrays.count					 = static_cast<GLuint>(coords.size());
   6557 		indirectArrays.primCount				 = 1;
   6558 
   6559 		glGenBuffers(1, &_bufferIndirect);
   6560 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   6561 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectArrays, GL_STATIC_DRAW);
   6562 
   6563 		DIResult result;
   6564 		glDrawArraysIndirect(GL_TRIANGLES, 0);
   6565 		if (glGetError() != GL_INVALID_OPERATION)
   6566 		{
   6567 			result.error() << "Invalid error code returned by a driver";
   6568 		}
   6569 
   6570 		glDisableVertexAttribArray(0);
   6571 
   6572 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   6573 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   6574 
   6575 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   6576 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   6577 										 getWindowHeight()));
   6578 
   6579 		return result.code();
   6580 	}
   6581 
   6582 	virtual long Cleanup()
   6583 	{
   6584 		glDisableVertexAttribArray(0);
   6585 		glUseProgram(0);
   6586 		glDeleteProgram(_program);
   6587 		glDeleteVertexArrays(1, &_vao);
   6588 		glDeleteBuffers(1, &_bufferIndirect);
   6589 		return NO_ERROR;
   6590 	}
   6591 
   6592 private:
   6593 	GLuint _program;
   6594 	GLuint _vao, _ebo, _bufferIndirect;
   6595 };
   6596 
   6597 template <typename api>
   6598 struct CNegativeNoVBOElements : public DrawIndirectBase
   6599 {
   6600 	virtual std::string Title()
   6601 	{
   6602 		return "Negative: no VBO - glDrawElementsIndirect";
   6603 	}
   6604 
   6605 	virtual std::string Purpose()
   6606 	{
   6607 		return "Verify that a driver sets error and no driver crash occurred";
   6608 	}
   6609 
   6610 	virtual std::string Method()
   6611 	{
   6612 		return "Use glDrawElementsIndirect with enabled vertex array, that has no VBO bound";
   6613 	}
   6614 
   6615 	virtual std::string PassCriteria()
   6616 	{
   6617 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   6618 	}
   6619 
   6620 	virtual long Setup()
   6621 	{
   6622 		glClear(GL_COLOR_BUFFER_BIT);
   6623 		return NO_ERROR;
   6624 	}
   6625 
   6626 	virtual long Run()
   6627 	{
   6628 
   6629 		api::ES_Only();
   6630 
   6631 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   6632 		if (!_program)
   6633 		{
   6634 			return ERROR;
   6635 		}
   6636 		glUseProgram(_program);
   6637 
   6638 		CColorArray coords;
   6639 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   6640 
   6641 		glGenVertexArrays(1, &_vao);
   6642 		glBindVertexArray(_vao);
   6643 		glEnableVertexAttribArray(0);
   6644 		glEnableVertexAttribArray(0);
   6645 
   6646 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   6647 		indirectElements.count						 = static_cast<GLuint>(coords.size());
   6648 		indirectElements.primCount					 = 1;
   6649 
   6650 		CElementArray elements(coords.size(), 0);
   6651 		for (size_t i = 0; i < elements.size(); ++i)
   6652 		{
   6653 			elements[i] = static_cast<GLuint>(i);
   6654 		}
   6655 
   6656 		glGenBuffers(1, &_bufferIndirect);
   6657 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   6658 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   6659 
   6660 		glGenBuffers(1, &_ebo);
   6661 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   6662 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   6663 					 GL_STATIC_DRAW);
   6664 
   6665 		DIResult result;
   6666 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   6667 		if (glGetError() != GL_INVALID_OPERATION)
   6668 		{
   6669 			result.error() << "Invalid error code returned by a driver";
   6670 		}
   6671 
   6672 		glDisableVertexAttribArray(0);
   6673 
   6674 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   6675 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   6676 
   6677 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   6678 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   6679 										 getWindowHeight()));
   6680 
   6681 		return result.code();
   6682 	}
   6683 
   6684 	virtual long Cleanup()
   6685 	{
   6686 		glDisableVertexAttribArray(0);
   6687 		glUseProgram(0);
   6688 		glDeleteProgram(_program);
   6689 		glDeleteVertexArrays(1, &_vao);
   6690 		glDeleteBuffers(1, &_ebo);
   6691 		glDeleteBuffers(1, &_bufferIndirect);
   6692 		return NO_ERROR;
   6693 	}
   6694 
   6695 private:
   6696 	GLuint _program;
   6697 	GLuint _vao, _ebo, _bufferIndirect;
   6698 };
   6699 
   6700 template <typename api>
   6701 struct CNegativeBufferMappedArray : public DrawIndirectBase
   6702 {
   6703 	virtual std::string Title()
   6704 	{
   6705 		return "Negative: buffer mapped - glDrawArraysIndirect";
   6706 	}
   6707 
   6708 	virtual std::string Purpose()
   6709 	{
   6710 		return "Verify that a driver sets error and no driver crash occurred";
   6711 	}
   6712 
   6713 	virtual std::string Method()
   6714 	{
   6715 		return "1. Create and bind buffer" NL "2. Map buffer" NL "3. Call glDrawArrayIndirect";
   6716 	}
   6717 
   6718 	virtual std::string PassCriteria()
   6719 	{
   6720 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   6721 	}
   6722 
   6723 	virtual long Setup()
   6724 	{
   6725 		glClear(GL_COLOR_BUFFER_BIT);
   6726 		return NO_ERROR;
   6727 	}
   6728 
   6729 	virtual long Run()
   6730 	{
   6731 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   6732 		if (!_program)
   6733 		{
   6734 			return ERROR;
   6735 		}
   6736 		glUseProgram(_program);
   6737 
   6738 		CColorArray coords;
   6739 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   6740 
   6741 		glGenVertexArrays(1, &_vao);
   6742 		glBindVertexArray(_vao);
   6743 
   6744 		glGenBuffers(1, &_buffer);
   6745 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   6746 
   6747 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   6748 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   6749 		glEnableVertexAttribArray(0);
   6750 
   6751 		DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 };
   6752 		indirectArrays.count					 = static_cast<GLuint>(coords.size());
   6753 		indirectArrays.primCount				 = 1;
   6754 
   6755 		glGenBuffers(1, &_bufferIndirect);
   6756 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   6757 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW);
   6758 
   6759 		DIResult result;
   6760 		void*	buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawArraysIndirectCommand), GL_MAP_READ_BIT);
   6761 		if (buf == 0)
   6762 		{
   6763 			result.error() << "glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_MAP_READ_BIT) returned NULL";
   6764 		}
   6765 
   6766 		glDrawArraysIndirect(GL_TRIANGLES, 0);
   6767 
   6768 		GLenum error = glGetError();
   6769 		if (error == GL_INVALID_OPERATION)
   6770 		{
   6771 			//GL error: nothing is rendered
   6772 			CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   6773 			CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   6774 
   6775 			ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   6776 			result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef,
   6777 											 getWindowWidth(), getWindowHeight()));
   6778 		}
   6779 		else if (error == GL_NO_ERROR)
   6780 		{
   6781 			//No GL error: undefined
   6782 		}
   6783 		else
   6784 		{
   6785 			result.error() << "Invalid error code returned by a driver";
   6786 		}
   6787 
   6788 		if (buf)
   6789 		{
   6790 			if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) != GL_TRUE)
   6791 			{
   6792 				result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE";
   6793 			}
   6794 			buf = 0;
   6795 		}
   6796 
   6797 		return result.code();
   6798 	}
   6799 
   6800 	virtual long Cleanup()
   6801 	{
   6802 		glDisableVertexAttribArray(0);
   6803 		glUseProgram(0);
   6804 		glDeleteProgram(_program);
   6805 		glDeleteVertexArrays(1, &_vao);
   6806 		glDeleteBuffers(1, &_buffer);
   6807 		glDeleteBuffers(1, &_bufferIndirect);
   6808 		return NO_ERROR;
   6809 	}
   6810 
   6811 private:
   6812 	GLuint _program;
   6813 	GLuint _vao, _buffer, _bufferIndirect;
   6814 };
   6815 
   6816 template <typename api>
   6817 struct CNegativeBufferMappedElements : public DrawIndirectBase
   6818 {
   6819 	virtual std::string Title()
   6820 	{
   6821 		return "Negative: buffer mapped - glDrawElementsIndirect";
   6822 	}
   6823 
   6824 	virtual std::string Purpose()
   6825 	{
   6826 		return "Verify that a driver sets error and no driver crash occurred";
   6827 	}
   6828 
   6829 	virtual std::string Method()
   6830 	{
   6831 		return "1. Create and bind buffer" NL "2. Map buffer" NL "3. Call glDrawElementsIndirect";
   6832 	}
   6833 
   6834 	virtual std::string PassCriteria()
   6835 	{
   6836 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   6837 	}
   6838 
   6839 	virtual long Setup()
   6840 	{
   6841 		glClear(GL_COLOR_BUFFER_BIT);
   6842 		return NO_ERROR;
   6843 	}
   6844 
   6845 	virtual long Run()
   6846 	{
   6847 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   6848 		if (!_program)
   6849 		{
   6850 			return ERROR;
   6851 		}
   6852 		glUseProgram(_program);
   6853 
   6854 		CColorArray coords;
   6855 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   6856 
   6857 		glGenVertexArrays(1, &_vao);
   6858 		glBindVertexArray(_vao);
   6859 
   6860 		glGenBuffers(1, &_buffer);
   6861 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   6862 
   6863 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   6864 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   6865 		glEnableVertexAttribArray(0);
   6866 
   6867 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   6868 		indirectElements.count						 = static_cast<GLuint>(coords.size());
   6869 		indirectElements.primCount					 = 1;
   6870 
   6871 		CElementArray elements(coords.size(), 0);
   6872 		for (size_t i = 0; i < elements.size(); ++i)
   6873 		{
   6874 			elements[i] = static_cast<GLuint>(i);
   6875 		}
   6876 
   6877 		glGenBuffers(1, &_bufferIndirect);
   6878 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   6879 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   6880 
   6881 		glGenBuffers(1, &_ebo);
   6882 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   6883 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   6884 					 GL_STATIC_DRAW);
   6885 
   6886 		DIResult result;
   6887 		void* buf = glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawElementsIndirectCommand), GL_MAP_WRITE_BIT);
   6888 		if (buf == 0)
   6889 		{
   6890 			result.error() << "glMapBuffer(GL_DRAW_INDIRECT_BUFFER, GL_MAP_WRITE_BIT) returned NULL";
   6891 		}
   6892 
   6893 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   6894 
   6895 		GLenum error = glGetError();
   6896 		if (error == GL_INVALID_OPERATION)
   6897 		{
   6898 			//GL error: nothing is rendered
   6899 			CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   6900 			CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   6901 
   6902 			ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   6903 			result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef,
   6904 											 getWindowWidth(), getWindowHeight()));
   6905 		}
   6906 		else if (error == GL_NO_ERROR)
   6907 		{
   6908 			//No GL error: undefined
   6909 		}
   6910 		else
   6911 		{
   6912 			result.error() << "Invalid error code returned by a driver";
   6913 		}
   6914 
   6915 		if (buf)
   6916 		{
   6917 			if (glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) != GL_TRUE)
   6918 			{
   6919 				result.error() << "glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER) returned GL_FALSE, expected GL_TRUE";
   6920 			}
   6921 			buf = 0;
   6922 		}
   6923 
   6924 		return result.code();
   6925 	}
   6926 
   6927 	virtual long Cleanup()
   6928 	{
   6929 		glDisableVertexAttribArray(0);
   6930 		glUseProgram(0);
   6931 		glDeleteProgram(_program);
   6932 		glDeleteVertexArrays(1, &_vao);
   6933 		glDeleteBuffers(1, &_buffer);
   6934 		glDeleteBuffers(1, &_ebo);
   6935 		glDeleteBuffers(1, &_bufferIndirect);
   6936 		return NO_ERROR;
   6937 	}
   6938 
   6939 private:
   6940 	GLuint _program;
   6941 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   6942 };
   6943 
   6944 template <typename api>
   6945 struct CNegativeDataWrongElements : public DrawIndirectBase
   6946 {
   6947 	virtual std::string Title()
   6948 	{
   6949 		return "Negative: invalid type - glDrawElementsIndirect";
   6950 	}
   6951 
   6952 	virtual std::string Purpose()
   6953 	{
   6954 		return "Verify that a driver sets error and no driver crash occurred";
   6955 	}
   6956 
   6957 	virtual std::string Method()
   6958 	{
   6959 		return "1. Bind non-zero buffer" NL "2. Call glDrawElementsIndirect with invalid type";
   6960 	}
   6961 
   6962 	virtual std::string PassCriteria()
   6963 	{
   6964 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   6965 	}
   6966 
   6967 	virtual long Setup()
   6968 	{
   6969 		glClear(GL_COLOR_BUFFER_BIT);
   6970 		return NO_ERROR;
   6971 	}
   6972 
   6973 	virtual long Run()
   6974 	{
   6975 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   6976 		if (!_program)
   6977 		{
   6978 			return ERROR;
   6979 		}
   6980 		glUseProgram(_program);
   6981 
   6982 		CColorArray coords;
   6983 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   6984 
   6985 		glGenVertexArrays(1, &_vao);
   6986 		glBindVertexArray(_vao);
   6987 
   6988 		glGenBuffers(1, &_buffer);
   6989 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   6990 
   6991 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   6992 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   6993 		glEnableVertexAttribArray(0);
   6994 
   6995 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   6996 		indirectElements.count						 = static_cast<GLuint>(coords.size());
   6997 		indirectElements.primCount					 = 1;
   6998 
   6999 		CElementArray elements(coords.size(), 0);
   7000 		for (size_t i = 0; i < elements.size(); ++i)
   7001 		{
   7002 			elements[i] = static_cast<GLuint>(i);
   7003 		}
   7004 
   7005 		glGenBuffers(1, &_bufferIndirect);
   7006 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   7007 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   7008 
   7009 		glGenBuffers(1, &_ebo);
   7010 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   7011 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   7012 					 GL_STATIC_DRAW);
   7013 
   7014 		DIResult result;
   7015 
   7016 		glDrawElementsIndirect(GL_TRIANGLES, GL_FLOAT, 0);
   7017 		if (glGetError() != GL_INVALID_ENUM)
   7018 		{
   7019 			result.error() << "Invalid error code returned by a driver for GL_FLOAT type";
   7020 		}
   7021 
   7022 		glDrawElementsIndirect(GL_TRIANGLES, GL_INT, 0);
   7023 		if (glGetError() != GL_INVALID_ENUM)
   7024 		{
   7025 			result.error() << "Invalid error code returned by a driver for GL_INT type";
   7026 		}
   7027 
   7028 		glDrawElementsIndirect(GL_TRIANGLES, GL_STATIC_DRAW, 0);
   7029 		if (glGetError() != GL_INVALID_ENUM)
   7030 		{
   7031 			result.error() << "Invalid error code returned by a driver for GL_STATIC_DRAW type";
   7032 		}
   7033 
   7034 		glDrawElementsIndirect(GL_TRIANGLES, GL_SHORT, 0);
   7035 		if (glGetError() != GL_INVALID_ENUM)
   7036 		{
   7037 			result.error() << "Invalid error code returned by a driver for GL_SHORT type";
   7038 		}
   7039 
   7040 		glDrawElementsIndirect(GL_TRIANGLES, GL_BYTE, 0);
   7041 		if (glGetError() != GL_INVALID_ENUM)
   7042 		{
   7043 			result.error() << "Invalid error code returned by a driver for GL_BYTE type";
   7044 		}
   7045 
   7046 		glDrawElementsIndirect(GL_TRIANGLES, GL_DOUBLE, 0);
   7047 		if (glGetError() != GL_INVALID_ENUM)
   7048 		{
   7049 			result.error() << "Invalid error code returned by a driver for GL_DOUBLE type";
   7050 		}
   7051 
   7052 		glDrawElementsIndirect(GL_TRIANGLES, GL_INVALID_ENUM, 0);
   7053 		if (glGetError() != GL_INVALID_ENUM)
   7054 		{
   7055 			result.error() << "Invalid error code returned by a driver for GL_INVALID_ENUM type";
   7056 		}
   7057 
   7058 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   7059 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   7060 
   7061 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   7062 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   7063 										 getWindowHeight()));
   7064 
   7065 		return result.code();
   7066 	}
   7067 
   7068 	virtual long Cleanup()
   7069 	{
   7070 		glDisableVertexAttribArray(0);
   7071 		glUseProgram(0);
   7072 		glDeleteProgram(_program);
   7073 		glDeleteVertexArrays(1, &_vao);
   7074 		glDeleteBuffers(1, &_buffer);
   7075 		glDeleteBuffers(1, &_ebo);
   7076 		glDeleteBuffers(1, &_bufferIndirect);
   7077 		return NO_ERROR;
   7078 	}
   7079 
   7080 private:
   7081 	GLuint _program;
   7082 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   7083 };
   7084 
   7085 template <typename api>
   7086 class CNegativeGshArray : public DrawIndirectBase
   7087 {
   7088 public:
   7089 	virtual std::string Title()
   7090 	{
   7091 		return "Negative: incompatible the input primitive type of gsh - glDrawArrayIndirect";
   7092 	}
   7093 
   7094 	virtual std::string Purpose()
   7095 	{
   7096 		return "Verify that a driver sets error and no driver crash occurred";
   7097 	}
   7098 
   7099 	virtual std::string Method()
   7100 	{
   7101 		return "1. Bind non-zero buffer" NL "2. Set data" NL "3. Set wrong geometry shader" NL
   7102 			   "4. Call glDrawArrayIndirect";
   7103 	}
   7104 
   7105 	virtual std::string PassCriteria()
   7106 	{
   7107 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   7108 	}
   7109 
   7110 	virtual long Setup()
   7111 	{
   7112 		glClear(GL_COLOR_BUFFER_BIT);
   7113 		return NO_ERROR;
   7114 	}
   7115 
   7116 	virtual long Run()
   7117 	{
   7118 		_program = CreateProgram(Vsh(), Gsh(), Fsh(), true);
   7119 		if (!_program)
   7120 		{
   7121 			return ERROR;
   7122 		}
   7123 		glUseProgram(_program);
   7124 
   7125 		CColorArray coords;
   7126 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   7127 
   7128 		glGenVertexArrays(1, &_vao);
   7129 		glBindVertexArray(_vao);
   7130 
   7131 		glGenBuffers(1, &_buffer);
   7132 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   7133 
   7134 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   7135 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   7136 		glEnableVertexAttribArray(0);
   7137 
   7138 		DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 };
   7139 		indirectArrays.count					 = static_cast<GLuint>(coords.size());
   7140 		indirectArrays.primCount				 = 1;
   7141 		indirectArrays.first					 = 0;
   7142 		indirectArrays.reservedMustBeZero		 = 2312;
   7143 
   7144 		glGenBuffers(1, &_bufferIndirect);
   7145 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   7146 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW);
   7147 
   7148 		DIResult result;
   7149 
   7150 		glDrawArraysIndirect(GL_POINTS, 0);
   7151 		if (glGetError() != GL_INVALID_OPERATION)
   7152 		{
   7153 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7154 		}
   7155 
   7156 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   7157 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   7158 
   7159 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   7160 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   7161 										 getWindowHeight()));
   7162 
   7163 		return result.code();
   7164 	}
   7165 
   7166 	virtual long Cleanup()
   7167 	{
   7168 		glDisableVertexAttribArray(0);
   7169 		glUseProgram(0);
   7170 		glDeleteProgram(_program);
   7171 		glDeleteVertexArrays(1, &_vao);
   7172 		glDeleteBuffers(1, &_buffer);
   7173 		glDeleteBuffers(1, &_bufferIndirect);
   7174 		return NO_ERROR;
   7175 	}
   7176 
   7177 private:
   7178 	std::string Vsh()
   7179 	{
   7180 		return "#version 150" NL "in vec4 coords;" NL "void main() {" NL "  gl_Position = coords;" NL "}";
   7181 	}
   7182 
   7183 	std::string Gsh()
   7184 	{
   7185 		return "#version 150" NL "layout(triangles) in;" NL "layout(triangle_strip, max_vertices = 10) out;" NL
   7186 			   "void main() {" NL " for (int i=0; i<gl_in.length(); ++i) {" NL
   7187 			   "     gl_Position = gl_in[i].gl_Position;" NL "     EmitVertex();" NL " }" NL "}";
   7188 	}
   7189 
   7190 	std::string Fsh()
   7191 	{
   7192 		return "#version 140" NL "out vec4 outColor;" NL "void main() {" NL
   7193 			   "  outColor = vec4(0.1f, 0.2f, 0.3f, 1.0f);" NL "}";
   7194 	}
   7195 	GLuint _program;
   7196 	GLuint _vao, _buffer, _bufferIndirect;
   7197 };
   7198 
   7199 template <typename api>
   7200 class CNegativeGshElements : public DrawIndirectBase
   7201 {
   7202 public:
   7203 	virtual std::string Title()
   7204 	{
   7205 		return "Negative: incompatible the input primitive type of gsh - glDrawElementsIndirect";
   7206 	}
   7207 
   7208 	virtual std::string Purpose()
   7209 	{
   7210 		return "Verify that a driver sets error and no driver crash occurred";
   7211 	}
   7212 
   7213 	virtual std::string Method()
   7214 	{
   7215 		return "1. Bind non-zero buffer" NL "2. Set data" NL "3. Set wrong geometry shader" NL
   7216 			   "4. Call glDrawElementsIndirect";
   7217 	}
   7218 
   7219 	virtual std::string PassCriteria()
   7220 	{
   7221 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   7222 	}
   7223 
   7224 	virtual long Setup()
   7225 	{
   7226 		glClear(GL_COLOR_BUFFER_BIT);
   7227 		return NO_ERROR;
   7228 	}
   7229 
   7230 	virtual long Run()
   7231 	{
   7232 		_program = CreateProgram(Vsh(), Gsh(), Fsh(), true);
   7233 		if (!_program)
   7234 		{
   7235 			return ERROR;
   7236 		}
   7237 		glUseProgram(_program);
   7238 
   7239 		CColorArray coords;
   7240 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   7241 
   7242 		glGenVertexArrays(1, &_vao);
   7243 		glBindVertexArray(_vao);
   7244 
   7245 		glGenBuffers(1, &_buffer);
   7246 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   7247 
   7248 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   7249 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   7250 		glEnableVertexAttribArray(0);
   7251 
   7252 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   7253 		indirectElements.count						 = static_cast<GLuint>(coords.size());
   7254 		indirectElements.primCount					 = 1;
   7255 
   7256 		CElementArray elements(coords.size(), 0);
   7257 		for (size_t i = 0; i < elements.size(); ++i)
   7258 		{
   7259 			elements[i] = static_cast<GLuint>(i);
   7260 		}
   7261 
   7262 		glGenBuffers(1, &_bufferIndirect);
   7263 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   7264 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   7265 
   7266 		glGenBuffers(1, &_ebo);
   7267 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   7268 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   7269 					 GL_STATIC_DRAW);
   7270 
   7271 		DIResult result;
   7272 
   7273 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   7274 		if (glGetError() != GL_INVALID_OPERATION)
   7275 		{
   7276 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7277 		}
   7278 
   7279 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   7280 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   7281 
   7282 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   7283 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   7284 										 getWindowHeight()));
   7285 
   7286 		return result.code();
   7287 	}
   7288 
   7289 	virtual long Cleanup()
   7290 	{
   7291 		glDisableVertexAttribArray(0);
   7292 		glUseProgram(0);
   7293 		glDeleteProgram(_program);
   7294 		glDeleteVertexArrays(1, &_vao);
   7295 		glDeleteBuffers(1, &_buffer);
   7296 		glDeleteBuffers(1, &_ebo);
   7297 		glDeleteBuffers(1, &_bufferIndirect);
   7298 		return NO_ERROR;
   7299 	}
   7300 
   7301 private:
   7302 	std::string Vsh()
   7303 	{
   7304 		return "#version 150" NL "in vec4 coords;" NL "void main() {" NL "  gl_Position = coords;" NL "}";
   7305 	}
   7306 
   7307 	std::string Gsh()
   7308 	{
   7309 		return "#version 150" NL "layout(lines) in;" NL "layout(line_strip, max_vertices = 10) out;" NL
   7310 			   "void main() {" NL " for (int i=0; i<gl_in.length(); ++i) {" NL
   7311 			   "     gl_Position = gl_in[i].gl_Position;" NL "     EmitVertex();" NL " }" NL "}";
   7312 	}
   7313 
   7314 	std::string Fsh()
   7315 	{
   7316 		return "#version 140" NL "out vec4 outColor;" NL "void main() {" NL
   7317 			   "  outColor = vec4(0.1f, 0.2f, 0.3f, 1.0f);" NL "}";
   7318 	}
   7319 	int	_program;
   7320 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   7321 };
   7322 
   7323 template <typename api>
   7324 struct CNegativeInvalidSizeArrays : public DrawIndirectBase
   7325 {
   7326 	struct TWrongStructure1
   7327 	{
   7328 		GLuint count;
   7329 		GLuint primCount;
   7330 	};
   7331 
   7332 	struct TWrongStructure2
   7333 	{
   7334 		GLfloat count;
   7335 		GLuint  primCount;
   7336 	};
   7337 
   7338 	virtual std::string Title()
   7339 	{
   7340 		return "Negative: wrong structure - glDrawArrayIndirect";
   7341 	}
   7342 
   7343 	virtual std::string Purpose()
   7344 	{
   7345 		return "Verify that a driver sets error and no driver crash occurred";
   7346 	}
   7347 
   7348 	virtual std::string Method()
   7349 	{
   7350 		return "Call glDrawArrayIndirect with wrong structure";
   7351 	}
   7352 
   7353 	virtual std::string PassCriteria()
   7354 	{
   7355 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   7356 	}
   7357 
   7358 	virtual long Setup()
   7359 	{
   7360 		glClear(GL_COLOR_BUFFER_BIT);
   7361 		return NO_ERROR;
   7362 	}
   7363 
   7364 	virtual long Run()
   7365 	{
   7366 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   7367 		if (!_program)
   7368 		{
   7369 			return ERROR;
   7370 		}
   7371 		glUseProgram(_program);
   7372 
   7373 		CColorArray coords;
   7374 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   7375 
   7376 		glGenVertexArrays(1, &_vao);
   7377 		glBindVertexArray(_vao);
   7378 
   7379 		glGenBuffers(1, &_buffer);
   7380 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   7381 
   7382 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   7383 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   7384 		glEnableVertexAttribArray(0);
   7385 
   7386 		TWrongStructure1 indirectArrays = { 0, 0 };
   7387 		indirectArrays.count			= static_cast<GLuint>(coords.size());
   7388 		indirectArrays.primCount		= 1;
   7389 
   7390 		glGenBuffers(1, &_bufferIndirect);
   7391 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   7392 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(TWrongStructure1), &indirectArrays, GL_STATIC_DRAW);
   7393 
   7394 		DIResult result;
   7395 
   7396 		glDrawArraysIndirect(GL_TRIANGLES, 0);
   7397 		if (glGetError() != GL_INVALID_OPERATION)
   7398 		{
   7399 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7400 		}
   7401 
   7402 		glDeleteBuffers(1, &_bufferIndirect);
   7403 
   7404 		TWrongStructure2 indirectArrays2 = { 0, 0 };
   7405 		indirectArrays2.count			 = static_cast<GLfloat>(coords.size());
   7406 		indirectArrays2.primCount		 = 1;
   7407 
   7408 		glGenBuffers(1, &_bufferIndirect);
   7409 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   7410 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(TWrongStructure2), &indirectArrays2, GL_STATIC_DRAW);
   7411 
   7412 		glDrawArraysIndirect(GL_TRIANGLES, 0);
   7413 		if (glGetError() != GL_INVALID_OPERATION)
   7414 		{
   7415 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7416 		}
   7417 
   7418 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   7419 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   7420 
   7421 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   7422 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   7423 										 getWindowHeight()));
   7424 
   7425 		return result.code();
   7426 	}
   7427 
   7428 	virtual long Cleanup()
   7429 	{
   7430 		glDisableVertexAttribArray(0);
   7431 		glUseProgram(0);
   7432 		glDeleteProgram(_program);
   7433 		glDeleteVertexArrays(1, &_vao);
   7434 		glDeleteBuffers(1, &_buffer);
   7435 		glDeleteBuffers(1, &_bufferIndirect);
   7436 		return NO_ERROR;
   7437 	}
   7438 
   7439 private:
   7440 	GLuint _program;
   7441 	GLuint _vao, _buffer, _bufferIndirect;
   7442 };
   7443 
   7444 template <typename api>
   7445 struct CNegativeInvalidSizeElements : public DrawIndirectBase
   7446 {
   7447 	struct TWrongStructure
   7448 	{
   7449 		GLfloat count;
   7450 		GLuint  primCount;
   7451 	};
   7452 
   7453 	virtual std::string Title()
   7454 	{
   7455 		return "Negative: wrong structure - glDrawElementsIndirect";
   7456 	}
   7457 
   7458 	virtual std::string Purpose()
   7459 	{
   7460 		return "Verify that a driver sets error and no driver crash occurred";
   7461 	}
   7462 
   7463 	virtual std::string Method()
   7464 	{
   7465 		return "Call glDrawElementsIndirect with wrong structure";
   7466 	}
   7467 
   7468 	virtual std::string PassCriteria()
   7469 	{
   7470 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   7471 	}
   7472 
   7473 	virtual long Setup()
   7474 	{
   7475 		glClear(GL_COLOR_BUFFER_BIT);
   7476 		return NO_ERROR;
   7477 	}
   7478 
   7479 	virtual long Run()
   7480 	{
   7481 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   7482 		if (!_program)
   7483 		{
   7484 			return ERROR;
   7485 		}
   7486 		glUseProgram(_program);
   7487 
   7488 		CColorArray coords;
   7489 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   7490 
   7491 		glGenVertexArrays(1, &_vao);
   7492 		glBindVertexArray(_vao);
   7493 
   7494 		glGenBuffers(1, &_buffer);
   7495 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   7496 
   7497 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   7498 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   7499 		glEnableVertexAttribArray(0);
   7500 
   7501 		DrawArraysIndirectCommand indirectElements = { 0, 0, 0, 0 };
   7502 		indirectElements.count					   = static_cast<GLuint>(coords.size());
   7503 		indirectElements.primCount				   = 1;
   7504 
   7505 		CElementArray elements(coords.size(), 0);
   7506 		for (size_t i = 0; i < elements.size(); ++i)
   7507 		{
   7508 			elements[i] = static_cast<GLuint>(i);
   7509 		}
   7510 
   7511 		glGenBuffers(1, &_bufferIndirect);
   7512 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   7513 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   7514 
   7515 		glGenBuffers(1, &_ebo);
   7516 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   7517 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   7518 					 GL_STATIC_DRAW);
   7519 
   7520 		DIResult result;
   7521 
   7522 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   7523 		if (glGetError() != GL_INVALID_OPERATION)
   7524 		{
   7525 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7526 		}
   7527 
   7528 		TWrongStructure indirectElements2 = { 0, 0 };
   7529 		indirectElements2.count			  = static_cast<GLfloat>(coords.size());
   7530 		indirectElements2.primCount		  = 1;
   7531 
   7532 		glDeleteBuffers(1, &_bufferIndirect);
   7533 		glGenBuffers(1, &_bufferIndirect);
   7534 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   7535 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(TWrongStructure), &indirectElements2, GL_STATIC_DRAW);
   7536 
   7537 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0);
   7538 		if (glGetError() != GL_INVALID_OPERATION)
   7539 		{
   7540 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7541 		}
   7542 
   7543 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   7544 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   7545 
   7546 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   7547 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   7548 										 getWindowHeight()));
   7549 
   7550 		return result.code();
   7551 	}
   7552 
   7553 	virtual long Cleanup()
   7554 	{
   7555 		glDisableVertexAttribArray(0);
   7556 		glUseProgram(0);
   7557 		glDeleteProgram(_program);
   7558 		glDeleteVertexArrays(1, &_vao);
   7559 		glDeleteBuffers(1, &_buffer);
   7560 		glDeleteBuffers(1, &_ebo);
   7561 		glDeleteBuffers(1, &_bufferIndirect);
   7562 		return NO_ERROR;
   7563 	}
   7564 
   7565 private:
   7566 	GLuint _program;
   7567 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   7568 };
   7569 
   7570 template <typename api>
   7571 struct CNegativeStructureWrongOffsetArray : public DrawIndirectBase
   7572 {
   7573 	virtual std::string Title()
   7574 	{
   7575 		return "Negative: wrong offset - glDrawArrayIndirect";
   7576 	}
   7577 
   7578 	virtual std::string Purpose()
   7579 	{
   7580 		return "Verify that a driver sets error and no driver crash occurred";
   7581 	}
   7582 
   7583 	virtual std::string Method()
   7584 	{
   7585 		return "Call glDrawArrayIndirect with wrong offset";
   7586 	}
   7587 
   7588 	virtual std::string PassCriteria()
   7589 	{
   7590 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   7591 	}
   7592 
   7593 	virtual long Setup()
   7594 	{
   7595 		glClear(GL_COLOR_BUFFER_BIT);
   7596 		return NO_ERROR;
   7597 	}
   7598 
   7599 	virtual long Run()
   7600 	{
   7601 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   7602 		if (!_program)
   7603 		{
   7604 			return ERROR;
   7605 		}
   7606 		glUseProgram(_program);
   7607 
   7608 		CColorArray coords;
   7609 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   7610 
   7611 		glGenVertexArrays(1, &_vao);
   7612 		glBindVertexArray(_vao);
   7613 
   7614 		glGenBuffers(1, &_buffer);
   7615 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   7616 
   7617 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   7618 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   7619 		glEnableVertexAttribArray(0);
   7620 
   7621 		DrawArraysIndirectCommand indirectArrays = { 0, 0, 0, 0 };
   7622 		indirectArrays.count					 = static_cast<GLuint>(coords.size());
   7623 		indirectArrays.primCount				 = 1;
   7624 
   7625 		glGenBuffers(1, &_bufferIndirect);
   7626 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   7627 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawArraysIndirectCommand), &indirectArrays, GL_STATIC_DRAW);
   7628 
   7629 		DIResult result;
   7630 
   7631 		glDrawArraysIndirect(GL_TRIANGLES, (void*)(sizeof(DrawArraysIndirectCommand) * 2));
   7632 		if (glGetError() != GL_INVALID_OPERATION)
   7633 		{
   7634 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7635 		}
   7636 
   7637 		glDrawArraysIndirect(GL_TRIANGLES, (void*)(sizeof(GLuint)));
   7638 		if (glGetError() != GL_INVALID_OPERATION)
   7639 		{
   7640 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7641 		}
   7642 
   7643 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   7644 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   7645 
   7646 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   7647 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   7648 										 getWindowHeight()));
   7649 
   7650 		return result.code();
   7651 	}
   7652 
   7653 	virtual long Cleanup()
   7654 	{
   7655 		glDisableVertexAttribArray(0);
   7656 		glUseProgram(0);
   7657 		glDeleteProgram(_program);
   7658 		glDeleteVertexArrays(1, &_vao);
   7659 		glDeleteBuffers(1, &_buffer);
   7660 		glDeleteBuffers(1, &_bufferIndirect);
   7661 		return NO_ERROR;
   7662 	}
   7663 
   7664 private:
   7665 	GLuint _program;
   7666 	GLuint _vao, _buffer, _bufferIndirect;
   7667 };
   7668 
   7669 template <typename api>
   7670 struct CNegativeStructureWrongOffsetElements : public DrawIndirectBase
   7671 {
   7672 	virtual std::string Title()
   7673 	{
   7674 		return "Negative: wrong offset - glDrawElementsIndirect";
   7675 	}
   7676 
   7677 	virtual std::string Purpose()
   7678 	{
   7679 		return "Verify that a driver sets error and no driver crash occurred";
   7680 	}
   7681 
   7682 	virtual std::string Method()
   7683 	{
   7684 		return "Call glDrawElementsIndirect with wrong structure";
   7685 	}
   7686 
   7687 	virtual std::string PassCriteria()
   7688 	{
   7689 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   7690 	}
   7691 
   7692 	virtual long Setup()
   7693 	{
   7694 		glClear(GL_COLOR_BUFFER_BIT);
   7695 		return NO_ERROR;
   7696 	}
   7697 
   7698 	virtual long Run()
   7699 	{
   7700 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   7701 		if (!_program)
   7702 		{
   7703 			return ERROR;
   7704 		}
   7705 		glUseProgram(_program);
   7706 
   7707 		CColorArray coords;
   7708 		PrimitiveGen(GL_TRIANGLES, 8, 8, coords);
   7709 
   7710 		glGenVertexArrays(1, &_vao);
   7711 		glBindVertexArray(_vao);
   7712 
   7713 		glGenBuffers(1, &_buffer);
   7714 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   7715 
   7716 		glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(coords[0])), &coords[0], GL_STREAM_DRAW);
   7717 		glVertexAttribPointer(0, sizeof(coords[0]) / sizeof(float), GL_FLOAT, GL_FALSE, sizeof(coords[0]), 0);
   7718 		glEnableVertexAttribArray(0);
   7719 
   7720 		DrawElementsIndirectCommand indirectElements = { 0, 0, 0, 0, 0 };
   7721 		indirectElements.count						 = static_cast<GLuint>(coords.size());
   7722 		indirectElements.primCount					 = 1;
   7723 
   7724 		CElementArray elements(coords.size(), 0);
   7725 		for (size_t i = 0; i < elements.size(); ++i)
   7726 		{
   7727 			elements[i] = static_cast<GLuint>(i);
   7728 		}
   7729 
   7730 		glGenBuffers(1, &_bufferIndirect);
   7731 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   7732 		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand), &indirectElements, GL_STATIC_DRAW);
   7733 
   7734 		glGenBuffers(1, &_ebo);
   7735 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   7736 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(elements.size() * sizeof(elements[0])), &elements[0],
   7737 					 GL_STATIC_DRAW);
   7738 
   7739 		DIResult result;
   7740 
   7741 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, (void*)(sizeof(DrawElementsIndirectCommand) * 2));
   7742 		if (glGetError() != GL_INVALID_OPERATION)
   7743 		{
   7744 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7745 		}
   7746 
   7747 		glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, (void*)(sizeof(GLuint)));
   7748 		if (glGetError() != GL_INVALID_OPERATION)
   7749 		{
   7750 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7751 		}
   7752 
   7753 		CColorArray bufferRef(getWindowWidth() * getWindowHeight(), tcu::Vec4(0.0f));
   7754 		CColorArray bufferTest(getWindowWidth() * getWindowHeight(), tcu::Vec4(1.0f));
   7755 
   7756 		ReadPixelsFloat<api>(0, 0, getWindowWidth(), getWindowHeight(), &bufferTest[0]);
   7757 		result.sub_result(BuffersCompare(bufferTest, getWindowWidth(), getWindowHeight(), bufferRef, getWindowWidth(),
   7758 										 getWindowHeight()));
   7759 
   7760 		return result.code();
   7761 	}
   7762 
   7763 	virtual long Cleanup()
   7764 	{
   7765 		glDisableVertexAttribArray(0);
   7766 		glUseProgram(0);
   7767 		glDeleteProgram(_program);
   7768 		glDeleteVertexArrays(1, &_vao);
   7769 		glDeleteBuffers(1, &_buffer);
   7770 		glDeleteBuffers(1, &_ebo);
   7771 		glDeleteBuffers(1, &_bufferIndirect);
   7772 		return NO_ERROR;
   7773 	}
   7774 
   7775 private:
   7776 	GLuint _program;
   7777 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   7778 };
   7779 
   7780 template <typename api>
   7781 struct CNegativeUnalignedOffset : public DrawIndirectBase
   7782 {
   7783 	virtual std::string Title()
   7784 	{
   7785 		return "Negative: unaligned offset - glDrawElementsIndirect and glDrawArraysIndirect";
   7786 	}
   7787 
   7788 	virtual std::string Purpose()
   7789 	{
   7790 		return "Verify that a driver sets error and no system/driver crash occurred";
   7791 	}
   7792 
   7793 	virtual std::string Method()
   7794 	{
   7795 		return "Call with unaligned offset (1, 3, 1023)";
   7796 	}
   7797 
   7798 	virtual std::string PassCriteria()
   7799 	{
   7800 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   7801 	}
   7802 
   7803 	virtual long Run()
   7804 	{
   7805 		_program = CreateProgram(shaders::vshSimple<api>(), "", shaders::fshSimple<api>(), true);
   7806 		if (!_program)
   7807 		{
   7808 			return ERROR;
   7809 		}
   7810 		glUseProgram(_program);
   7811 
   7812 		glGenVertexArrays(1, &_vao);
   7813 		glBindVertexArray(_vao);
   7814 
   7815 		std::vector<GLuint> zarro(4096, 0);
   7816 
   7817 		glGenBuffers(1, &_buffer);
   7818 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   7819 		glBufferData(GL_ARRAY_BUFFER, 4096, &zarro[0], GL_STREAM_DRAW);
   7820 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
   7821 		glEnableVertexAttribArray(0);
   7822 
   7823 		glGenBuffers(1, &_bufferIndirect);
   7824 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   7825 		glBufferData(GL_DRAW_INDIRECT_BUFFER, 4096, &zarro[0], GL_STATIC_DRAW);
   7826 
   7827 		glGenBuffers(1, &_ebo);
   7828 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   7829 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4096, &zarro[0], GL_STATIC_DRAW);
   7830 
   7831 		DIResult result;
   7832 
   7833 		int offsets[] = { 1, 3, 1023 };
   7834 		for (size_t i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++)
   7835 		{
   7836 			glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, reinterpret_cast<void*>((deUintptr)offsets[i]));
   7837 			if (glGetError() != GL_INVALID_VALUE)
   7838 			{
   7839 				result.error() << "Invalid error code returned by a driver for GL_INVALID_VALUE type";
   7840 			}
   7841 			glDrawArraysIndirect(GL_TRIANGLES, reinterpret_cast<void*>((deUintptr)offsets[i]));
   7842 			if (glGetError() != GL_INVALID_VALUE)
   7843 			{
   7844 				result.error() << "Invalid error code returned by a driver for GL_INVALID_VALUE type";
   7845 			}
   7846 		}
   7847 
   7848 		return result.code();
   7849 	}
   7850 
   7851 	virtual long Cleanup()
   7852 	{
   7853 		glDisableVertexAttribArray(0);
   7854 		glUseProgram(0);
   7855 		glDeleteProgram(_program);
   7856 		glDeleteVertexArrays(1, &_vao);
   7857 		glDeleteBuffers(1, &_buffer);
   7858 		glDeleteBuffers(1, &_ebo);
   7859 		glDeleteBuffers(1, &_bufferIndirect);
   7860 		return NO_ERROR;
   7861 	}
   7862 
   7863 private:
   7864 	GLuint _program;
   7865 	GLuint _vao, _buffer, _ebo, _bufferIndirect;
   7866 };
   7867 
   7868 template <typename api>
   7869 struct CNegativeXFB : public DrawIndirectBase
   7870 {
   7871 	virtual std::string Title()
   7872 	{
   7873 		return "Negative: transform feedback active and not paused - glDrawElementsIndirect and glDrawArraysIndirect";
   7874 	}
   7875 
   7876 	virtual std::string Purpose()
   7877 	{
   7878 		return "Verify that a driver sets error and no system/driver crash occurred";
   7879 	}
   7880 
   7881 	virtual std::string Method()
   7882 	{
   7883 		return "Call with transform feedback active";
   7884 	}
   7885 
   7886 	virtual std::string PassCriteria()
   7887 	{
   7888 		return "The test will pass if OpenGL errors reported and no driver crash occurred";
   7889 	}
   7890 
   7891 	virtual long Run()
   7892 	{
   7893 		api::ES_Only();
   7894 
   7895 		bool drawWithXFBAllowed = m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader");
   7896 
   7897 		_program				 = CreateProgram(Vsh(), "", shaders::fshSimple<api>(), false);
   7898 		const GLchar* varyings[] = { "dataOut" };
   7899 		glTransformFeedbackVaryings(_program, 1, varyings, GL_INTERLEAVED_ATTRIBS);
   7900 		glLinkProgram(_program);
   7901 		if (!CheckProgram(_program))
   7902 		{
   7903 			return ERROR;
   7904 		}
   7905 		glUseProgram(_program);
   7906 
   7907 		glGenVertexArrays(1, &_vao);
   7908 		glBindVertexArray(_vao);
   7909 
   7910 		std::vector<GLuint> zarro(4096, 0);
   7911 
   7912 		glGenBuffers(1, &_buffer);
   7913 		glBindBuffer(GL_ARRAY_BUFFER, _buffer);
   7914 		glBufferData(GL_ARRAY_BUFFER, 4096, &zarro[0], GL_STREAM_DRAW);
   7915 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
   7916 		glEnableVertexAttribArray(0);
   7917 
   7918 		glGenBuffers(1, &_bufferIndirect);
   7919 		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _bufferIndirect);
   7920 		glBufferData(GL_DRAW_INDIRECT_BUFFER, 4096, &zarro[0], GL_STATIC_DRAW);
   7921 
   7922 		glGenBuffers(1, &_ebo);
   7923 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
   7924 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4096, &zarro[0], GL_STATIC_DRAW);
   7925 
   7926 		glGenBuffers(1, &_xfb);
   7927 		glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, _xfb);
   7928 		glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 4096, &zarro[0], GL_STATIC_DRAW);
   7929 		glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, _xfb);
   7930 
   7931 		DIResult result;
   7932 
   7933 		//Without XFO
   7934 		glBeginTransformFeedback(GL_POINTS);
   7935 
   7936 		glDrawElementsIndirect(GL_POINTS, GL_UNSIGNED_INT, NULL);
   7937 		if (!drawWithXFBAllowed && glGetError() != GL_INVALID_OPERATION)
   7938 		{
   7939 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7940 		}
   7941 		glDrawArraysIndirect(GL_POINTS, NULL);
   7942 		if (!drawWithXFBAllowed && glGetError() != GL_INVALID_OPERATION)
   7943 		{
   7944 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7945 		}
   7946 		glEndTransformFeedback();
   7947 
   7948 		//With XFO
   7949 		glGenTransformFeedbacks(1, &_xfo);
   7950 		glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, _xfo);
   7951 		glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, _xfb);
   7952 		glBeginTransformFeedback(GL_POINTS);
   7953 		glPauseTransformFeedback();
   7954 		glResumeTransformFeedback();
   7955 
   7956 		glDrawElementsIndirect(GL_POINTS, GL_UNSIGNED_INT, NULL);
   7957 		if (!drawWithXFBAllowed && glGetError() != GL_INVALID_OPERATION)
   7958 		{
   7959 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7960 		}
   7961 		glDrawArraysIndirect(GL_POINTS, NULL);
   7962 		if (!drawWithXFBAllowed && glGetError() != GL_INVALID_OPERATION)
   7963 		{
   7964 			result.error() << "Invalid error code returned by a driver for GL_INVALID_OPERATION type";
   7965 		}
   7966 		glEndTransformFeedback();
   7967 
   7968 		glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
   7969 		return result.code();
   7970 	}
   7971 
   7972 	virtual long Cleanup()
   7973 	{
   7974 		glDisableVertexAttribArray(0);
   7975 		glUseProgram(0);
   7976 		glDeleteProgram(_program);
   7977 		glDeleteVertexArrays(1, &_vao);
   7978 		glDeleteBuffers(1, &_buffer);
   7979 		glDeleteBuffers(1, &_ebo);
   7980 		glDeleteBuffers(1, &_bufferIndirect);
   7981 		glDeleteBuffers(1, &_xfb);
   7982 		glDeleteTransformFeedbacks(1, &_xfo);
   7983 		return NO_ERROR;
   7984 	}
   7985 
   7986 	std::string Vsh()
   7987 	{
   7988 		return api::glslVer() + NL "out highp vec4 dataOut;" NL "in vec4 i_vertex;" NL "void main() {" NL
   7989 								   "  dataOut = i_vertex;" NL "  gl_Position = i_vertex;" NL "}";
   7990 	}
   7991 
   7992 private:
   7993 	GLuint _program;
   7994 	GLuint _vao, _buffer, _ebo, _bufferIndirect, _xfo, _xfb;
   7995 };
   7996 
   7997 } // namespace
   7998 DrawIndirectTestsGL40::DrawIndirectTestsGL40(glcts::Context& context) : TestCaseGroup(context, "draw_indirect", "")
   7999 {
   8000 }
   8001 
   8002 DrawIndirectTestsGL40::~DrawIndirectTestsGL40(void)
   8003 {
   8004 }
   8005 
   8006 void DrawIndirectTestsGL40::init()
   8007 {
   8008 	using namespace glcts;
   8009 
   8010 	DILogger::setOutput(m_context.getTestContext().getLog());
   8011 
   8012 	addChild(
   8013 		new TestSubcase(m_context, "basic-binding-default", TestSubcase::Create<CDefaultBindingPoint<test_api::GL> >));
   8014 	addChild(new TestSubcase(m_context, "basic-binding-zero", TestSubcase::Create<CZeroBindingPoint<test_api::GL> >));
   8015 	addChild(
   8016 		new TestSubcase(m_context, "basic-binding-single", TestSubcase::Create<CSingleBindingPoint<test_api::GL> >));
   8017 	addChild(new TestSubcase(m_context, "basic-binding-multi", TestSubcase::Create<CMultiBindingPoint<test_api::GL> >));
   8018 	addChild(
   8019 		new TestSubcase(m_context, "basic-binding-delete", TestSubcase::Create<CDeleteBindingPoint<test_api::GL> >));
   8020 
   8021 	addChild(new TestSubcase(m_context, "basic-buffer-data", TestSubcase::Create<CBufferData<test_api::GL> >));
   8022 	addChild(new TestSubcase(m_context, "basic-buffer-subData", TestSubcase::Create<CBufferSubData<test_api::GL> >));
   8023 	addChild(new TestSubcase(m_context, "basic-buffer-unMap", TestSubcase::Create<CBufferMap<test_api::GL> >));
   8024 	addChild(
   8025 		new TestSubcase(m_context, "basic-buffer-getPointerv", TestSubcase::Create<CBufferGetPointerv<test_api::GL> >));
   8026 	addChild(new TestSubcase(m_context, "basic-buffer-mapRange", TestSubcase::Create<CBufferMapRange<test_api::GL> >));
   8027 	addChild(new TestSubcase(m_context, "basic-buffer-flushMappedRange",
   8028 							 TestSubcase::Create<CBufferFlushMappedRange<test_api::GL> >));
   8029 	addChild(
   8030 		new TestSubcase(m_context, "basic-buffer-copySubData", TestSubcase::Create<CBufferCopySubData<test_api::GL> >));
   8031 
   8032 	addChild(new TestSubcase(m_context, "basic-drawArrays-singlePrimitive",
   8033 							 TestSubcase::Create<CVBODrawArraysSingle<test_api::GL> >));
   8034 	addChild(new TestSubcase(m_context, "basic-drawArrays-manyPrimitives",
   8035 							 TestSubcase::Create<CVBODrawArraysMany<test_api::GL> >));
   8036 	addChild(new TestSubcase(m_context, "basic-drawArrays-instancing",
   8037 							 TestSubcase::Create<CVBODrawArraysInstancing<test_api::GL> >));
   8038 	addChild(new TestSubcase(m_context, "basic-drawArrays-xfbPaused",
   8039 							 TestSubcase::Create<CVBODrawArraysXFBPaused<test_api::GL> >));
   8040 	addChild(new TestSubcase(m_context, "basic-drawElements-singlePrimitive",
   8041 							 TestSubcase::Create<CVBODrawElementsSingle<test_api::GL> >));
   8042 	addChild(new TestSubcase(m_context, "basic-drawElements-manyPrimitives",
   8043 							 TestSubcase::Create<CVBODrawElementsMany<test_api::GL> >));
   8044 	addChild(new TestSubcase(m_context, "basic-drawElements-instancing",
   8045 							 TestSubcase::Create<CVBODrawElementsInstancing<test_api::GL> >));
   8046 	addChild(new TestSubcase(m_context, "basic-drawElements-xfbPaused",
   8047 							 TestSubcase::Create<CVBODrawArraysXFBPaused<test_api::GL> >));
   8048 
   8049 	addChild(new TestSubcase(m_context, "basic-drawArrays-simple",
   8050 							 TestSubcase::Create<CBufferIndirectDrawArraysSimple<test_api::GL> >));
   8051 	addChild(new TestSubcase(m_context, "basic-drawArrays-noFirst",
   8052 							 TestSubcase::Create<CBufferIndirectDrawArraysNoFirst<test_api::GL> >));
   8053 	addChild(new TestSubcase(m_context, "basic-drawArrays-bufferOffset",
   8054 							 TestSubcase::Create<CBufferIndirectDrawArraysOffset<test_api::GL> >));
   8055 	addChild(new TestSubcase(m_context, "basic-drawArrays-vertexIds",
   8056 							 TestSubcase::Create<CBufferIndirectDrawArraysVertexIds<test_api::GL> >));
   8057 	addChild(new TestSubcase(m_context, "basic-drawElements-simple",
   8058 							 TestSubcase::Create<CBufferIndirectDrawElementsSimple<test_api::GL> >));
   8059 	addChild(new TestSubcase(m_context, "basic-drawElements-noFirstIndex",
   8060 							 TestSubcase::Create<CBufferIndirectDrawElementsNoFirstIndex<test_api::GL> >));
   8061 	addChild(new TestSubcase(m_context, "basic-drawElements-basevertex",
   8062 							 TestSubcase::Create<CBufferIndirectDrawElementsNoBasevertex<test_api::GL> >));
   8063 	addChild(new TestSubcase(m_context, "basic-drawElements-bufferOffset",
   8064 							 TestSubcase::Create<CBufferIndirectDrawElementsOffset<test_api::GL> >));
   8065 	addChild(new TestSubcase(m_context, "basic-drawElements-vertexIds",
   8066 							 TestSubcase::Create<CBufferIndirectDrawElementsVertexIds<test_api::GL> >));
   8067 
   8068 	addChild(new TestSubcase(m_context, "basic-indicesDataType-unsigned_short",
   8069 							 TestSubcase::Create<CIndicesDataTypeUnsignedShort<test_api::GL> >));
   8070 	addChild(new TestSubcase(m_context, "basic-indicesDataType-unsigned_byte",
   8071 							 TestSubcase::Create<CIndicesDataTypeUnsignedByte<test_api::GL> >));
   8072 
   8073 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-points",
   8074 							 TestSubcase::Create<CModeDrawArraysPoints<test_api::GL> >));
   8075 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-lines",
   8076 							 TestSubcase::Create<CModeDrawArraysLines<test_api::GL> >));
   8077 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-line_strip",
   8078 							 TestSubcase::Create<CModeDrawArraysLineStrip<test_api::GL> >));
   8079 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-line_loop",
   8080 							 TestSubcase::Create<CModeDrawArraysLineLoop<test_api::GL> >));
   8081 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangle_strip",
   8082 							 TestSubcase::Create<CModeDrawArraysTriangleStrip<test_api::GL> >));
   8083 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangle_fan",
   8084 							 TestSubcase::Create<CModeDrawArraysTriangleFan<test_api::GL> >));
   8085 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-lines_adjacency",
   8086 							 TestSubcase::Create<CModeDrawArraysLinesAdjacency<test_api::GL> >));
   8087 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-line_strip_adjacency",
   8088 							 TestSubcase::Create<CModeDrawArraysLineStripAdjacency<test_api::GL> >));
   8089 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangles_adjacency",
   8090 							 TestSubcase::Create<CModeDrawArraysTrianglesAdjacency<test_api::GL> >));
   8091 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangle_strip_adjacency",
   8092 							 TestSubcase::Create<CModeDrawArraysTriangleStripAdjacency<test_api::GL> >));
   8093 
   8094 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-points",
   8095 							 TestSubcase::Create<CModeDrawElementsPoints<test_api::GL> >));
   8096 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-lines",
   8097 							 TestSubcase::Create<CModeDrawElementsLines<test_api::GL> >));
   8098 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-line_strip",
   8099 							 TestSubcase::Create<CModeDrawElementsLineStrip<test_api::GL> >));
   8100 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-line_loop",
   8101 							 TestSubcase::Create<CModeDrawElementsLineLoop<test_api::GL> >));
   8102 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangle_strip",
   8103 							 TestSubcase::Create<CModeDrawElementsTriangleStrip<test_api::GL> >));
   8104 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangle_fan",
   8105 							 TestSubcase::Create<CModeDrawElementsTriangleFan<test_api::GL> >));
   8106 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-lines_adjacency",
   8107 							 TestSubcase::Create<CModeDrawElementsLinesAdjacency<test_api::GL> >));
   8108 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-line_strip_adjacency",
   8109 							 TestSubcase::Create<CModeDrawElementsLineStripAdjacency<test_api::GL> >));
   8110 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangles_adjacency",
   8111 							 TestSubcase::Create<CModeDrawElementsTrianglesAdjacency<test_api::GL> >));
   8112 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangle_strip_adjacency",
   8113 							 TestSubcase::Create<CModeDrawElementsTriangleStripAdjacency<test_api::GL> >));
   8114 
   8115 	addChild(new TestSubcase(m_context, "advanced-twoPass-transformFeedback-arrays",
   8116 							 TestSubcase::Create<CTransformFeedbackArray<test_api::GL> >));
   8117 	addChild(new TestSubcase(m_context, "advanced-twoPass-transformFeedback-elements",
   8118 							 TestSubcase::Create<CTransformFeedbackElements<test_api::GL> >));
   8119 
   8120 	addChild(new TestSubcase(m_context, "advanced-primitiveRestart-elements",
   8121 							 TestSubcase::Create<CPrimitiveRestartElements<test_api::GL> >));
   8122 
   8123 	addChild(new TestSubcase(m_context, "misc-reservedMustBeZero-arrays",
   8124 							 TestSubcase::Create<CNonZeroReservedMustBeZeroArray<test_api::GL> >));
   8125 	addChild(new TestSubcase(m_context, "misc-reservedMustBeZero-elements",
   8126 							 TestSubcase::Create<CNonZeroReservedMustBeZeroElements<test_api::GL> >));
   8127 
   8128 	addChild(new TestSubcase(m_context, "negative-noindirect-arrays",
   8129 							 TestSubcase::Create<CNegativeZeroBufferArray<test_api::GL> >));
   8130 	addChild(new TestSubcase(m_context, "negative-noindirect-elements",
   8131 							 TestSubcase::Create<CNegativeZeroBufferElements<test_api::GL> >));
   8132 	addChild(new TestSubcase(m_context, "negative-invalidMode-arrays",
   8133 							 TestSubcase::Create<CNegativeInvalidModeArray<test_api::GL> >));
   8134 	addChild(new TestSubcase(m_context, "negative-invalidMode-elements",
   8135 							 TestSubcase::Create<CNegativeInvalidModeElements<test_api::GL> >));
   8136 	addChild(
   8137 		new TestSubcase(m_context, "negative-noVAO-arrays", TestSubcase::Create<CNegativeNoVAOArrays<test_api::GL> >));
   8138 	addChild(new TestSubcase(m_context, "negative-noVAO-elements",
   8139 							 TestSubcase::Create<CNegativeNoVAOElements<test_api::GL> >));
   8140 	addChild(new TestSubcase(m_context, "negative-bufferMapped-arrays",
   8141 							 TestSubcase::Create<CNegativeBufferMappedArray<test_api::GL> >));
   8142 	addChild(new TestSubcase(m_context, "negative-bufferMapped-elements",
   8143 							 TestSubcase::Create<CNegativeBufferMappedElements<test_api::GL> >));
   8144 	addChild(new TestSubcase(m_context, "negative-invalidType-elements",
   8145 							 TestSubcase::Create<CNegativeDataWrongElements<test_api::GL> >));
   8146 	addChild(new TestSubcase(m_context, "negative-gshIncompatible-arrays",
   8147 							 TestSubcase::Create<CNegativeGshArray<test_api::GL> >));
   8148 	addChild(new TestSubcase(m_context, "negative-gshIncompatible-elements",
   8149 							 TestSubcase::Create<CNegativeGshElements<test_api::GL> >));
   8150 	addChild(new TestSubcase(m_context, "negative-wrongOffset-arrays",
   8151 							 TestSubcase::Create<CNegativeStructureWrongOffsetArray<test_api::GL> >));
   8152 	addChild(new TestSubcase(m_context, "negative-wrongOffset-elements",
   8153 							 TestSubcase::Create<CNegativeStructureWrongOffsetElements<test_api::GL> >));
   8154 	addChild(new TestSubcase(m_context, "negative-invalidSize-arrays",
   8155 							 TestSubcase::Create<CNegativeInvalidSizeArrays<test_api::GL> >));
   8156 	addChild(new TestSubcase(m_context, "negative-invalidSize-elements",
   8157 							 TestSubcase::Create<CNegativeInvalidSizeElements<test_api::GL> >));
   8158 	addChild(new TestSubcase(m_context, "negative-unalignedOffset",
   8159 							 TestSubcase::Create<CNegativeUnalignedOffset<test_api::GL> >));
   8160 }
   8161 
   8162 DrawIndirectTestsGL43::DrawIndirectTestsGL43(glcts::Context& context) : TestCaseGroup(context, "draw_indirect_43", "")
   8163 {
   8164 }
   8165 
   8166 DrawIndirectTestsGL43::~DrawIndirectTestsGL43(void)
   8167 {
   8168 }
   8169 
   8170 void DrawIndirectTestsGL43::init()
   8171 {
   8172 	using namespace glcts;
   8173 
   8174 	DILogger::setOutput(m_context.getTestContext().getLog());
   8175 	addChild(new TestSubcase(m_context, "advanced-twoPass-Compute-arrays",
   8176 							 TestSubcase::Create<CComputeShaderArray<test_api::GL> >));
   8177 	addChild(new TestSubcase(m_context, "advanced-twoPass-Compute-elements",
   8178 							 TestSubcase::Create<CComputeShaderElements<test_api::GL> >));
   8179 }
   8180 
   8181 DrawIndirectTestsES31::DrawIndirectTestsES31(glcts::Context& context) : TestCaseGroup(context, "draw_indirect", "")
   8182 {
   8183 }
   8184 
   8185 DrawIndirectTestsES31::~DrawIndirectTestsES31(void)
   8186 {
   8187 }
   8188 
   8189 void DrawIndirectTestsES31::init()
   8190 {
   8191 	using namespace glcts;
   8192 
   8193 	DILogger::setOutput(m_context.getTestContext().getLog());
   8194 
   8195 	addChild(
   8196 		new TestSubcase(m_context, "basic-binding-default", TestSubcase::Create<CDefaultBindingPoint<test_api::ES3> >));
   8197 	addChild(new TestSubcase(m_context, "basic-binding-zero", TestSubcase::Create<CZeroBindingPoint<test_api::ES3> >));
   8198 	addChild(
   8199 		new TestSubcase(m_context, "basic-binding-single", TestSubcase::Create<CSingleBindingPoint<test_api::ES3> >));
   8200 	addChild(
   8201 		new TestSubcase(m_context, "basic-binding-multi", TestSubcase::Create<CMultiBindingPoint<test_api::ES3> >));
   8202 	addChild(
   8203 		new TestSubcase(m_context, "basic-binding-delete", TestSubcase::Create<CDeleteBindingPoint<test_api::ES3> >));
   8204 
   8205 	addChild(new TestSubcase(m_context, "basic-buffer-data", TestSubcase::Create<CBufferData<test_api::ES3> >));
   8206 	addChild(new TestSubcase(m_context, "basic-buffer-subData", TestSubcase::Create<CBufferSubData<test_api::ES3> >));
   8207 	addChild(new TestSubcase(m_context, "basic-buffer-getPointerv",
   8208 							 TestSubcase::Create<CBufferGetPointerv<test_api::ES3> >));
   8209 	addChild(new TestSubcase(m_context, "basic-buffer-mapRange", TestSubcase::Create<CBufferMapRange<test_api::ES3> >));
   8210 	addChild(new TestSubcase(m_context, "basic-buffer-flushMappedRange",
   8211 							 TestSubcase::Create<CBufferFlushMappedRange<test_api::ES3> >));
   8212 	addChild(new TestSubcase(m_context, "basic-buffer-copySubData",
   8213 							 TestSubcase::Create<CBufferCopySubData<test_api::ES3> >));
   8214 
   8215 	addChild(new TestSubcase(m_context, "basic-drawArrays-singlePrimitive",
   8216 							 TestSubcase::Create<CVBODrawArraysSingle<test_api::ES3> >));
   8217 	addChild(new TestSubcase(m_context, "basic-drawArrays-manyPrimitives",
   8218 							 TestSubcase::Create<CVBODrawArraysMany<test_api::ES3> >));
   8219 	addChild(new TestSubcase(m_context, "basic-drawArrays-instancing",
   8220 							 TestSubcase::Create<CVBODrawArraysInstancing<test_api::ES3> >));
   8221 	addChild(new TestSubcase(m_context, "basic-drawArrays-xfbPaused",
   8222 							 TestSubcase::Create<CVBODrawArraysXFBPaused<test_api::ES3> >));
   8223 	addChild(new TestSubcase(m_context, "basic-drawElements-singlePrimitive",
   8224 							 TestSubcase::Create<CVBODrawElementsSingle<test_api::ES3> >));
   8225 	addChild(new TestSubcase(m_context, "basic-drawElements-manyPrimitives",
   8226 							 TestSubcase::Create<CVBODrawElementsMany<test_api::ES3> >));
   8227 	addChild(new TestSubcase(m_context, "basic-drawElements-instancing",
   8228 							 TestSubcase::Create<CVBODrawElementsInstancing<test_api::ES3> >));
   8229 	addChild(new TestSubcase(m_context, "basic-drawElements-xfbPaused",
   8230 							 TestSubcase::Create<CVBODrawArraysXFBPaused<test_api::ES3> >));
   8231 
   8232 	addChild(new TestSubcase(m_context, "basic-drawArrays-simple",
   8233 							 TestSubcase::Create<CBufferIndirectDrawArraysSimple<test_api::ES3> >));
   8234 	addChild(new TestSubcase(m_context, "basic-drawArrays-noFirst",
   8235 							 TestSubcase::Create<CBufferIndirectDrawArraysNoFirst<test_api::ES3> >));
   8236 	addChild(new TestSubcase(m_context, "basic-drawArrays-bufferOffset",
   8237 							 TestSubcase::Create<CBufferIndirectDrawArraysOffset<test_api::ES3> >));
   8238 	addChild(new TestSubcase(m_context, "basic-drawArrays-vertexIds",
   8239 							 TestSubcase::Create<CBufferIndirectDrawArraysVertexIds<test_api::ES3> >));
   8240 	addChild(new TestSubcase(m_context, "basic-drawElements-simple",
   8241 							 TestSubcase::Create<CBufferIndirectDrawElementsSimple<test_api::ES3> >));
   8242 	addChild(new TestSubcase(m_context, "basic-drawElements-noFirstIndex",
   8243 							 TestSubcase::Create<CBufferIndirectDrawElementsNoFirstIndex<test_api::ES3> >));
   8244 	addChild(new TestSubcase(m_context, "basic-drawElements-basevertex",
   8245 							 TestSubcase::Create<CBufferIndirectDrawElementsNoBasevertex<test_api::ES3> >));
   8246 	addChild(new TestSubcase(m_context, "basic-drawElements-bufferOffset",
   8247 							 TestSubcase::Create<CBufferIndirectDrawElementsOffset<test_api::ES3> >));
   8248 	addChild(new TestSubcase(m_context, "basic-drawElements-vertexIds",
   8249 							 TestSubcase::Create<CBufferIndirectDrawElementsVertexIds<test_api::ES3> >));
   8250 
   8251 	addChild(new TestSubcase(m_context, "basic-indicesDataType-unsigned_short",
   8252 							 TestSubcase::Create<CIndicesDataTypeUnsignedShort<test_api::ES3> >));
   8253 	addChild(new TestSubcase(m_context, "basic-indicesDataType-unsigned_byte",
   8254 							 TestSubcase::Create<CIndicesDataTypeUnsignedByte<test_api::ES3> >));
   8255 
   8256 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-points",
   8257 							 TestSubcase::Create<CModeDrawArraysPoints<test_api::ES3> >));
   8258 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-lines",
   8259 							 TestSubcase::Create<CModeDrawArraysLines<test_api::ES3> >));
   8260 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-line_strip",
   8261 							 TestSubcase::Create<CModeDrawArraysLineStrip<test_api::ES3> >));
   8262 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-line_loop",
   8263 							 TestSubcase::Create<CModeDrawArraysLineLoop<test_api::ES3> >));
   8264 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangle_strip",
   8265 							 TestSubcase::Create<CModeDrawArraysTriangleStrip<test_api::ES3> >));
   8266 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangle_fan",
   8267 							 TestSubcase::Create<CModeDrawArraysTriangleFan<test_api::ES3> >));
   8268 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-lines_adjacency",
   8269 							 TestSubcase::Create<CModeDrawArraysLinesAdjacency<test_api::ES3> >));
   8270 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-line_strip_adjacency",
   8271 							 TestSubcase::Create<CModeDrawArraysLineStripAdjacency<test_api::ES3> >));
   8272 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangles_adjacency",
   8273 							 TestSubcase::Create<CModeDrawArraysTrianglesAdjacency<test_api::ES3> >));
   8274 	addChild(new TestSubcase(m_context, "basic-mode-drawArrays-triangle_strip_adjacency",
   8275 							 TestSubcase::Create<CModeDrawArraysTriangleStripAdjacency<test_api::ES3> >));
   8276 
   8277 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-points",
   8278 							 TestSubcase::Create<CModeDrawElementsPoints<test_api::ES3> >));
   8279 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-lines",
   8280 							 TestSubcase::Create<CModeDrawElementsLines<test_api::ES3> >));
   8281 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-line_strip",
   8282 							 TestSubcase::Create<CModeDrawElementsLineStrip<test_api::ES3> >));
   8283 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-line_loop",
   8284 							 TestSubcase::Create<CModeDrawElementsLineLoop<test_api::ES3> >));
   8285 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangle_strip",
   8286 							 TestSubcase::Create<CModeDrawElementsTriangleStrip<test_api::ES3> >));
   8287 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangle_fan",
   8288 							 TestSubcase::Create<CModeDrawElementsTriangleFan<test_api::ES3> >));
   8289 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-lines_adjacency",
   8290 							 TestSubcase::Create<CModeDrawElementsLinesAdjacency<test_api::ES3> >));
   8291 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-line_strip_adjacency",
   8292 							 TestSubcase::Create<CModeDrawElementsLineStripAdjacency<test_api::ES3> >));
   8293 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangles_adjacency",
   8294 							 TestSubcase::Create<CModeDrawElementsTrianglesAdjacency<test_api::ES3> >));
   8295 	addChild(new TestSubcase(m_context, "basic-mode-drawElements-triangle_strip_adjacency",
   8296 							 TestSubcase::Create<CModeDrawElementsTriangleStripAdjacency<test_api::ES3> >));
   8297 
   8298 	addChild(new TestSubcase(m_context, "advanced-twoPass-transformFeedback-arrays",
   8299 							 TestSubcase::Create<CTransformFeedbackArray<test_api::ES3> >));
   8300 	addChild(new TestSubcase(m_context, "advanced-twoPass-transformFeedback-elements",
   8301 							 TestSubcase::Create<CTransformFeedbackElements<test_api::ES3> >));
   8302 
   8303 	addChild(new TestSubcase(m_context, "advanced-twoPass-Compute-arrays",
   8304 							 TestSubcase::Create<CComputeShaderArray<test_api::ES3> >));
   8305 	addChild(new TestSubcase(m_context, "advanced-twoPass-Compute-elements",
   8306 							 TestSubcase::Create<CComputeShaderElements<test_api::ES3> >));
   8307 
   8308 	addChild(new TestSubcase(m_context, "advanced-primitiveRestart-elements",
   8309 							 TestSubcase::Create<CPrimitiveRestartElements<test_api::ES3> >));
   8310 
   8311 	addChild(new TestSubcase(m_context, "misc-reservedMustBeZero-arrays",
   8312 							 TestSubcase::Create<CNonZeroReservedMustBeZeroArray<test_api::ES3> >));
   8313 	addChild(new TestSubcase(m_context, "misc-reservedMustBeZero-elements",
   8314 							 TestSubcase::Create<CNonZeroReservedMustBeZeroElements<test_api::ES3> >));
   8315 
   8316 	addChild(new TestSubcase(m_context, "negative-noindirect-arrays",
   8317 							 TestSubcase::Create<CNegativeZeroBufferArray<test_api::ES3> >));
   8318 	addChild(new TestSubcase(m_context, "negative-noindirect-elements",
   8319 							 TestSubcase::Create<CNegativeZeroBufferElements<test_api::ES3> >));
   8320 	addChild(new TestSubcase(m_context, "negative-invalidMode-arrays",
   8321 							 TestSubcase::Create<CNegativeInvalidModeArray<test_api::ES3> >));
   8322 	addChild(new TestSubcase(m_context, "negative-invalidMode-elements",
   8323 							 TestSubcase::Create<CNegativeInvalidModeElements<test_api::ES3> >));
   8324 	addChild(
   8325 		new TestSubcase(m_context, "negative-noVAO-arrays", TestSubcase::Create<CNegativeNoVAOArrays<test_api::ES3> >));
   8326 	addChild(new TestSubcase(m_context, "negative-noVAO-elements",
   8327 							 TestSubcase::Create<CNegativeNoVAOElements<test_api::ES3> >));
   8328 	addChild(
   8329 		new TestSubcase(m_context, "negative-noVBO-arrays", TestSubcase::Create<CNegativeNoVBOArrays<test_api::ES3> >));
   8330 	addChild(new TestSubcase(m_context, "negative-noVBO-elements",
   8331 							 TestSubcase::Create<CNegativeNoVBOElements<test_api::ES3> >));
   8332 	addChild(new TestSubcase(m_context, "negative-bufferMapped-arrays",
   8333 							 TestSubcase::Create<CNegativeBufferMappedArray<test_api::ES3> >));
   8334 	addChild(new TestSubcase(m_context, "negative-bufferMapped-elements",
   8335 							 TestSubcase::Create<CNegativeBufferMappedElements<test_api::ES3> >));
   8336 	addChild(new TestSubcase(m_context, "negative-invalidType-elements",
   8337 							 TestSubcase::Create<CNegativeDataWrongElements<test_api::ES3> >));
   8338 
   8339 	addChild(new TestSubcase(m_context, "negative-wrongOffset-arrays",
   8340 							 TestSubcase::Create<CNegativeStructureWrongOffsetArray<test_api::ES3> >));
   8341 	addChild(new TestSubcase(m_context, "negative-wrongOffset-elements",
   8342 							 TestSubcase::Create<CNegativeStructureWrongOffsetElements<test_api::ES3> >));
   8343 	addChild(new TestSubcase(m_context, "negative-invalidSize-arrays",
   8344 							 TestSubcase::Create<CNegativeInvalidSizeArrays<test_api::ES3> >));
   8345 	addChild(new TestSubcase(m_context, "negative-invalidSize-elements",
   8346 							 TestSubcase::Create<CNegativeInvalidSizeElements<test_api::ES3> >));
   8347 	addChild(new TestSubcase(m_context, "negative-unalignedOffset",
   8348 							 TestSubcase::Create<CNegativeUnalignedOffset<test_api::ES3> >));
   8349 	addChild(new TestSubcase(m_context, "negative-xfb", TestSubcase::Create<CNegativeXFB<test_api::ES3> >));
   8350 }
   8351 }
   8352