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
33namespace glcts
34{
35using namespace glw;
36namespace
37{
38
39class DILogger
40{
41public:
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
85private:
86	void				 operator=(const DILogger&);
87	bool				 null_log_;
88	std::ostringstream   str_;
89	static tcu::TestLog* s_tcuLog;
90};
91tcu::TestLog* DILogger::s_tcuLog = NULL;
92
93class DIResult
94{
95public:
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
120private:
121	DILogger sub_result_inner(long _code)
122	{
123		status_ |= _code;
124		return DILogger();
125	}
126	DILogger logger_;
127	long	 status_;
128};
129
130namespace test_api
131{
132struct 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
147struct 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
170namespace shaders
171{
172
173template <typename api>
174std::string vshSimple()
175{
176	return api::glslVer() + NL "in vec4 i_vertex;" NL "void main()" NL "{" NL "    gl_Position = i_vertex;" NL "}";
177}
178template <typename api>
179std::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
185template <typename api>
186std::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
193class DrawIndirectBase : public glcts::SubcaseBase
194{
195protected:
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
821template <>
822void 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
827template <>
828void 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
839template <>
840void DrawIndirectBase::GetBufferSubData<test_api::GL>(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data)
841{
842	glGetBufferSubData(target, offset, size, data);
843}
844
845template <>
846void 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
853template <typename api>
854struct 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
882template <typename api>
883struct 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
913template <typename api>
914struct 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
952private:
953	GLuint _buffer;
954};
955
956template <typename api>
957class CMultiBindingPoint : public DrawIndirectBase
958{
959public:
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
1003private:
1004	GLuint _buffers[10];
1005};
1006
1007template <typename api>
1008struct 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
1038private:
1039	GLuint _buffer;
1040};
1041
1042template <typename api>
1043struct 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
1196private:
1197	GLuint _buffers[10];
1198};
1199
1200template <typename api>
1201struct 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
1264private:
1265	GLuint _buffer;
1266};
1267
1268template <typename api>
1269struct 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
1385private:
1386	GLuint _buffer;
1387};
1388
1389template <typename api>
1390struct 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
1480private:
1481	GLuint _buffer;
1482};
1483
1484template <class api>
1485struct 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
1604private:
1605	GLuint _buffer;
1606};
1607
1608template <class api>
1609struct 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
1702private:
1703	GLuint _buffer;
1704};
1705
1706template <class api>
1707struct 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
1785private:
1786	GLuint _buffer;
1787};
1788
1789template <class api>
1790struct 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
1855private:
1856	GLuint _buffers[2];
1857};
1858
1859template <class api>
1860struct 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
1941private:
1942	GLuint _buffers[2];
1943};
1944
1945class CBasicVertexDef : public DrawIndirectBase
1946{
1947public:
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
2083private:
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
2098class CBasicVertexInstancingDef : public DrawIndirectBase
2099{
2100public:
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
2300private:
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
2314template <typename api>
2315class CVBODrawArraysSingle : public CBasicVertexDef
2316{
2317public:
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
2348template <typename api>
2349class CVBODrawArraysMany : public CBasicVertexDef
2350{
2351public:
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
2382template <typename api>
2383class CVBODrawArraysInstancing : public CBasicVertexInstancingDef
2384{
2385public:
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
2416class CBasicXFBPausedDef : public DrawIndirectBase
2417{
2418public:
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
2581private:
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
2596template <typename api>
2597class CVBODrawArraysXFBPaused : public CBasicXFBPausedDef
2598{
2599public:
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
2630template <typename api>
2631class CVBODrawElementsSingle : public CBasicVertexDef
2632{
2633public:
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
2664template <typename api>
2665class CVBODrawElementsMany : public CBasicVertexDef
2666{
2667public:
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
2699template <typename api>
2700class CVBODrawElementsInstancing : public CBasicVertexInstancingDef
2701{
2702public:
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
2733template <typename api>
2734class CVBODrawElementsXFBPaused : public CBasicXFBPausedDef
2735{
2736public:
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
2767template <typename api>
2768class CBufferIndirectDrawArraysSimple : public DrawIndirectBase
2769{
2770public:
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
2854private:
2855	GLuint _program;
2856	GLuint _vao, _buffer, _bufferIndirect;
2857};
2858
2859template <typename api>
2860class CBufferIndirectDrawArraysNoFirst : public DrawIndirectBase
2861{
2862public:
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
2952private:
2953	GLuint _program;
2954	GLuint _vao, _buffer, _bufferIndirect;
2955};
2956
2957template <typename api>
2958class CBufferIndirectDrawArraysOffset : public DrawIndirectBase
2959{
2960public:
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
3045private:
3046	GLuint _program;
3047	GLuint _vao, _buffer, _bufferIndirect;
3048};
3049
3050template <typename api>
3051class CBufferIndirectDrawElementsSimple : public DrawIndirectBase
3052{
3053public:
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
3150private:
3151	GLuint _program;
3152	GLuint _vao, _buffer, _bufferIndirect, _ebo;
3153};
3154
3155template <typename api>
3156class CBufferIndirectDrawElementsNoFirstIndex : public DrawIndirectBase
3157{
3158public:
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
3260private:
3261	GLuint _program;
3262	GLuint _vao, _buffer, _bufferIndirect, _ebo;
3263};
3264
3265template <typename api>
3266class CBufferIndirectDrawElementsNoBasevertex : public DrawIndirectBase
3267{
3268public:
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
3370private:
3371	GLuint _program;
3372	GLuint _vao, _buffer, _ebo, _bufferIndirect;
3373};
3374
3375template <typename api>
3376class CBufferIndirectDrawElementsOffset : public DrawIndirectBase
3377{
3378public:
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
3476private:
3477	GLuint _program;
3478	GLuint _vao, _buffer, _ebo, _bufferIndirect;
3479};
3480
3481class CBasicVertexIDsDef : public DrawIndirectBase
3482{
3483public:
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
3702private:
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
3716template <typename api>
3717class CBufferIndirectDrawArraysVertexIds : public CBasicVertexIDsDef
3718{
3719public:
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
3751template <typename api>
3752class CBufferIndirectDrawElementsVertexIds : public CBasicVertexIDsDef
3753{
3754public:
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
3786template <typename api>
3787class CIndicesDataTypeUnsignedShort : public DrawIndirectBase
3788{
3789public:
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
3892private:
3893	GLuint _program;
3894	GLuint _vao, _buffer, _ebo, _bufferIndirect;
3895};
3896
3897template <typename api>
3898class CIndicesDataTypeUnsignedByte : public DrawIndirectBase
3899{
3900public:
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
4003private:
4004	GLuint _program;
4005	GLuint _vao, _buffer, _ebo, _bufferIndirect;
4006};
4007
4008class CPrimitiveMode : public DrawIndirectBase
4009{
4010public:
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
4228private:
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
4239template <typename api>
4240class CModeDrawArraysPoints : public CPrimitiveMode
4241{
4242public:
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
4274template <typename api>
4275class CModeDrawArraysLines : public CPrimitiveMode
4276{
4277public:
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
4309template <typename api>
4310class CModeDrawArraysLineStrip : public CPrimitiveMode
4311{
4312public:
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
4343template <typename api>
4344class CModeDrawArraysLineLoop : public CPrimitiveMode
4345{
4346public:
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
4378template <typename api>
4379class CModeDrawArraysTriangleStrip : public CPrimitiveMode
4380{
4381public:
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
4413template <typename api>
4414class CModeDrawArraysTriangleFan : public CPrimitiveMode
4415{
4416public:
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
4448template <typename api>
4449class CModeDrawArraysLinesAdjacency : public CPrimitiveMode
4450{
4451public:
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
4485template <typename api>
4486class CModeDrawArraysLineStripAdjacency : public CPrimitiveMode
4487{
4488public:
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
4522template <typename api>
4523class CModeDrawArraysTrianglesAdjacency : public CPrimitiveMode
4524{
4525public:
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
4559template <typename api>
4560class CModeDrawArraysTriangleStripAdjacency : public CPrimitiveMode
4561{
4562public:
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
4595template <typename api>
4596class CModeDrawElementsPoints : public CPrimitiveMode
4597{
4598public:
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
4630template <typename api>
4631class CModeDrawElementsLines : public CPrimitiveMode
4632{
4633public:
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
4664template <typename api>
4665class CModeDrawElementsLineStrip : public CPrimitiveMode
4666{
4667public:
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
4698template <typename api>
4699class CModeDrawElementsLineLoop : public CPrimitiveMode
4700{
4701public:
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
4732template <typename api>
4733class CModeDrawElementsTriangleStrip : public CPrimitiveMode
4734{
4735public:
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
4766template <typename api>
4767class CModeDrawElementsTriangleFan : public CPrimitiveMode
4768{
4769public:
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
4800template <typename api>
4801class CModeDrawElementsLinesAdjacency : public CPrimitiveMode
4802{
4803public:
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
4836template <typename api>
4837class CModeDrawElementsLineStripAdjacency : public CPrimitiveMode
4838{
4839public:
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
4872template <typename api>
4873class CModeDrawElementsTrianglesAdjacency : public CPrimitiveMode
4874{
4875public:
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
4908template <typename api>
4909class CModeDrawElementsTriangleStripAdjacency : public CPrimitiveMode
4910{
4911public:
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
4944class CTransformFeedback : public DrawIndirectBase
4945{
4946public:
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
5104private:
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
5120template <typename api>
5121struct 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
5153template <typename api>
5154struct 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
5186class CComputeBase : public DrawIndirectBase
5187{
5188public:
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
5360private:
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
5431template <typename api>
5432struct 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
5465template <typename api>
5466struct 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
5499template <typename api>
5500class CPrimitiveRestartElements : public DrawIndirectBase
5501{
5502public:
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
5630private:
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
5654template <>
5655int CPrimitiveRestartElements<test_api::ES3>::PrimitiveRestartIndex()
5656{
5657	return 0xffffffff;
5658}
5659
5660template <>
5661int CPrimitiveRestartElements<test_api::GL>::PrimitiveRestartIndex()
5662{
5663	return 3432432;
5664}
5665
5666template <>
5667void CPrimitiveRestartElements<test_api::ES3>::DisablePrimitiveRestart()
5668{
5669	glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
5670}
5671
5672template <>
5673void CPrimitiveRestartElements<test_api::GL>::DisablePrimitiveRestart()
5674{
5675	glDisable(GL_PRIMITIVE_RESTART);
5676}
5677
5678template <>
5679void CPrimitiveRestartElements<test_api::ES3>::EnablePrimitiveRestart()
5680{
5681	glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
5682}
5683
5684template <>
5685void CPrimitiveRestartElements<test_api::GL>::EnablePrimitiveRestart()
5686{
5687	glPrimitiveRestartIndex(PrimitiveRestartIndex());
5688	glEnable(GL_PRIMITIVE_RESTART);
5689}
5690
5691template <typename api>
5692class 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
5776private:
5777	GLuint _program;
5778	GLuint _vao, _buffer, _bufferIndirect;
5779};
5780
5781template <typename api>
5782struct 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
5879private:
5880	GLuint _program;
5881	GLuint _vao, _buffer, _ebo, _bufferIndirect;
5882};
5883
5884template <typename api>
5885struct 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
5962private:
5963	GLuint _program;
5964	GLuint _vao, _buffer;
5965};
5966
5967template <typename api>
5968struct 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
6058private:
6059	GLuint _program;
6060	GLuint _vao, _buffer, _ebo;
6061};
6062
6063template <typename api>
6064struct 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
6181private:
6182	GLuint _program;
6183	GLuint _vao, _buffer, _bufferIndirect;
6184};
6185
6186template <typename api>
6187struct 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
6309private:
6310	GLuint _program;
6311	GLuint _vao, _buffer, _ebo, _bufferIndirect;
6312};
6313
6314template <typename api>
6315struct 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
6403private:
6404	GLuint _program;
6405	GLuint _buffer, _ebo, _bufferIndirect;
6406};
6407
6408template <typename api>
6409struct 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
6505private:
6506	GLuint _program;
6507	GLuint _buffer, _ebo, _bufferIndirect;
6508};
6509
6510template <typename api>
6511struct 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
6592private:
6593	GLuint _program;
6594	GLuint _vao, _ebo, _bufferIndirect;
6595};
6596
6597template <typename api>
6598struct 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
6695private:
6696	GLuint _program;
6697	GLuint _vao, _ebo, _bufferIndirect;
6698};
6699
6700template <typename api>
6701struct 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
6811private:
6812	GLuint _program;
6813	GLuint _vao, _buffer, _bufferIndirect;
6814};
6815
6816template <typename api>
6817struct 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
6939private:
6940	GLuint _program;
6941	GLuint _vao, _buffer, _ebo, _bufferIndirect;
6942};
6943
6944template <typename api>
6945struct 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
7080private:
7081	GLuint _program;
7082	GLuint _vao, _buffer, _ebo, _bufferIndirect;
7083};
7084
7085template <typename api>
7086class CNegativeGshArray : public DrawIndirectBase
7087{
7088public:
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
7177private:
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
7199template <typename api>
7200class CNegativeGshElements : public DrawIndirectBase
7201{
7202public:
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
7301private:
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
7323template <typename api>
7324struct 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
7439private:
7440	GLuint _program;
7441	GLuint _vao, _buffer, _bufferIndirect;
7442};
7443
7444template <typename api>
7445struct 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
7565private:
7566	GLuint _program;
7567	GLuint _vao, _buffer, _ebo, _bufferIndirect;
7568};
7569
7570template <typename api>
7571struct 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
7664private:
7665	GLuint _program;
7666	GLuint _vao, _buffer, _bufferIndirect;
7667};
7668
7669template <typename api>
7670struct 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
7775private:
7776	GLuint _program;
7777	GLuint _vao, _buffer, _ebo, _bufferIndirect;
7778};
7779
7780template <typename api>
7781struct 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
7863private:
7864	GLuint _program;
7865	GLuint _vao, _buffer, _ebo, _bufferIndirect;
7866};
7867
7868template <typename api>
7869struct 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
7992private:
7993	GLuint _program;
7994	GLuint _vao, _buffer, _ebo, _bufferIndirect, _xfo, _xfb;
7995};
7996
7997} // namespace
7998DrawIndirectTestsGL40::DrawIndirectTestsGL40(glcts::Context& context) : TestCaseGroup(context, "draw_indirect", "")
7999{
8000}
8001
8002DrawIndirectTestsGL40::~DrawIndirectTestsGL40(void)
8003{
8004}
8005
8006void 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
8162DrawIndirectTestsGL43::DrawIndirectTestsGL43(glcts::Context& context) : TestCaseGroup(context, "draw_indirect_43", "")
8163{
8164}
8165
8166DrawIndirectTestsGL43::~DrawIndirectTestsGL43(void)
8167{
8168}
8169
8170void 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
8181DrawIndirectTestsES31::DrawIndirectTestsES31(glcts::Context& context) : TestCaseGroup(context, "draw_indirect", "")
8182{
8183}
8184
8185DrawIndirectTestsES31::~DrawIndirectTestsES31(void)
8186{
8187}
8188
8189void 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