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 "es31cVertexAttribBindingTests.hpp"
25#include "glwEnums.hpp"
26#include "tcuMatrix.hpp"
27#include "tcuRenderTarget.hpp"
28#include <cstdarg>
29
30#include <cmath>
31
32namespace glcts
33{
34using namespace glw;
35using tcu::Vec4;
36using tcu::IVec4;
37using tcu::UVec4;
38using tcu::Vec3;
39using tcu::IVec3;
40using tcu::UVec3;
41using tcu::Vec2;
42using tcu::IVec2;
43using tcu::UVec2;
44using tcu::Mat4;
45
46namespace
47{
48
49class VertexAttribBindingBase : public glcts::SubcaseBase
50{
51	virtual std::string Title()
52	{
53		return NL "";
54	}
55
56	virtual std::string Purpose()
57	{
58		return NL "";
59	}
60
61	virtual std::string Method()
62	{
63		return NL "";
64	}
65
66	virtual std::string PassCriteria()
67	{
68		return NL "";
69	}
70
71public:
72	bool IsSSBOInVSFSAvailable(int required)
73	{
74		GLint blocksVS, blocksFS;
75		glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS);
76		glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &blocksFS);
77		if (blocksVS >= required && blocksFS >= required)
78			return true;
79		else
80		{
81			std::ostringstream reason;
82			reason << "Required " << required << " VS storage blocks but only " << blocksVS << " available."
83				   << std::endl
84				   << "Required " << required << " FS storage blocks but only " << blocksFS << " available."
85				   << std::endl;
86			OutputNotSupported(reason.str());
87			return false;
88		}
89	}
90
91	int getWindowWidth()
92	{
93		const tcu::RenderTarget& renderTarget = m_context.getRenderTarget();
94		return renderTarget.getWidth();
95	}
96
97	int getWindowHeight()
98	{
99		const tcu::RenderTarget& renderTarget = m_context.getRenderTarget();
100		return renderTarget.getHeight();
101	}
102
103	inline bool ColorEqual(const Vec4& c0, const Vec4& c1, const Vec4& epsilon)
104	{
105		if (fabs(c0[0] - c1[0]) > epsilon[0])
106			return false;
107		if (fabs(c0[1] - c1[1]) > epsilon[1])
108			return false;
109		if (fabs(c0[2] - c1[2]) > epsilon[2])
110			return false;
111		if (fabs(c0[3] - c1[3]) > epsilon[3])
112			return false;
113		return true;
114	}
115
116	bool CheckProgram(GLuint program)
117	{
118		GLint status;
119		glGetProgramiv(program, GL_LINK_STATUS, &status);
120
121		if (status == GL_FALSE)
122		{
123			GLint attached_shaders;
124			glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
125
126			if (attached_shaders > 0)
127			{
128				std::vector<GLuint> shaders(attached_shaders);
129				glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
130
131				for (GLint i = 0; i < attached_shaders; ++i)
132				{
133					GLenum type;
134					glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
135					switch (type)
136					{
137					case GL_VERTEX_SHADER:
138						m_context.getTestContext().getLog()
139							<< tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
140						break;
141					case GL_FRAGMENT_SHADER:
142						m_context.getTestContext().getLog()
143							<< tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
144						break;
145					default:
146						m_context.getTestContext().getLog()
147							<< tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
148						break;
149					}
150					GLint length;
151					glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
152					if (length > 0)
153					{
154						std::vector<GLchar> source(length);
155						glGetShaderSource(shaders[i], length, NULL, &source[0]);
156						m_context.getTestContext().getLog()
157							<< tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
158					}
159					glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
160					if (length > 0)
161					{
162						std::vector<GLchar> log(length);
163						glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
164						m_context.getTestContext().getLog()
165							<< tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
166					}
167				}
168			}
169			GLint length;
170			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
171			if (length > 0)
172			{
173				std::vector<GLchar> log(length);
174				glGetProgramInfoLog(program, length, NULL, &log[0]);
175				m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
176			}
177		}
178		return status == GL_TRUE ? true : false;
179	}
180
181	bool IsEqual(IVec4 a, IVec4 b)
182	{
183		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
184	}
185
186	bool IsEqual(UVec4 a, UVec4 b)
187	{
188		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
189	}
190
191	bool IsEqual(Vec2 a, Vec2 b)
192	{
193		return (a[0] == b[0]) && (a[1] == b[1]);
194	}
195
196	bool IsEqual(IVec2 a, IVec2 b)
197	{
198		return (a[0] == b[0]) && (a[1] == b[1]);
199	}
200
201	bool IsEqual(UVec2 a, UVec2 b)
202	{
203		return (a[0] == b[0]) && (a[1] == b[1]);
204	}
205
206	bool CheckFB(Vec3 expected)
207	{
208		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
209		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
210		Vec3					 g_color_eps  = Vec3(1.f / static_cast<float>(1 << pixelFormat.redBits),
211								1.f / static_cast<float>(1 << pixelFormat.greenBits),
212								1.f / static_cast<float>(1 << pixelFormat.blueBits));
213		Vec3				 g_color_max = Vec3(255);
214		std::vector<GLubyte> fb(getWindowWidth() * getWindowHeight() * 4);
215		int					 fb_w = getWindowWidth();
216		int					 fb_h = getWindowHeight();
217		glReadPixels(0, 0, fb_w, fb_h, GL_RGBA, GL_UNSIGNED_BYTE, &fb[0]);
218		for (GLint i = 0, y = 0; y < fb_h; ++y)
219			for (GLint x = 0; x < fb_w; ++x, i += 4)
220			{
221				if (fabs(fb[i + 0] / g_color_max[0] - expected[0]) > g_color_eps[0] ||
222					fabs(fb[i + 1] / g_color_max[1] - expected[1]) > g_color_eps[1] ||
223					fabs(fb[i + 2] / g_color_max[2] - expected[2]) > g_color_eps[2])
224				{
225					m_context.getTestContext().getLog()
226						<< tcu::TestLog::Message << "Incorrect framebuffer color at pixel (" << x << " " << y
227						<< "). Color is (" << fb[i + 0] / g_color_max[0] << " " << fb[i + 1] / g_color_max[1] << " "
228						<< fb[i + 2] / g_color_max[2] << ". Color should be (" << expected[0] << " " << expected[1]
229						<< " " << expected[2] << ")." << tcu::TestLog::EndMessage;
230					return false;
231				}
232			}
233		return true;
234	}
235
236	GLhalf FloatToHalf(float f)
237	{
238		const unsigned int HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000;
239		/* max exponent value in single precision that will be converted */
240		/* to Inf or Nan when stored as a half-float */
241		const unsigned int HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000;
242		/* 255 is the max exponent biased value */
243		const unsigned int FLOAT_MAX_BIASED_EXP		 = (0xFF << 23);
244		const unsigned int HALF_FLOAT_MAX_BIASED_EXP = (0x1F << 10);
245		char*			   c						 = reinterpret_cast<char*>(&f);
246		unsigned int	   x						 = *reinterpret_cast<unsigned int*>(c);
247		unsigned int	   sign						 = (GLhalf)(x >> 31);
248		unsigned int	   mantissa;
249		unsigned int	   exp;
250		GLhalf			   hf;
251
252		/* get mantissa */
253		mantissa = x & ((1 << 23) - 1);
254		/* get exponent bits */
255		exp = x & FLOAT_MAX_BIASED_EXP;
256		if (exp >= HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
257		{
258			/* check if the original single precision float number is a NaN */
259			if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
260			{
261				/* we have a single precision NaN */
262				mantissa = (1 << 23) - 1;
263			}
264			else
265			{
266				/* 16-bit half-float representation stores number as Inf */
267				mantissa = 0;
268			}
269			hf = (GLhalf)((((GLhalf)sign) << 15) | (GLhalf)(HALF_FLOAT_MAX_BIASED_EXP) | (GLhalf)(mantissa >> 13));
270		}
271		/* check if exponent is <= -15 */
272		else if (exp <= HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
273		{
274			/* store a denorm half-float value or zero */
275			exp = (HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
276			mantissa |= (1 << 23);
277			mantissa >>= (14 + exp);
278			hf = (GLhalf)((((GLhalf)sign) << 15) | (GLhalf)(mantissa));
279		}
280		else
281		{
282			hf = (GLhalf)((((GLhalf)sign) << 15) | (GLhalf)((exp - HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 13) |
283						  (GLhalf)(mantissa >> 13));
284		}
285
286		return hf;
287	}
288};
289//=============================================================================
290// 1.1 BasicUsage
291//-----------------------------------------------------------------------------
292class BasicUsage : public VertexAttribBindingBase
293{
294	bool pipeline;
295
296	GLuint m_vsp, m_fsp, m_ppo, m_vao, m_vbo;
297
298	virtual long Setup()
299	{
300		if (pipeline)
301		{
302			m_vsp = m_fsp = 0;
303			glGenProgramPipelines(1, &m_ppo);
304		}
305		else
306		{
307			m_ppo = 0;
308		}
309		glGenVertexArrays(1, &m_vao);
310		glGenBuffers(1, &m_vbo);
311		return NO_ERROR;
312	}
313
314	virtual long Cleanup()
315	{
316		if (pipeline)
317		{
318			glDeleteProgram(m_vsp);
319			glDeleteProgram(m_fsp);
320			glDeleteProgramPipelines(1, &m_ppo);
321		}
322		else
323		{
324			glUseProgram(0);
325			glDeleteProgram(m_ppo);
326		}
327		glDeleteVertexArrays(1, &m_vao);
328		glDeleteBuffers(1, &m_vbo);
329		return NO_ERROR;
330	}
331
332	virtual long Run()
333	{
334		const char* const glsl_vs =
335			"#version 310 es" NL "layout(location = 7) in vec4 vs_in_position;" NL
336			"layout(location = 1) in vec3 vs_in_color;" NL "out vec3 g_color;" NL "void main() {" NL
337			"  gl_Position = vs_in_position;" NL "  g_color = vs_in_color;" NL "}";
338		const char* const glsl_fs =
339			"#version 310 es" NL "precision highp float;" NL "in vec3 g_color;" NL "out vec4 fs_out_color;" NL
340			"void main() {" NL "  fs_out_color = vec4(g_color, 1);" NL "}";
341		if (pipeline)
342		{
343			m_vsp = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
344			m_fsp = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs);
345			if (!CheckProgram(m_vsp) || !CheckProgram(m_fsp))
346				return ERROR;
347			glUseProgramStages(m_ppo, GL_VERTEX_SHADER_BIT, m_vsp);
348			glUseProgramStages(m_ppo, GL_FRAGMENT_SHADER_BIT, m_fsp);
349		}
350		else
351		{
352			m_ppo			 = glCreateProgram();
353			const GLuint sh  = glCreateShader(GL_VERTEX_SHADER);
354			const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
355			glShaderSource(sh, 1, &glsl_vs, NULL);
356			glShaderSource(fsh, 1, &glsl_fs, NULL);
357			glCompileShader(sh);
358			glCompileShader(fsh);
359			glAttachShader(m_ppo, sh);
360			glAttachShader(m_ppo, fsh);
361			glDeleteShader(sh);
362			glDeleteShader(fsh);
363			glLinkProgram(m_ppo);
364			if (!CheckProgram(m_ppo))
365				return ERROR;
366		}
367		/* vbo */
368		{
369			const float data[] = {
370				-1.0f, -1.0f, 0.0f,  1.0f, 0.0f, 1.0f, -1.0f, 0.0f,  1.0f, 0.0f, -1.0f, 1.0f, 0.0f,  1.0f,
371				0.0f,  1.0f,  1.0f,  0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f,  1.0f, -1.0f, 1.0f,
372				1.0f,  0.0f,  -1.0f, 1.0f, 1.0f, 1.0f, 0.0f,  1.0f,  1.0f, 1.0f, 1.0f,  0.0f,
373			};
374			glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
375			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
376			glBindBuffer(GL_ARRAY_BUFFER, 0);
377		}
378		glBindVertexArray(m_vao);
379		glVertexAttribFormat(7, 2, GL_FLOAT, GL_FALSE, 0);
380		glVertexAttribFormat(1, 3, GL_FLOAT, GL_FALSE, 8);
381		glVertexAttribBinding(7, 0);
382		glVertexAttribBinding(1, 0);
383		glBindVertexBuffer(0, m_vbo, 0, 20);
384		glEnableVertexAttribArray(7);
385		glEnableVertexAttribArray(1);
386		glBindVertexArray(0);
387
388		glClear(GL_COLOR_BUFFER_BIT);
389		glBindVertexArray(m_vao);
390		if (pipeline)
391			glBindProgramPipeline(m_ppo);
392		else
393			glUseProgram(m_ppo);
394
395		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
396		if (!CheckFB(Vec3(0, 1, 0)))
397			return ERROR;
398
399		glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
400		if (!CheckFB(Vec3(1, 1, 0)))
401			return ERROR;
402
403		return NO_ERROR;
404	}
405
406public:
407	BasicUsage() : pipeline(true)
408	{
409	}
410};
411//=============================================================================
412// BasicInputBase
413//-----------------------------------------------------------------------------
414class BasicInputBase : public VertexAttribBindingBase
415{
416
417	GLuint m_po, m_xfbo;
418
419protected:
420	Vec4	expected_data[60];
421	GLsizei instance_count;
422	GLint   base_instance;
423
424	virtual long Setup()
425	{
426		m_po = 0;
427		glGenBuffers(1, &m_xfbo);
428		for (int i			 = 0; i < 60; ++i)
429			expected_data[i] = Vec4(0.0f);
430		instance_count		 = 1;
431		base_instance		 = -1;
432		return NO_ERROR;
433	}
434
435	virtual long Cleanup()
436	{
437		glDisable(GL_RASTERIZER_DISCARD);
438		glUseProgram(0);
439		glDeleteProgram(m_po);
440		glDeleteBuffers(1, &m_xfbo);
441		return NO_ERROR;
442	}
443
444	virtual long Run()
445	{
446		const char* const glsl_vs =
447			"#version 310 es" NL "layout(location = 0) in vec4 vs_in_attrib0;" NL
448			"layout(location = 1) in vec4 vs_in_attrib1;" NL "layout(location = 2) in vec4 vs_in_attrib2;" NL
449			"layout(location = 3) in vec4 vs_in_attrib3;" NL "layout(location = 4) in vec4 vs_in_attrib4;" NL
450			"layout(location = 5) in vec4 vs_in_attrib5;" NL "layout(location = 6) in vec4 vs_in_attrib6;" NL
451			"layout(location = 7) in vec4 vs_in_attrib7;" NL "layout(location = 8) in vec4 vs_in_attrib8;" NL
452			"layout(location = 9) in vec4 vs_in_attrib9;" NL "layout(location = 10) in vec4 vs_in_attrib10;" NL
453			"layout(location = 11) in vec4 vs_in_attrib11;" NL "layout(location = 12) in vec4 vs_in_attrib12;" NL
454			"layout(location = 13) in vec4 vs_in_attrib13;" NL "layout(location = 14) in vec4 vs_in_attrib14;" NL
455			"out vec4 attrib[15];" NL "void main() {" NL "  attrib[0] = vs_in_attrib0;" NL
456			"  attrib[1] = vs_in_attrib1;" NL "  attrib[2] = vs_in_attrib2;" NL "  attrib[3] = vs_in_attrib3;" NL
457			"  attrib[4] = vs_in_attrib4;" NL "  attrib[5] = vs_in_attrib5;" NL "  attrib[6] = vs_in_attrib6;" NL
458			"  attrib[7] = vs_in_attrib7;" NL "  attrib[8] = vs_in_attrib8;" NL "  attrib[9] = vs_in_attrib9;" NL
459			"  attrib[10] = vs_in_attrib10;" NL "  attrib[11] = vs_in_attrib11;" NL "  attrib[12] = vs_in_attrib12;" NL
460			"  attrib[13] = vs_in_attrib13;" NL "  attrib[14] = vs_in_attrib14;" NL "}";
461		const char* const glsl_fs = "#version 310 es" NL "precision mediump float;" NL "in vec4 attrib[15];" NL
462									"out vec4 fs_out_color;" NL "void main() {" NL "  fs_out_color = attrib[8];" NL "}";
463		m_po = glCreateProgram();
464		/* attach shader */
465		{
466			const GLuint sh  = glCreateShader(GL_VERTEX_SHADER);
467			const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
468			glShaderSource(sh, 1, &glsl_vs, NULL);
469			glShaderSource(fsh, 1, &glsl_fs, NULL);
470			glCompileShader(sh);
471			glCompileShader(fsh);
472			glAttachShader(m_po, sh);
473			glAttachShader(m_po, fsh);
474			glDeleteShader(sh);
475			glDeleteShader(fsh);
476		}
477		/* setup XFB */
478		{
479			const GLchar* const v[15] = { "attrib[0]",  "attrib[1]",  "attrib[2]",  "attrib[3]",  "attrib[4]",
480										  "attrib[5]",  "attrib[6]",  "attrib[7]",  "attrib[8]",  "attrib[9]",
481										  "attrib[10]", "attrib[11]", "attrib[12]", "attrib[13]", "attrib[14]" };
482			glTransformFeedbackVaryings(m_po, 15, v, GL_INTERLEAVED_ATTRIBS);
483		}
484		glLinkProgram(m_po);
485		if (!CheckProgram(m_po))
486			return ERROR;
487
488		/* buffer data */
489		{
490			std::vector<GLubyte> zero(sizeof(expected_data));
491			glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_xfbo);
492			glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(expected_data), &zero[0], GL_DYNAMIC_DRAW);
493		}
494
495		// capture
496		glEnable(GL_RASTERIZER_DISCARD);
497		glUseProgram(m_po);
498		glBeginTransformFeedback(GL_POINTS);
499		if (base_instance != -1)
500		{
501			glDrawArraysInstancedBaseInstance(GL_POINTS, 0, 2, instance_count, static_cast<GLuint>(base_instance));
502		}
503		else
504		{
505			glDrawArraysInstanced(GL_POINTS, 0, 2, instance_count);
506		}
507		glEndTransformFeedback();
508
509		Vec4* data =
510			static_cast<Vec4*>(glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(Vec4) * 60, GL_MAP_READ_BIT));
511
512		long status = NO_ERROR;
513		for (int i = 0; i < 60; ++i)
514		{
515			if (!ColorEqual(expected_data[i], data[i], Vec4(0.01f)))
516			{
517				m_context.getTestContext().getLog()
518					<< tcu::TestLog::Message << "Data is: " << data[i][0] << " " << data[i][1] << " " << data[i][2]
519					<< " " << data[i][3] << ", data should be: " << expected_data[i][0] << " " << expected_data[i][1]
520					<< " " << expected_data[i][2] << " " << expected_data[i][3] << ", index is: " << i
521					<< tcu::TestLog::EndMessage;
522				status = ERROR;
523				break;
524			}
525		}
526		return status;
527	}
528};
529
530//=============================================================================
531// 1.2.1 BasicInputCase1
532//-----------------------------------------------------------------------------
533class BasicInputCase1 : public BasicInputBase
534{
535
536	GLuint m_vao, m_vbo;
537
538	virtual long Setup()
539	{
540		BasicInputBase::Setup();
541		glGenVertexArrays(1, &m_vao);
542		glGenBuffers(1, &m_vbo);
543		return NO_ERROR;
544	}
545
546	virtual long Cleanup()
547	{
548		BasicInputBase::Cleanup();
549		glDeleteVertexArrays(1, &m_vao);
550		glDeleteBuffers(1, &m_vbo);
551		return NO_ERROR;
552	}
553
554	virtual long Run()
555	{
556		for (GLuint i = 0; i < 16; ++i)
557		{
558			glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f);
559		}
560		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
561		glBufferData(GL_ARRAY_BUFFER, sizeof(Vec3) * 2, NULL, GL_STATIC_DRAW);
562		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vec3), &Vec3(1.0f, 2.0f, 3.0f)[0]);
563		glBufferSubData(GL_ARRAY_BUFFER, 12, sizeof(Vec3), &Vec3(4.0f, 5.0f, 6.0f)[0]);
564		glBindBuffer(GL_ARRAY_BUFFER, 0);
565
566		glBindVertexArray(m_vao);
567		glBindVertexBuffer(0, m_vbo, 0, 12);
568		glVertexAttribFormat(1, 3, GL_FLOAT, GL_FALSE, 0);
569		glVertexAttribBinding(1, 0);
570		glEnableVertexAttribArray(1);
571		expected_data[1]  = Vec4(1.0f, 2.0f, 3.0f, 1.0f);
572		expected_data[16] = Vec4(4.0f, 5.0f, 6.0f, 1.0f);
573		return BasicInputBase::Run();
574	}
575};
576//=============================================================================
577// 1.2.2 BasicInputCase2
578//-----------------------------------------------------------------------------
579class BasicInputCase2 : public BasicInputBase
580{
581
582	GLuint m_vao, m_vbo;
583
584	virtual long Setup()
585	{
586		BasicInputBase::Setup();
587		glGenVertexArrays(1, &m_vao);
588		glGenBuffers(1, &m_vbo);
589		return NO_ERROR;
590	}
591
592	virtual long Cleanup()
593	{
594		BasicInputBase::Cleanup();
595		glDeleteVertexArrays(1, &m_vao);
596		glDeleteBuffers(1, &m_vbo);
597		return NO_ERROR;
598	}
599
600	virtual long Run()
601	{
602		for (GLuint i = 0; i < 16; ++i)
603		{
604			glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f);
605		}
606		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
607		glBufferData(GL_ARRAY_BUFFER, sizeof(Vec3) * 2, NULL, GL_STATIC_DRAW);
608		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vec3), &Vec3(1.0f, 2.0f, 3.0f)[0]);
609		glBufferSubData(GL_ARRAY_BUFFER, 12, sizeof(Vec3), &Vec3(4.0f, 5.0f, 6.0f)[0]);
610		glBindBuffer(GL_ARRAY_BUFFER, 0);
611
612		glBindVertexArray(m_vao);
613		glVertexAttribBinding(1, 0);
614		glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, 0);
615		glVertexAttribFormat(1, 3, GL_FLOAT, GL_FALSE, 0);
616		glVertexAttribFormat(7, 1, GL_FLOAT, GL_FALSE, 8);
617		glVertexAttribFormat(14, 2, GL_FLOAT, GL_FALSE, 4);
618		glVertexAttribBinding(0, 0);
619		glVertexAttribBinding(7, 0);
620		glVertexAttribBinding(14, 0);
621		glBindVertexBuffer(0, m_vbo, 0, 12);
622		glEnableVertexAttribArray(0);
623		glEnableVertexAttribArray(1);
624		glEnableVertexAttribArray(7);
625		glEnableVertexAttribArray(14);
626
627		expected_data[0]  = Vec4(1.0f, 2.0f, 0.0f, 1.0f);
628		expected_data[1]  = Vec4(1.0f, 2.0f, 3.0f, 1.0f);
629		expected_data[7]  = Vec4(3.0f, 0.0f, 0.0f, 1.0f);
630		expected_data[14] = Vec4(2.0f, 3.0f, 0.0f, 1.0f);
631		expected_data[15] = Vec4(4.0f, 5.0f, 0.0f, 1.0f);
632		expected_data[16] = Vec4(4.0f, 5.0f, 6.0f, 1.0f);
633		expected_data[22] = Vec4(6.0f, 0.0f, 0.0f, 1.0f);
634		expected_data[29] = Vec4(5.0f, 6.0f, 0.0f, 1.0f);
635		return BasicInputBase::Run();
636	}
637};
638//=============================================================================
639// 1.2.3 BasicInputCase3
640//-----------------------------------------------------------------------------
641class BasicInputCase3 : public BasicInputBase
642{
643
644	GLuint m_vao, m_vbo;
645
646	virtual long Setup()
647	{
648		BasicInputBase::Setup();
649		glGenVertexArrays(1, &m_vao);
650		glGenBuffers(1, &m_vbo);
651		return NO_ERROR;
652	}
653
654	virtual long Cleanup()
655	{
656		BasicInputBase::Cleanup();
657		glDeleteVertexArrays(1, &m_vao);
658		glDeleteBuffers(1, &m_vbo);
659		return NO_ERROR;
660	}
661
662	virtual long Run()
663	{
664		for (GLuint i = 0; i < 16; ++i)
665		{
666			glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f);
667		}
668		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
669		glBufferData(GL_ARRAY_BUFFER, 36 * 2, NULL, GL_STATIC_DRAW);
670		/* */
671		{
672			GLubyte d[] = { 1, 2, 3, 4 };
673			glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(d), d);
674		}
675		glBufferSubData(GL_ARRAY_BUFFER, 16, sizeof(Vec3), &Vec3(5.0f, 6.0f, 7.0f)[0]);
676		glBufferSubData(GL_ARRAY_BUFFER, 28, sizeof(Vec2), &Vec2(8.0f, 9.0f)[0]);
677		/* */
678		{
679			GLubyte d[] = { 10, 11, 12, 13 };
680			glBufferSubData(GL_ARRAY_BUFFER, 0 + 36, sizeof(d), d);
681		}
682		glBufferSubData(GL_ARRAY_BUFFER, 16 + 36, sizeof(Vec3), &Vec3(14.0f, 15.0f, 16.0f)[0]);
683		glBufferSubData(GL_ARRAY_BUFFER, 28 + 36, sizeof(Vec2), &Vec2(17.0f, 18.0f)[0]);
684		glBindBuffer(GL_ARRAY_BUFFER, 0);
685
686		glBindVertexArray(m_vao);
687		glEnableVertexAttribArray(1);
688		glVertexAttribFormat(0, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0);
689		glVertexAttribBinding(1, 3);
690		glVertexAttribFormat(1, 3, GL_FLOAT, GL_FALSE, 16);
691		glVertexAttribBinding(2, 3);
692		glVertexAttribFormat(2, 2, GL_FLOAT, GL_FALSE, 28);
693		glVertexAttribBinding(0, 3);
694		glBindVertexBuffer(3, m_vbo, 0, 36);
695		glEnableVertexAttribArray(0);
696		glEnableVertexAttribArray(2);
697
698		expected_data[0]	  = Vec4(1.0f, 2.0f, 3.0f, 4.0f);
699		expected_data[1]	  = Vec4(5.0f, 6.0f, 7.0f, 1.0f);
700		expected_data[2]	  = Vec4(8.0f, 9.0f, 0.0f, 1.0f);
701		expected_data[0 + 15] = Vec4(10.0f, 11.0f, 12.0f, 13.0f);
702		expected_data[1 + 15] = Vec4(14.0f, 15.0f, 16.0f, 1.0f);
703		expected_data[2 + 15] = Vec4(17.0f, 18.0f, 0.0f, 1.0f);
704		return BasicInputBase::Run();
705	}
706};
707//=============================================================================
708// 1.2.4 BasicInputCase4
709//-----------------------------------------------------------------------------
710class BasicInputCase4 : public BasicInputBase
711{
712
713	GLuint m_vao, m_vbo[2];
714
715	virtual long Setup()
716	{
717		BasicInputBase::Setup();
718		glGenVertexArrays(1, &m_vao);
719		glGenBuffers(2, m_vbo);
720		return NO_ERROR;
721	}
722
723	virtual long Cleanup()
724	{
725		BasicInputBase::Cleanup();
726		glDeleteVertexArrays(1, &m_vao);
727		glDeleteBuffers(2, m_vbo);
728		return NO_ERROR;
729	}
730
731	virtual long Run()
732	{
733		for (GLuint i = 0; i < 16; ++i)
734		{
735			glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f);
736		}
737		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[0]);
738		glBufferData(GL_ARRAY_BUFFER, 20 * 2, NULL, GL_STATIC_DRAW);
739		/* */
740		{
741			GLbyte d[] = { -127, 127, -127, 127 };
742			glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(d), d);
743		}
744		/* */
745		{
746			GLushort d[] = { 1, 2, 3, 4 };
747			glBufferSubData(GL_ARRAY_BUFFER, 4, sizeof(d), d);
748		}
749		/* */
750		{
751			GLuint d[] = { 5, 6 };
752			glBufferSubData(GL_ARRAY_BUFFER, 12, sizeof(d), d);
753		}
754		/* */
755		{
756			GLbyte d[] = { 127, -127, 127, -127 };
757			glBufferSubData(GL_ARRAY_BUFFER, 0 + 20, sizeof(d), d);
758		}
759		/* */
760		{
761			GLushort d[] = { 7, 8, 9, 10 };
762			glBufferSubData(GL_ARRAY_BUFFER, 4 + 20, sizeof(d), d);
763		}
764		/* */
765		{
766			GLuint d[] = { 11, 12 };
767			glBufferSubData(GL_ARRAY_BUFFER, 12 + 20, sizeof(d), d);
768		}
769		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[1]);
770		glBufferData(GL_ARRAY_BUFFER, 24 * 2 + 8, NULL, GL_STATIC_DRAW);
771		/* */
772		{
773			GLhalf d[] = { FloatToHalf(0.0), FloatToHalf(100.0), FloatToHalf(200.0) };
774			glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(d), d);
775		}
776		/* */
777		{
778			GLhalf d[] = { FloatToHalf(300.0), FloatToHalf(400.0) };
779			glBufferSubData(GL_ARRAY_BUFFER, 26, sizeof(d), d);
780		}
781		glBindBuffer(GL_ARRAY_BUFFER, 0);
782
783		glBindVertexArray(m_vao);
784		glVertexAttribFormat(0, 4, GL_BYTE, GL_TRUE, 0);
785		glVertexAttribFormat(1, 4, GL_UNSIGNED_SHORT, GL_FALSE, 4);
786		glVertexAttribFormat(2, 2, GL_UNSIGNED_INT, GL_FALSE, 12);
787		glVertexAttribFormat(5, 2, GL_HALF_FLOAT, GL_FALSE, 0);
788		glVertexAttribBinding(0, 0);
789		glVertexAttribBinding(1, 0);
790		glVertexAttribBinding(2, 0);
791		glVertexAttribBinding(5, 6);
792		glBindVertexBuffer(0, m_vbo[0], 0, 20);
793		glBindVertexBuffer(6, m_vbo[1], 2, 24);
794		glEnableVertexAttribArray(0);
795		glEnableVertexAttribArray(1);
796		glEnableVertexAttribArray(2);
797		glEnableVertexAttribArray(5);
798
799		expected_data[0]	  = Vec4(-1.0f, 1.0f, -1.0f, 1.0f);
800		expected_data[1]	  = Vec4(1.0f, 2.0f, 3.0f, 4.0f);
801		expected_data[2]	  = Vec4(5.0f, 6.0f, 0.0f, 1.0f);
802		expected_data[5]	  = Vec4(100.0f, 200.0f, 0.0f, 1.0f);
803		expected_data[0 + 15] = Vec4(1.0f, -1.0f, 1.0f, -1.0f);
804		expected_data[1 + 15] = Vec4(7.0f, 8.0f, 9.0f, 10.0f);
805		expected_data[2 + 15] = Vec4(11.0f, 12.0f, 0.0f, 1.0f);
806		expected_data[5 + 15] = Vec4(300.0f, 400.0f, 0.0f, 1.0f);
807		return BasicInputBase::Run();
808	}
809};
810//=============================================================================
811// 1.2.5 BasicInputCase5
812//-----------------------------------------------------------------------------
813class BasicInputCase5 : public BasicInputBase
814{
815
816	GLuint m_vao, m_vbo;
817
818	virtual long Setup()
819	{
820		BasicInputBase::Setup();
821		glGenVertexArrays(1, &m_vao);
822		glGenBuffers(1, &m_vbo);
823		return NO_ERROR;
824	}
825
826	virtual long Cleanup()
827	{
828		BasicInputBase::Cleanup();
829		glDeleteVertexArrays(1, &m_vao);
830		glDeleteBuffers(1, &m_vbo);
831		return NO_ERROR;
832	}
833
834	virtual long Run()
835	{
836		for (GLuint i = 0; i < 16; ++i)
837		{
838			glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f);
839		}
840		const int kStride = 116;
841		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
842		glBufferData(GL_ARRAY_BUFFER, kStride * 2, NULL, GL_STATIC_DRAW);
843		/* */
844		{
845			GLubyte d[] = { 0, 0xff, 0xff / 2, 0 };
846			glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(d), d);
847		}
848		/* */
849		{
850			GLushort d[] = { 0, 0xffff, 0xffff / 2, 0 };
851			glBufferSubData(GL_ARRAY_BUFFER, 4, sizeof(d), d);
852		}
853		/* */
854		{
855			GLuint d[] = { 0, 0xffffffff, 0xffffffff / 2, 0 };
856			glBufferSubData(GL_ARRAY_BUFFER, 12, sizeof(d), d);
857		}
858		/* */
859		{
860			GLbyte d[] = { 0, -127, 127, 0 };
861			glBufferSubData(GL_ARRAY_BUFFER, 28, sizeof(d), d);
862		}
863		/* */
864		{
865			GLshort d[] = { 0, -32767, 32767, 0 };
866			glBufferSubData(GL_ARRAY_BUFFER, 32, sizeof(d), d);
867		}
868		/* */
869		{
870			GLint d[] = { 0, -2147483647, 2147483647, 0 };
871			glBufferSubData(GL_ARRAY_BUFFER, 40, sizeof(d), d);
872		}
873		/* */
874		{
875			GLfloat d[] = { 0, 1.0f, 2.0f, 0 };
876			glBufferSubData(GL_ARRAY_BUFFER, 56, sizeof(d), d);
877		}
878		/* */
879		{
880			GLhalf d[] = { FloatToHalf(0.0), FloatToHalf(10.0), FloatToHalf(20.0), FloatToHalf(0.0) };
881			glBufferSubData(GL_ARRAY_BUFFER, 72, sizeof(d), d);
882		}
883		/* */
884		{
885			GLubyte d[] = { 0, 0xff / 4, 0xff / 2, 0xff };
886			glBufferSubData(GL_ARRAY_BUFFER, 104, sizeof(d), d);
887		}
888		/* */
889		{
890			GLuint d = 0 | (1023 << 10) | (511 << 20) | (1 << 30);
891			glBufferSubData(GL_ARRAY_BUFFER, 108, sizeof(d), &d);
892		}
893		/* */
894		{
895			GLint d = 0 | (511 << 10) | (255 << 20) | (0 << 30);
896			glBufferSubData(GL_ARRAY_BUFFER, 112, sizeof(d), &d);
897		}
898
899		/* */
900		{
901			GLubyte d[] = { 0xff, 0xff, 0xff / 2, 0 };
902			glBufferSubData(GL_ARRAY_BUFFER, 0 + kStride, sizeof(d), d);
903		}
904		/* */
905		{
906			GLushort d[] = { 0xffff, 0xffff, 0xffff / 2, 0 };
907			glBufferSubData(GL_ARRAY_BUFFER, 4 + kStride, sizeof(d), d);
908		}
909		/* */
910		{
911			GLuint d[] = { 0xffffffff, 0xffffffff, 0xffffffff / 2, 0 };
912			glBufferSubData(GL_ARRAY_BUFFER, 12 + kStride, sizeof(d), d);
913		}
914		/* */
915		{
916			GLbyte d[] = { 127, -127, 127, 0 };
917			glBufferSubData(GL_ARRAY_BUFFER, 28 + kStride, sizeof(d), d);
918		}
919		/* */
920		{
921			GLshort d[] = { 32767, -32767, 32767, 0 };
922			glBufferSubData(GL_ARRAY_BUFFER, 32 + kStride, sizeof(d), d);
923		}
924		/* */
925		{
926			GLint d[] = { 2147483647, -2147483647, 2147483647, 0 };
927			glBufferSubData(GL_ARRAY_BUFFER, 40 + kStride, sizeof(d), d);
928		}
929		/* */
930		{
931			GLfloat d[] = { 0, 3.0f, 4.0f, 0 };
932			glBufferSubData(GL_ARRAY_BUFFER, 56 + kStride, sizeof(d), d);
933		}
934		/* */
935		{
936			GLhalf d[] = { FloatToHalf(0.0), FloatToHalf(30.0), FloatToHalf(40.0), FloatToHalf(0.0) };
937			glBufferSubData(GL_ARRAY_BUFFER, 72 + kStride, sizeof(d), d);
938		}
939		/* */
940		{
941			GLubyte d[] = { 0xff, 0xff / 2, 0xff / 4, 0 };
942			glBufferSubData(GL_ARRAY_BUFFER, 104 + kStride, sizeof(d), d);
943		}
944		/* */
945		{
946			GLuint d = 0 | (1023 << 10) | (511 << 20) | (2u << 30);
947			glBufferSubData(GL_ARRAY_BUFFER, 108 + kStride, sizeof(d), &d);
948		}
949		/* */
950		{
951			GLint d = (-511 & 0x3ff) | (511 << 10) | (255 << 20) | 3 << 30;
952			glBufferSubData(GL_ARRAY_BUFFER, 112 + kStride, sizeof(d), &d);
953		}
954		glBindBuffer(GL_ARRAY_BUFFER, 0);
955
956		glBindVertexArray(m_vao);
957		glVertexAttribFormat(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
958		glVertexAttribFormat(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 4);
959		glVertexAttribFormat(2, 4, GL_UNSIGNED_INT, GL_TRUE, 12);
960		glVertexAttribFormat(3, 4, GL_BYTE, GL_TRUE, 28);
961		glVertexAttribFormat(4, 4, GL_SHORT, GL_TRUE, 32);
962		glVertexAttribFormat(5, 4, GL_INT, GL_TRUE, 40);
963		glVertexAttribFormat(6, 4, GL_FLOAT, GL_TRUE, 56);
964		glVertexAttribFormat(7, 4, GL_HALF_FLOAT, GL_TRUE, 72);
965		glVertexAttribFormat(8, 4, GL_UNSIGNED_BYTE, GL_TRUE, 104);
966		glVertexAttribFormat(9, 4, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 108);
967		glVertexAttribFormat(10, 4, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 108);
968		glVertexAttribFormat(11, 4, GL_INT_2_10_10_10_REV, GL_TRUE, 112);
969		glVertexAttribFormat(12, 4, GL_INT_2_10_10_10_REV, GL_TRUE, 112);
970		for (GLuint i = 0; i < 13; ++i)
971		{
972			glVertexAttribBinding(i, 0);
973			glEnableVertexAttribArray(i);
974		}
975		glBindVertexBuffer(0, m_vbo, 0, kStride);
976
977		expected_data[0]	   = Vec4(0.0f, 1.0f, 0.5f, 0.0f);
978		expected_data[1]	   = Vec4(0.0f, 1.0f, 0.5f, 0.0f);
979		expected_data[2]	   = Vec4(0.0f, 1.0f, 0.5f, 0.0f);
980		expected_data[3]	   = Vec4(0.0f, -1.0f, 1.0f, 0.0f);
981		expected_data[4]	   = Vec4(0.0f, -1.0f, 1.0f, 0.0f);
982		expected_data[5]	   = Vec4(0.0f, -1.0f, 1.0f, 0.0f);
983		expected_data[6]	   = Vec4(0.0f, 1.0f, 2.0f, 0.0f);
984		expected_data[7]	   = Vec4(0.0f, 10.0f, 20.0f, 0.0f);
985		expected_data[8]	   = Vec4(0.0f, 0.25f, 0.5f, 1.0f);
986		expected_data[9]	   = Vec4(0.0f, 1.0f, 0.5f, 0.33f);
987		expected_data[10]	  = Vec4(0.0f, 1.0f, 0.5f, 0.33f);
988		expected_data[11]	  = Vec4(0.0f, 1.0f, 0.5f, 0.0f);
989		expected_data[12]	  = Vec4(0.0f, 1.0f, 0.5f, 0.0f);
990		expected_data[0 + 15]  = Vec4(1.0f, 1.0f, 0.5f, 0.0f);
991		expected_data[1 + 15]  = Vec4(1.0f, 1.0f, 0.5f, 0.0f);
992		expected_data[2 + 15]  = Vec4(1.0f, 1.0f, 0.5f, 0.0f);
993		expected_data[3 + 15]  = Vec4(1.0f, -1.0f, 1.0f, 0.0f);
994		expected_data[4 + 15]  = Vec4(1.0f, -1.0f, 1.0f, 0.0f);
995		expected_data[5 + 15]  = Vec4(1.0f, -1.0f, 1.0f, 0.0f);
996		expected_data[6 + 15]  = Vec4(0.0f, 3.0f, 4.0f, 0.0f);
997		expected_data[7 + 15]  = Vec4(0.0f, 30.0f, 40.0f, 0.0f);
998		expected_data[8 + 15]  = Vec4(1.0f, 0.5f, 0.25f, 0.0f);
999		expected_data[9 + 15]  = Vec4(0.0f, 1.0f, 0.5f, 0.66f);
1000		expected_data[10 + 15] = Vec4(0.0f, 1.0f, 0.5f, 0.66f);
1001		expected_data[11 + 15] = Vec4(-1.0f, 1.0f, 0.5f, -1.0f);
1002		expected_data[12 + 15] = Vec4(-1.0f, 1.0f, 0.5f, -1.0f);
1003		return BasicInputBase::Run();
1004	}
1005};
1006//=============================================================================
1007// 1.2.6 BasicInputCase6
1008//-----------------------------------------------------------------------------
1009class BasicInputCase6 : public BasicInputBase
1010{
1011
1012	GLuint m_vao, m_vbo;
1013
1014	virtual long Setup()
1015	{
1016		BasicInputBase::Setup();
1017		glGenVertexArrays(1, &m_vao);
1018		glGenBuffers(1, &m_vbo);
1019		return NO_ERROR;
1020	}
1021
1022	virtual long Cleanup()
1023	{
1024		BasicInputBase::Cleanup();
1025		glDeleteVertexArrays(1, &m_vao);
1026		glDeleteBuffers(1, &m_vbo);
1027		return NO_ERROR;
1028	}
1029
1030	virtual long Run()
1031	{
1032		for (GLuint i = 0; i < 16; ++i)
1033		{
1034			glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f);
1035		}
1036		const int kStride = 112;
1037		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
1038		glBufferData(GL_ARRAY_BUFFER, kStride * 2, NULL, GL_STATIC_DRAW);
1039		/* */
1040		{
1041			GLubyte d[] = { 1, 2, 3, 4 };
1042			glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(d), d);
1043		}
1044		/* */
1045		{
1046			GLushort d[] = { 5, 6, 7, 8 };
1047			glBufferSubData(GL_ARRAY_BUFFER, 4, sizeof(d), d);
1048		}
1049		/* */
1050		{
1051			GLuint d[] = { 9, 10, 11, 12 };
1052			glBufferSubData(GL_ARRAY_BUFFER, 12, sizeof(d), d);
1053		}
1054		/* */
1055		{
1056			GLbyte d[] = { -1, 2, -3, 4 };
1057			glBufferSubData(GL_ARRAY_BUFFER, 28, sizeof(d), d);
1058		}
1059		/* */
1060		{
1061			GLshort d[] = { -5, 6, -7, 8 };
1062			glBufferSubData(GL_ARRAY_BUFFER, 32, sizeof(d), d);
1063		}
1064		/* */
1065		{
1066			GLint d[] = { -9, 10, -11, 12 };
1067			glBufferSubData(GL_ARRAY_BUFFER, 40, sizeof(d), d);
1068		}
1069		/* */
1070		{
1071			GLfloat d[] = { -13.0f, 14.0f, -15.0f, 16.0f };
1072			glBufferSubData(GL_ARRAY_BUFFER, 56, sizeof(d), d);
1073		}
1074		/* */
1075		{
1076			GLhalf d[] = { FloatToHalf(-18.0), FloatToHalf(19.0), FloatToHalf(-20.0), FloatToHalf(21.0) };
1077			glBufferSubData(GL_ARRAY_BUFFER, 72, sizeof(d), d);
1078		}
1079		/* */
1080		{
1081			GLuint d = 0 | (11 << 10) | (12 << 20) | (2u << 30);
1082			glBufferSubData(GL_ARRAY_BUFFER, 104, sizeof(d), &d);
1083		}
1084		/* */
1085		{
1086			GLint d = 0 | ((0xFFFFFFF5 << 10) & (0x3ff << 10)) | (12 << 20) | (1 << 30);
1087			glBufferSubData(GL_ARRAY_BUFFER, 108, sizeof(d), &d);
1088		}
1089
1090		/* */
1091		{
1092			GLubyte d[] = { 22, 23, 24, 25 };
1093			glBufferSubData(GL_ARRAY_BUFFER, 0 + kStride, sizeof(d), d);
1094		}
1095		/* */
1096		{
1097			GLushort d[] = { 26, 27, 28, 29 };
1098			glBufferSubData(GL_ARRAY_BUFFER, 4 + kStride, sizeof(d), d);
1099		}
1100		/* */
1101		{
1102			GLuint d[] = { 30, 31, 32, 33 };
1103			glBufferSubData(GL_ARRAY_BUFFER, 12 + kStride, sizeof(d), d);
1104		}
1105		/* */
1106		{
1107			GLbyte d[] = { -34, 35, -36, 37 };
1108			glBufferSubData(GL_ARRAY_BUFFER, 28 + kStride, sizeof(d), d);
1109		}
1110		/* */
1111		{
1112			GLshort d[] = { -38, 39, -40, 41 };
1113			glBufferSubData(GL_ARRAY_BUFFER, 32 + kStride, sizeof(d), d);
1114		}
1115		/* */
1116		{
1117			GLint d[] = { -42, 43, -44, 45 };
1118			glBufferSubData(GL_ARRAY_BUFFER, 40 + kStride, sizeof(d), d);
1119		}
1120		/* */
1121		{
1122			GLfloat d[] = { -46.0f, 47.0f, -48.0f, 49.0f };
1123			glBufferSubData(GL_ARRAY_BUFFER, 56 + kStride, sizeof(d), d);
1124		}
1125		/* */
1126		{
1127			GLhalf d[] = { FloatToHalf(-50.0), FloatToHalf(51.0), FloatToHalf(-52.0), FloatToHalf(53.0) };
1128			glBufferSubData(GL_ARRAY_BUFFER, 72 + kStride, sizeof(d), d);
1129		}
1130		/* */
1131		{
1132			GLuint d = 0 | (11 << 10) | (12 << 20) | (1 << 30);
1133			glBufferSubData(GL_ARRAY_BUFFER, 104 + kStride, sizeof(d), &d);
1134		}
1135		/* */
1136		{
1137			GLint d = 123 | ((0xFFFFFFFD << 10) & (0x3ff << 10)) | ((0xFFFFFE0C << 20) & (0x3ff << 20)) |
1138					  ((0xFFFFFFFF << 30) & (0x3 << 30));
1139			glBufferSubData(GL_ARRAY_BUFFER, 108 + kStride, sizeof(d), &d);
1140		}
1141		glBindBuffer(GL_ARRAY_BUFFER, 0);
1142
1143		glBindVertexArray(m_vao);
1144		glVertexAttribFormat(0, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0);
1145		glVertexAttribFormat(1, 4, GL_UNSIGNED_SHORT, GL_FALSE, 4);
1146		glVertexAttribFormat(2, 4, GL_UNSIGNED_INT, GL_FALSE, 12);
1147		glVertexAttribFormat(3, 4, GL_BYTE, GL_FALSE, 28);
1148		glVertexAttribFormat(4, 4, GL_SHORT, GL_FALSE, 32);
1149		glVertexAttribFormat(5, 4, GL_INT, GL_FALSE, 40);
1150		glVertexAttribFormat(6, 4, GL_FLOAT, GL_FALSE, 56);
1151		glVertexAttribFormat(7, 4, GL_HALF_FLOAT, GL_FALSE, 72);
1152		glVertexAttribFormat(8, 4, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 104);
1153		glVertexAttribFormat(9, 4, GL_INT_2_10_10_10_REV, GL_FALSE, 108);
1154		for (GLuint i = 0; i < 10; ++i)
1155		{
1156			glVertexAttribBinding(i, 0);
1157			glEnableVertexAttribArray(i);
1158		}
1159		glBindVertexBuffer(0, m_vbo, 0, kStride);
1160
1161		expected_data[0]	  = Vec4(1.0f, 2.0f, 3.0f, 4.0f);
1162		expected_data[1]	  = Vec4(5.0f, 6.0f, 7.0f, 8.0f);
1163		expected_data[2]	  = Vec4(9.0f, 10.0f, 11.0f, 12.0f);
1164		expected_data[3]	  = Vec4(-1.0f, 2.0f, -3.0f, 4.0f);
1165		expected_data[4]	  = Vec4(-5.0f, 6.0f, -7.0f, 8.0f);
1166		expected_data[5]	  = Vec4(-9.0f, 10.0f, -11.0f, 12.0f);
1167		expected_data[6]	  = Vec4(-13.0f, 14.0f, -15.0f, 16.0f);
1168		expected_data[7]	  = Vec4(-18.0f, 19.0f, -20.0f, 21.0f);
1169		expected_data[8]	  = Vec4(0.0f, 11.0f, 12.0f, 2.0f);
1170		expected_data[9]	  = Vec4(0.0f, -11.0f, 12.0f, 1.0f);
1171		expected_data[0 + 15] = Vec4(22.0f, 23.0f, 24.0f, 25.0f);
1172		expected_data[1 + 15] = Vec4(26.0f, 27.0f, 28.0f, 29.0f);
1173		expected_data[2 + 15] = Vec4(30.0f, 31.0f, 32.0f, 33.0f);
1174		expected_data[3 + 15] = Vec4(-34.0f, 35.0f, -36.0f, 37.0f);
1175		expected_data[4 + 15] = Vec4(-38.0f, 39.0f, -40.0f, 41.0f);
1176		expected_data[5 + 15] = Vec4(-42.0f, 43.0f, -44.0f, 45.0f);
1177		expected_data[6 + 15] = Vec4(-46.0f, 47.0f, -48.0f, 49.0f);
1178		expected_data[7 + 15] = Vec4(-50.0f, 51.0f, -52.0f, 53.0f);
1179		expected_data[8 + 15] = Vec4(0.0f, 11.0f, 12.0f, 1.0f);
1180		expected_data[9 + 15] = Vec4(123.0f, -3.0f, -500.0f, -1.0f);
1181		return BasicInputBase::Run();
1182	}
1183};
1184//=============================================================================
1185// 1.2.8 BasicInputCase8
1186//-----------------------------------------------------------------------------
1187class BasicInputCase8 : public BasicInputBase
1188{
1189
1190	GLuint m_vao, m_vbo[2];
1191
1192	virtual long Setup()
1193	{
1194		BasicInputBase::Setup();
1195		glGenVertexArrays(1, &m_vao);
1196		glGenBuffers(2, m_vbo);
1197		return NO_ERROR;
1198	}
1199
1200	virtual long Cleanup()
1201	{
1202		BasicInputBase::Cleanup();
1203		glDeleteVertexArrays(1, &m_vao);
1204		glDeleteBuffers(2, m_vbo);
1205		return NO_ERROR;
1206	}
1207
1208	virtual long Run()
1209	{
1210		for (GLuint i = 0; i < 16; ++i)
1211		{
1212			glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f);
1213		}
1214		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[0]);
1215		glBufferData(GL_ARRAY_BUFFER, 6 * 4, NULL, GL_STATIC_DRAW);
1216		/* */
1217		{
1218			GLfloat d[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f };
1219			glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(d), d);
1220		}
1221
1222		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[1]);
1223		glBufferData(GL_ARRAY_BUFFER, 10 * 4, NULL, GL_STATIC_DRAW);
1224		/* */
1225		{
1226			GLfloat d[] = { -1.0f, -2.0f, -3.0f, -4.0f, -5.0f, -6.0f, -7.0f, -8.0f, -9.0f, -10.0f };
1227			glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(d), d);
1228		}
1229		glBindBuffer(GL_ARRAY_BUFFER, 0);
1230
1231		glBindVertexArray(m_vao);
1232		glVertexAttribFormat(0, 3, GL_FLOAT, GL_FALSE, 0);
1233		glVertexAttribFormat(1, 3, GL_FLOAT, GL_FALSE, 0);
1234		glVertexAttribFormat(2, 1, GL_FLOAT, GL_FALSE, 4);
1235		glVertexAttribFormat(5, 4, GL_FLOAT, GL_FALSE, 12);
1236		glVertexAttribFormat(14, 2, GL_FLOAT, GL_FALSE, 8);
1237		glVertexAttribBinding(0, 0);
1238		glVertexAttribBinding(1, 1);
1239		glVertexAttribBinding(2, 1);
1240		glVertexAttribBinding(5, 15);
1241		glVertexAttribBinding(14, 7);
1242		glBindVertexBuffer(0, m_vbo[0], 0, 12);
1243		glBindVertexBuffer(1, m_vbo[0], 4, 4);
1244		glBindVertexBuffer(7, m_vbo[1], 8, 16);
1245		glBindVertexBuffer(15, m_vbo[1], 12, 0);
1246		glEnableVertexAttribArray(0);
1247		glEnableVertexAttribArray(1);
1248		glEnableVertexAttribArray(2);
1249		glEnableVertexAttribArray(5);
1250		glEnableVertexAttribArray(14);
1251
1252		expected_data[0]	   = Vec4(1.0f, 2.0f, 3.0f, 1.0f);
1253		expected_data[1]	   = Vec4(2.0f, 3.0f, 4.0f, 1.0f);
1254		expected_data[2]	   = Vec4(3.0f, 0.0f, 0.0f, 1.0f);
1255		expected_data[5]	   = Vec4(-7.0f, -8.0f, -9.0f, -10.0f);
1256		expected_data[14]	  = Vec4(-5.0f, -6.0f, 0.0f, 1.0f);
1257		expected_data[0 + 15]  = Vec4(4.0f, 5.0f, 6.0f, 1.0f);
1258		expected_data[1 + 15]  = Vec4(3.0f, 4.0f, 5.0f, 1.0f);
1259		expected_data[2 + 15]  = Vec4(4.0f, 0.0f, 0.0f, 1.0f);
1260		expected_data[5 + 15]  = Vec4(-7.0f, -8.0f, -9.0f, -10.0f);
1261		expected_data[14 + 15] = Vec4(-9.0f, -10.0f, 0.0f, 1.0f);
1262		return BasicInputBase::Run();
1263	}
1264};
1265//=============================================================================
1266// 1.2.9 BasicInputCase9
1267//-----------------------------------------------------------------------------
1268class BasicInputCase9 : public BasicInputBase
1269{
1270
1271	GLuint m_vao, m_vbo[2];
1272
1273	virtual long Setup()
1274	{
1275		BasicInputBase::Setup();
1276		glGenVertexArrays(1, &m_vao);
1277		glGenBuffers(2, m_vbo);
1278		return NO_ERROR;
1279	}
1280
1281	virtual long Cleanup()
1282	{
1283		BasicInputBase::Cleanup();
1284		glDeleteVertexArrays(1, &m_vao);
1285		glDeleteBuffers(2, m_vbo);
1286		return NO_ERROR;
1287	}
1288
1289	virtual long Run()
1290	{
1291		for (GLuint i = 0; i < 16; ++i)
1292		{
1293			glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f);
1294		}
1295		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[0]);
1296		glBufferData(GL_ARRAY_BUFFER, sizeof(Vec4) * 3, NULL, GL_STATIC_DRAW);
1297		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vec4), &Vec4(1.0f, 2.0f, 3.0f, 4.0f)[0]);
1298		glBufferSubData(GL_ARRAY_BUFFER, 16, sizeof(Vec4), &Vec4(5.0f, 6.0f, 7.0f, 8.0f)[0]);
1299		glBufferSubData(GL_ARRAY_BUFFER, 32, sizeof(Vec4), &Vec4(9.0f, 10.0f, 11.0f, 12.0f)[0]);
1300		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[1]);
1301		glBufferData(GL_ARRAY_BUFFER, sizeof(Vec4) * 3, NULL, GL_STATIC_DRAW);
1302		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vec4), &Vec4(10.0f, 20.0f, 30.0f, 40.0f)[0]);
1303		glBufferSubData(GL_ARRAY_BUFFER, 16, sizeof(Vec4), &Vec4(50.0f, 60.0f, 70.0f, 80.0f)[0]);
1304		glBindBuffer(GL_ARRAY_BUFFER, 0);
1305
1306		glBindVertexArray(m_vao);
1307		glVertexAttribFormat(0, 4, GL_FLOAT, GL_FALSE, 0);
1308		glVertexAttribFormat(2, 4, GL_FLOAT, GL_FALSE, 0);
1309		glVertexAttribFormat(4, 2, GL_FLOAT, GL_FALSE, 4);
1310		glVertexAttribBinding(0, 0);
1311		glVertexAttribBinding(2, 1);
1312		glVertexAttribBinding(4, 3);
1313		glEnableVertexAttribArray(0);
1314		glEnableVertexAttribArray(2);
1315		glEnableVertexAttribArray(4);
1316		glBindVertexBuffer(0, m_vbo[0], 0, 16);
1317		glBindVertexBuffer(1, m_vbo[0], 0, 16);
1318		glBindVertexBuffer(3, m_vbo[1], 4, 8);
1319		glVertexBindingDivisor(1, 1);
1320
1321		instance_count		  = 2;
1322		expected_data[0]	  = Vec4(1.0f, 2.0f, 3.0f, 4.0f);
1323		expected_data[2]	  = Vec4(1.0f, 2.0f, 3.0f, 4.0f);
1324		expected_data[4]	  = Vec4(30.0f, 40.0f, 0.0f, 1.0f);
1325		expected_data[0 + 15] = Vec4(5.0f, 6.0f, 7.0f, 8.0f);
1326		expected_data[2 + 15] = Vec4(1.0f, 2.0f, 3.0f, 4.0f);
1327		expected_data[4 + 15] = Vec4(50.0f, 60.0f, 0.0f, 1.0f);
1328
1329		expected_data[0 + 30]	  = Vec4(1.0f, 2.0f, 3.0f, 4.0f);
1330		expected_data[2 + 30]	  = Vec4(5.0f, 6.0f, 7.0f, 8.0f);
1331		expected_data[4 + 30]	  = Vec4(30.0f, 40.0f, 0.0f, 1.0f);
1332		expected_data[0 + 15 + 30] = Vec4(5.0f, 6.0f, 7.0f, 8.0f);
1333		expected_data[2 + 15 + 30] = Vec4(5.0f, 6.0f, 7.0f, 8.0f);
1334		expected_data[4 + 15 + 30] = Vec4(50.0f, 60.0f, 0.0f, 1.0f);
1335		return BasicInputBase::Run();
1336	}
1337};
1338//=============================================================================
1339// 1.2.11 BasicInputCase11
1340//-----------------------------------------------------------------------------
1341class BasicInputCase11 : public BasicInputBase
1342{
1343
1344	GLuint m_vao, m_vbo[2];
1345
1346	virtual long Setup()
1347	{
1348		BasicInputBase::Setup();
1349		glGenVertexArrays(1, &m_vao);
1350		glGenBuffers(2, m_vbo);
1351		return NO_ERROR;
1352	}
1353
1354	virtual long Cleanup()
1355	{
1356		BasicInputBase::Cleanup();
1357		glDeleteVertexArrays(1, &m_vao);
1358		glDeleteBuffers(2, m_vbo);
1359		return NO_ERROR;
1360	}
1361
1362	virtual long Run()
1363	{
1364		for (GLuint i = 0; i < 16; ++i)
1365		{
1366			glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f);
1367		}
1368		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[0]);
1369		glBufferData(GL_ARRAY_BUFFER, sizeof(Vec4) * 3, NULL, GL_STATIC_DRAW);
1370		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vec4), &Vec4(1.0f, 2.0f, 3.0f, 4.0f)[0]);
1371		glBufferSubData(GL_ARRAY_BUFFER, 16, sizeof(Vec4), &Vec4(5.0f, 6.0f, 7.0f, 8.0f)[0]);
1372		glBufferSubData(GL_ARRAY_BUFFER, 32, sizeof(Vec4), &Vec4(9.0f, 10.0f, 11.0f, 12.0f)[0]);
1373		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[1]);
1374		glBufferData(GL_ARRAY_BUFFER, sizeof(Vec4) * 3, NULL, GL_STATIC_DRAW);
1375		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vec4), &Vec4(10.0f, 20.0f, 30.0f, 40.0f)[0]);
1376		glBufferSubData(GL_ARRAY_BUFFER, 16, sizeof(Vec4), &Vec4(50.0f, 60.0f, 70.0f, 80.0f)[0]);
1377		glBindBuffer(GL_ARRAY_BUFFER, 0);
1378
1379		glBindVertexArray(m_vao);
1380		glVertexAttribFormat(0, 4, GL_FLOAT, GL_FALSE, 0);
1381		glVertexAttribFormat(2, 4, GL_FLOAT, GL_FALSE, 0);
1382		glVertexAttribFormat(4, 2, GL_FLOAT, GL_FALSE, 4);
1383		glVertexAttribBinding(0, 0);
1384		glVertexAttribBinding(2, 1);
1385		glVertexAttribBinding(4, 2);
1386		glEnableVertexAttribArray(0);
1387		glEnableVertexAttribArray(2);
1388		glEnableVertexAttribArray(4);
1389		glBindVertexBuffer(0, m_vbo[0], 0, 16);
1390		glBindVertexBuffer(1, m_vbo[0], 0, 16);
1391		glBindVertexBuffer(2, m_vbo[1], 4, 8);
1392		glVertexBindingDivisor(1, 1);
1393
1394		instance_count		  = 2;
1395		expected_data[0]	  = Vec4(1.0f, 2.0f, 3.0f, 4.0f);
1396		expected_data[2]	  = Vec4(1.0f, 2.0f, 3.0f, 4.0f);
1397		expected_data[4]	  = Vec4(30.0f, 40.0f, 0.0f, 1.0f);
1398		expected_data[0 + 15] = Vec4(5.0f, 6.0f, 7.0f, 8.0f);
1399		expected_data[2 + 15] = Vec4(1.0f, 2.0f, 3.0f, 4.0f);
1400		expected_data[4 + 15] = Vec4(50.0f, 60.0f, 0.0f, 1.0f);
1401
1402		expected_data[0 + 30]	  = Vec4(1.0f, 2.0f, 3.0f, 4.0f);
1403		expected_data[2 + 30]	  = Vec4(5.0f, 6.0f, 7.0f, 8.0f);
1404		expected_data[4 + 30]	  = Vec4(30.0f, 40.0f, 0.0f, 1.0f);
1405		expected_data[0 + 15 + 30] = Vec4(5.0f, 6.0f, 7.0f, 8.0f);
1406		expected_data[2 + 15 + 30] = Vec4(5.0f, 6.0f, 7.0f, 8.0f);
1407		expected_data[4 + 15 + 30] = Vec4(50.0f, 60.0f, 0.0f, 1.0f);
1408		return BasicInputBase::Run();
1409	}
1410};
1411//=============================================================================
1412// 1.2.12 BasicInputCase12
1413//-----------------------------------------------------------------------------
1414class BasicInputCase12 : public BasicInputBase
1415{
1416
1417	GLuint m_vao, m_vbo;
1418
1419	virtual long Setup()
1420	{
1421		BasicInputBase::Setup();
1422		glGenVertexArrays(1, &m_vao);
1423		glGenBuffers(1, &m_vbo);
1424		return NO_ERROR;
1425	}
1426
1427	virtual long Cleanup()
1428	{
1429		BasicInputBase::Cleanup();
1430		glDeleteVertexArrays(1, &m_vao);
1431		glDeleteBuffers(1, &m_vbo);
1432		return NO_ERROR;
1433	}
1434
1435	virtual long Run()
1436	{
1437		for (GLuint i = 0; i < 16; ++i)
1438		{
1439			glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f);
1440		}
1441		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
1442		glBufferData(GL_ARRAY_BUFFER, sizeof(Vec3) * 2, NULL, GL_STATIC_DRAW);
1443		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vec3), &Vec3(1.0f, 2.0f, 3.0f)[0]);
1444		glBufferSubData(GL_ARRAY_BUFFER, 12, sizeof(Vec3), &Vec3(4.0f, 5.0f, 6.0f)[0]);
1445		glBindBuffer(GL_ARRAY_BUFFER, 0);
1446
1447		glBindVertexArray(m_vao);
1448
1449		//glVertexAttribFormat(1, 3, GL_FLOAT, GL_FALSE, 0);
1450		//glVertexAttribBinding(1, 1);
1451		//glBindVertexBuffer(1, m_vbo, 0, 12);
1452		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
1453		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 12, 0);
1454		glBindBuffer(GL_ARRAY_BUFFER, 0);
1455
1456		glVertexAttribFormat(0, 3, GL_FLOAT, GL_FALSE, 0);
1457		glVertexAttribBinding(0, 1);
1458
1459		glEnableVertexAttribArray(0);
1460		glEnableVertexAttribArray(1);
1461
1462		expected_data[0]	  = Vec4(1.0f, 2.0f, 3.0f, 1.0f);
1463		expected_data[1]	  = Vec4(1.0f, 2.0f, 3.0f, 1.0f);
1464		expected_data[0 + 15] = Vec4(4.0f, 5.0f, 6.0f, 1.0f);
1465		expected_data[1 + 15] = Vec4(4.0f, 5.0f, 6.0f, 1.0f);
1466		return BasicInputBase::Run();
1467	}
1468};
1469//=============================================================================
1470// BasicInputIBase
1471//-----------------------------------------------------------------------------
1472class BasicInputIBase : public VertexAttribBindingBase
1473{
1474
1475	GLuint m_po, m_xfbo;
1476
1477protected:
1478	IVec4   expected_datai[32];
1479	UVec4   expected_dataui[32];
1480	GLsizei instance_count;
1481	GLuint  base_instance;
1482
1483	virtual long Setup()
1484	{
1485		m_po = 0;
1486		glGenBuffers(1, &m_xfbo);
1487		for (int i = 0; i < 32; ++i)
1488		{
1489			expected_datai[i]  = IVec4(0);
1490			expected_dataui[i] = UVec4(0);
1491		}
1492		instance_count = 1;
1493		return NO_ERROR;
1494	}
1495
1496	virtual long Cleanup()
1497	{
1498		glDisable(GL_RASTERIZER_DISCARD);
1499		glUseProgram(0);
1500		glDeleteProgram(m_po);
1501		glDeleteBuffers(1, &m_xfbo);
1502		return NO_ERROR;
1503	}
1504
1505	virtual long Run()
1506	{
1507		const char* const glsl_vs =
1508			"#version 310 es" NL "layout(location = 0) in ivec4 vs_in_attribi0;" NL
1509			"layout(location = 1) in ivec4 vs_in_attribi1;" NL "layout(location = 2) in ivec4 vs_in_attribi2;" NL
1510			"layout(location = 3) in ivec4 vs_in_attribi3;" NL "layout(location = 4) in ivec4 vs_in_attribi4;" NL
1511			"layout(location = 5) in ivec4 vs_in_attribi5;" NL "layout(location = 6) in ivec4 vs_in_attribi6;" NL
1512			"layout(location = 7) in ivec4 vs_in_attribi7;" NL "layout(location = 8) in uvec4 vs_in_attribui8;" NL
1513			"layout(location = 9) in uvec4 vs_in_attribui9;" NL "layout(location = 10) in uvec4 vs_in_attribui10;" NL
1514			"layout(location = 11) in uvec4 vs_in_attribui11;" NL "layout(location = 12) in uvec4 vs_in_attribui12;" NL
1515			"layout(location = 13) in uvec4 vs_in_attribui13;" NL "layout(location = 14) in uvec4 vs_in_attribui14;" NL
1516			"layout(location = 15) in uvec4 vs_in_attribui15;" NL "flat out ivec4 attribi[8];" NL
1517			"flat out uvec4 attribui[7];" NL "void main() {" NL "  attribi[0] = vs_in_attribi0;" NL
1518			"  attribi[1] = vs_in_attribi1;" NL "  attribi[2] = vs_in_attribi2;" NL "  attribi[3] = vs_in_attribi3;" NL
1519			"  attribi[4] = vs_in_attribi4;" NL "  attribi[5] = vs_in_attribi5;" NL "  attribi[6] = vs_in_attribi6;" NL
1520			"  attribi[7] = vs_in_attribi7;" NL "  attribui[0] = vs_in_attribui8;" NL
1521			"  attribui[1] = vs_in_attribui9;" NL "  attribui[2] = vs_in_attribui10;" NL
1522			"  attribui[3] = vs_in_attribui11;" NL "  attribui[4] = vs_in_attribui12;" NL
1523			"  attribui[5] = vs_in_attribui13;" NL "  attribui[6] = vs_in_attribui14;" NL "}";
1524		const char* const glsl_fs = "#version 310 es" NL "precision mediump float;" NL "flat in ivec4 attribi[8];" NL
1525									"flat in uvec4 attribui[7];" NL "out vec4 fs_out_color;" NL "void main() {" NL
1526									"  fs_out_color = vec4(attribui[1]);" NL "}";
1527		m_po = glCreateProgram();
1528		/* attach shader */
1529		{
1530			const GLuint sh  = glCreateShader(GL_VERTEX_SHADER);
1531			const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
1532			glShaderSource(sh, 1, &glsl_vs, NULL);
1533			glShaderSource(fsh, 1, &glsl_fs, NULL);
1534			glCompileShader(sh);
1535			glCompileShader(fsh);
1536			glAttachShader(m_po, sh);
1537			glAttachShader(m_po, fsh);
1538			glDeleteShader(sh);
1539			glDeleteShader(fsh);
1540		}
1541		/* setup XFB */
1542		{
1543			const GLchar* const v[15] = { "attribi[0]",  "attribi[1]",  "attribi[2]",  "attribi[3]",  "attribi[4]",
1544										  "attribi[5]",  "attribi[6]",  "attribi[7]",  "attribui[0]", "attribui[1]",
1545										  "attribui[2]", "attribui[3]", "attribui[4]", "attribui[5]", "attribui[6]" };
1546			glTransformFeedbackVaryings(m_po, 15, v, GL_INTERLEAVED_ATTRIBS);
1547		}
1548		glLinkProgram(m_po);
1549		if (!CheckProgram(m_po))
1550			return ERROR;
1551
1552		/* buffer data */
1553		{
1554			std::vector<GLubyte> zero(64 * 16);
1555			glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_xfbo);
1556			glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, (GLsizeiptr)zero.size(), &zero[0], GL_DYNAMIC_COPY);
1557		}
1558
1559		glEnable(GL_RASTERIZER_DISCARD);
1560		glUseProgram(m_po);
1561		glBeginTransformFeedback(GL_POINTS);
1562		glDrawArraysInstanced(GL_POINTS, 0, 2, instance_count);
1563		glEndTransformFeedback();
1564
1565		void*  data   = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(UVec4) * 64, GL_MAP_READ_BIT);
1566		IVec4* datai  = static_cast<IVec4*>(data);
1567		UVec4* dataui = (static_cast<UVec4*>(data)) + 8;
1568
1569		for (int i = 0; i < 4; ++i)
1570			for (int j = 0; j < 8; ++j)
1571			{
1572				if (!IsEqual(expected_datai[i * 8 + j], datai[i * 15 + j]))
1573				{
1574					m_context.getTestContext().getLog()
1575						<< tcu::TestLog::Message << "Datai is: " << datai[i * 15 + j][0] << " " << datai[i * 15 + j][1]
1576						<< " " << datai[i * 15 + j][2] << " " << datai[i * 15 + j][3]
1577						<< ", data should be: " << expected_datai[i * 8 + j][0] << " " << expected_datai[i * 8 + j][1]
1578						<< " " << expected_datai[i * 8 + j][2] << " " << expected_datai[i * 8 + j][3]
1579						<< ", index is: " << i * 8 + j << tcu::TestLog::EndMessage;
1580					return ERROR;
1581				}
1582				if (j != 7 && !IsEqual(expected_dataui[i * 8 + j], dataui[i * 15 + j]))
1583				{
1584					m_context.getTestContext().getLog()
1585						<< tcu::TestLog::Message << "Dataui is: " << dataui[i * 15 + j][0] << " "
1586						<< dataui[i * 15 + j][1] << " " << dataui[i * 15 + j][2] << " " << dataui[i * 15 + j][3]
1587						<< ", data should be: " << expected_datai[i * 8 + j][0] << " " << expected_datai[i * 8 + j][1]
1588						<< " " << expected_datai[i * 8 + j][2] << " " << expected_datai[i * 8 + j][3]
1589						<< ", index is: " << i * 8 + j << tcu::TestLog::EndMessage;
1590					return ERROR;
1591				}
1592			}
1593		return NO_ERROR;
1594	}
1595};
1596//=============================================================================
1597// 1.3.1 BasicInputICase1
1598//-----------------------------------------------------------------------------
1599class BasicInputICase1 : public BasicInputIBase
1600{
1601
1602	GLuint m_vao, m_vbo;
1603
1604	virtual long Setup()
1605	{
1606		BasicInputIBase::Setup();
1607		glGenVertexArrays(1, &m_vao);
1608		glGenBuffers(1, &m_vbo);
1609		return NO_ERROR;
1610	}
1611
1612	virtual long Cleanup()
1613	{
1614		BasicInputIBase::Cleanup();
1615		glDeleteVertexArrays(1, &m_vao);
1616		glDeleteBuffers(1, &m_vbo);
1617		return NO_ERROR;
1618	}
1619
1620	virtual long Run()
1621	{
1622		for (GLuint i = 0; i < 8; ++i)
1623		{
1624			glVertexAttribI4i(i, 0, 0, 0, 0);
1625			glVertexAttribI4ui(i + 8, 0, 0, 0, 0);
1626		}
1627		const int kStride = 88;
1628		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
1629		glBufferData(GL_ARRAY_BUFFER, kStride * 2, NULL, GL_STATIC_DRAW);
1630		/* */
1631		{
1632			GLbyte d[] = { 1, -2, 3, -4 };
1633			glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(d), d);
1634		}
1635		/* */
1636		{
1637			GLshort d[] = { 5, -6, 7, -8 };
1638			glBufferSubData(GL_ARRAY_BUFFER, 4, sizeof(d), d);
1639		}
1640		/* */
1641		{
1642			GLint d[] = { 9, -10, 11, -12 };
1643			glBufferSubData(GL_ARRAY_BUFFER, 12, sizeof(d), d);
1644		}
1645		/* */
1646		{
1647			GLubyte d[] = { 13, 14, 15, 16 };
1648			glBufferSubData(GL_ARRAY_BUFFER, 28, sizeof(d), d);
1649		}
1650		/* */
1651		{
1652			GLushort d[] = { 17, 18, 19, 20 };
1653			glBufferSubData(GL_ARRAY_BUFFER, 32, sizeof(d), d);
1654		}
1655		/* */
1656		{
1657			GLuint d[] = { 21, 22, 23, 24 };
1658			glBufferSubData(GL_ARRAY_BUFFER, 40, sizeof(d), d);
1659		}
1660		/* */
1661		{
1662			GLint d[] = { 90, -91, 92, -93 };
1663			glBufferSubData(GL_ARRAY_BUFFER, 56, sizeof(d), d);
1664		}
1665		/* */
1666		{
1667			GLuint d[] = { 94, 95, 96, 97 };
1668			glBufferSubData(GL_ARRAY_BUFFER, 72, sizeof(d), d);
1669		}
1670
1671		/* */
1672		{
1673			GLbyte d[] = { 25, -26, 27, -28 };
1674			glBufferSubData(GL_ARRAY_BUFFER, 0 + kStride, sizeof(d), d);
1675		}
1676		/* */
1677		{
1678			GLshort d[] = { 29, -30, 31, -32 };
1679			glBufferSubData(GL_ARRAY_BUFFER, 4 + kStride, sizeof(d), d);
1680		}
1681		/* */
1682		{
1683			GLint d[] = { 33, -34, 35, -36 };
1684			glBufferSubData(GL_ARRAY_BUFFER, 12 + kStride, sizeof(d), d);
1685		}
1686		/* */
1687		{
1688			GLubyte d[] = { 37, 38, 39, 40 };
1689			glBufferSubData(GL_ARRAY_BUFFER, 28 + kStride, sizeof(d), d);
1690		}
1691		/* */
1692		{
1693			GLushort d[] = { 41, 42, 43, 44 };
1694			glBufferSubData(GL_ARRAY_BUFFER, 32 + kStride, sizeof(d), d);
1695		}
1696		/* */
1697		{
1698			GLuint d[] = { 45, 46, 47, 48 };
1699			glBufferSubData(GL_ARRAY_BUFFER, 40 + kStride, sizeof(d), d);
1700		}
1701		/* */
1702		{
1703			GLint d[] = { 98, -99, 100, -101 };
1704			glBufferSubData(GL_ARRAY_BUFFER, 56 + kStride, sizeof(d), d);
1705		}
1706		/* */
1707		{
1708			GLuint d[] = { 102, 103, 104, 105 };
1709			glBufferSubData(GL_ARRAY_BUFFER, 72 + kStride, sizeof(d), d);
1710		}
1711		glBindBuffer(GL_ARRAY_BUFFER, 0);
1712
1713		glBindVertexArray(m_vao);
1714		glVertexAttribIFormat(0, 1, GL_BYTE, 0);
1715		glVertexAttribIFormat(1, 2, GL_SHORT, 4);
1716		glVertexAttribIFormat(2, 3, GL_INT, 12);
1717		glVertexAttribIFormat(3, 4, GL_INT, 56);
1718		glVertexAttribIFormat(8, 3, GL_UNSIGNED_BYTE, 28);
1719		glVertexAttribIFormat(9, 2, GL_UNSIGNED_SHORT, 32);
1720		glVertexAttribIFormat(10, 1, GL_UNSIGNED_INT, 40);
1721		glVertexAttribIFormat(11, 4, GL_UNSIGNED_INT, 72);
1722		glVertexAttribBinding(0, 0);
1723		glVertexAttribBinding(1, 0);
1724		glVertexAttribBinding(2, 0);
1725		glVertexAttribBinding(3, 0);
1726		glVertexAttribBinding(8, 0);
1727		glVertexAttribBinding(9, 0);
1728		glVertexAttribBinding(10, 0);
1729		glVertexAttribBinding(11, 0);
1730		glBindVertexBuffer(0, m_vbo, 0, kStride);
1731		glEnableVertexAttribArray(0);
1732		glEnableVertexAttribArray(1);
1733		glEnableVertexAttribArray(2);
1734		glEnableVertexAttribArray(3);
1735		glEnableVertexAttribArray(8);
1736		glEnableVertexAttribArray(9);
1737		glEnableVertexAttribArray(10);
1738		glEnableVertexAttribArray(11);
1739
1740		expected_datai[0]   = IVec4(1, 0, 0, 1);
1741		expected_datai[1]   = IVec4(5, -6, 0, 1);
1742		expected_datai[2]   = IVec4(9, -10, 11, 1);
1743		expected_datai[3]   = IVec4(90, -91, 92, -93);
1744		expected_dataui[0]  = UVec4(13, 14, 15, 1);
1745		expected_dataui[1]  = UVec4(17, 18, 0, 1);
1746		expected_dataui[2]  = UVec4(21, 0, 0, 1);
1747		expected_dataui[3]  = UVec4(94, 95, 96, 97);
1748		expected_datai[8]   = IVec4(25, 0, 0, 1);
1749		expected_datai[9]   = IVec4(29, -30, 0, 1);
1750		expected_datai[10]  = IVec4(33, -34, 35, 1);
1751		expected_datai[11]  = IVec4(98, -99, 100, -101);
1752		expected_dataui[8]  = UVec4(37, 38, 39, 1);
1753		expected_dataui[9]  = UVec4(41, 42, 0, 1);
1754		expected_dataui[10] = UVec4(45, 0, 0, 1);
1755		expected_dataui[11] = UVec4(102, 103, 104, 105);
1756		return BasicInputIBase::Run();
1757	}
1758};
1759//=============================================================================
1760// 1.3.2 BasicInputICase2
1761//-----------------------------------------------------------------------------
1762class BasicInputICase2 : public BasicInputIBase
1763{
1764
1765	GLuint m_vao, m_vbo[2];
1766
1767	virtual long Setup()
1768	{
1769		BasicInputIBase::Setup();
1770		glGenVertexArrays(1, &m_vao);
1771		glGenBuffers(2, m_vbo);
1772		return NO_ERROR;
1773	}
1774
1775	virtual long Cleanup()
1776	{
1777		BasicInputIBase::Cleanup();
1778		glDeleteVertexArrays(1, &m_vao);
1779		glDeleteBuffers(2, m_vbo);
1780		return NO_ERROR;
1781	}
1782
1783	virtual long Run()
1784	{
1785		for (GLuint i = 0; i < 8; ++i)
1786		{
1787			glVertexAttribI4i(i, 0, 0, 0, 0);
1788			glVertexAttribI4ui(i + 8, 0, 0, 0, 0);
1789		}
1790		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[0]);
1791		glBufferData(GL_ARRAY_BUFFER, sizeof(IVec3) * 2, NULL, GL_STATIC_DRAW);
1792		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(IVec3), &IVec3(1, 2, 3)[0]);
1793		glBufferSubData(GL_ARRAY_BUFFER, 12, sizeof(IVec3), &IVec3(4, 5, 6)[0]);
1794
1795		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[1]);
1796		glBufferData(GL_ARRAY_BUFFER, sizeof(UVec4), NULL, GL_STATIC_DRAW);
1797		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(UVec4), &UVec4(10, 20, 30, 40)[0]);
1798		glBindBuffer(GL_ARRAY_BUFFER, 0);
1799
1800		glBindVertexArray(m_vao);
1801		glVertexAttribIFormat(0, 3, GL_INT, 0);
1802		glVertexAttribIFormat(2, 2, GL_INT, 4);
1803		glVertexAttribIFormat(14, 1, GL_UNSIGNED_INT, 0);
1804		glVertexAttribBinding(0, 2);
1805		glVertexAttribBinding(2, 0);
1806		glVertexAttribBinding(14, 7);
1807		glEnableVertexAttribArray(0);
1808		glEnableVertexAttribArray(2);
1809		glEnableVertexAttribArray(14);
1810		glBindVertexBuffer(0, m_vbo[0], 0, 8);
1811		glBindVertexBuffer(2, m_vbo[0], 0, 12);
1812		glBindVertexBuffer(7, m_vbo[1], 4, 16);
1813		glVertexBindingDivisor(0, 1);
1814		glVertexBindingDivisor(2, 0);
1815		glVertexBindingDivisor(7, 2);
1816
1817		instance_count		= 2;
1818		expected_datai[0]   = IVec4(1, 2, 3, 1);
1819		expected_datai[2]   = IVec4(2, 3, 0, 1);
1820		expected_dataui[6]  = UVec4(20, 0, 0, 1);
1821		expected_datai[8]   = IVec4(4, 5, 6, 1);
1822		expected_datai[10]  = IVec4(2, 3, 0, 1);
1823		expected_dataui[14] = UVec4(20, 0, 0, 1);
1824
1825		expected_datai[16]  = IVec4(1, 2, 3, 1);
1826		expected_datai[18]  = IVec4(4, 5, 0, 1);
1827		expected_dataui[22] = UVec4(20, 0, 0, 1);
1828		expected_datai[24]  = IVec4(4, 5, 6, 1);
1829		expected_datai[26]  = IVec4(4, 5, 0, 1);
1830		expected_dataui[30] = UVec4(20, 0, 0, 1);
1831		return BasicInputIBase::Run();
1832	}
1833};
1834//=============================================================================
1835// 1.3.3 BasicInputICase3
1836//-----------------------------------------------------------------------------
1837class BasicInputICase3 : public BasicInputIBase
1838{
1839
1840	GLuint m_vao, m_vbo;
1841
1842	virtual long Setup()
1843	{
1844		BasicInputIBase::Setup();
1845		glGenVertexArrays(1, &m_vao);
1846		glGenBuffers(1, &m_vbo);
1847		return NO_ERROR;
1848	}
1849
1850	virtual long Cleanup()
1851	{
1852		BasicInputIBase::Cleanup();
1853		glDeleteVertexArrays(1, &m_vao);
1854		glDeleteBuffers(1, &m_vbo);
1855		return NO_ERROR;
1856	}
1857
1858	virtual long Run()
1859	{
1860		for (GLuint i = 0; i < 8; ++i)
1861		{
1862			glVertexAttribI4i(i, 0, 0, 0, 0);
1863			glVertexAttribI4ui(i + 8, 0, 0, 0, 0);
1864		}
1865		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
1866		glBufferData(GL_ARRAY_BUFFER, sizeof(IVec3) * 2, NULL, GL_STATIC_DRAW);
1867		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(IVec3), &IVec3(1, 2, 3)[0]);
1868		glBufferSubData(GL_ARRAY_BUFFER, 12, sizeof(IVec3), &IVec3(4, 5, 6)[0]);
1869		glBindBuffer(GL_ARRAY_BUFFER, 0);
1870
1871		glBindVertexArray(m_vao);
1872
1873		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
1874		glVertexAttribIPointer(7, 3, GL_INT, 12, 0);
1875		glBindBuffer(GL_ARRAY_BUFFER, 0);
1876
1877		glVertexAttribIFormat(0, 2, GL_INT, 4);
1878		glVertexAttribBinding(0, 7);
1879
1880		glEnableVertexAttribArray(0);
1881		glEnableVertexAttribArray(7);
1882
1883		expected_datai[0]	 = IVec4(2, 3, 0, 1);
1884		expected_datai[7]	 = IVec4(1, 2, 3, 1);
1885		expected_datai[0 + 8] = IVec4(5, 6, 0, 1);
1886		expected_datai[7 + 8] = IVec4(4, 5, 6, 1);
1887		return BasicInputIBase::Run();
1888	}
1889};
1890
1891class VertexAttribState : public glcts::GLWrapper
1892{
1893public:
1894	int		  array_enabled;
1895	int		  array_size;
1896	int		  array_stride;
1897	int		  array_type;
1898	int		  array_normalized;
1899	int		  array_integer;
1900	int		  array_divisor;
1901	deUintptr array_pointer;
1902	int		  array_buffer_binding;
1903	int		  binding;
1904	int		  relative_offset;
1905	int		  index;
1906
1907	VertexAttribState(int attribindex)
1908		: array_enabled(0)
1909		, array_size(4)
1910		, array_stride(0)
1911		, array_type(GL_FLOAT)
1912		, array_normalized(0)
1913		, array_integer(0)
1914		, array_divisor(0)
1915		, array_pointer(0)
1916		, array_buffer_binding(0)
1917		, binding(attribindex)
1918		, relative_offset(0)
1919		, index(attribindex)
1920	{
1921	}
1922
1923	bool stateVerify()
1924	{
1925		GLint p;
1926		bool  status = true;
1927		glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &p);
1928		if (p != array_enabled)
1929		{
1930			m_context.getTestContext().getLog()
1931				<< tcu::TestLog::Message << "GL_VERTEX_ATTRIB_ARRAY_ENABLED(" << index << ") is " << p << " should be "
1932				<< array_enabled << tcu::TestLog::EndMessage;
1933			status = false;
1934		}
1935		glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &p);
1936		if (p != array_size)
1937		{
1938			m_context.getTestContext().getLog()
1939				<< tcu::TestLog::Message << "GL_VERTEX_ATTRIB_ARRAY_SIZE(" << index << ") is " << p << " should be "
1940				<< array_size << tcu::TestLog::EndMessage;
1941			status = false;
1942		}
1943		glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &p);
1944		if (p != array_stride)
1945		{
1946			m_context.getTestContext().getLog()
1947				<< tcu::TestLog::Message << "GL_VERTEX_ATTRIB_ARRAY_STRIDE(" << index << ") is " << p << " should be "
1948				<< array_stride << tcu::TestLog::EndMessage;
1949			status = false;
1950		}
1951		glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &p);
1952		if (p != array_type)
1953		{
1954			m_context.getTestContext().getLog()
1955				<< tcu::TestLog::Message << "GL_VERTEX_ATTRIB_ARRAY_TYPE(" << index << ") is " << tcu::toHex(p)
1956				<< " should be " << tcu::toHex(array_type) << tcu::TestLog::EndMessage;
1957			status = false;
1958		}
1959		glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &p);
1960		if (p != array_normalized)
1961		{
1962			m_context.getTestContext().getLog()
1963				<< tcu::TestLog::Message << "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED(" << index << ") is " << p
1964				<< " should be " << array_normalized << tcu::TestLog::EndMessage;
1965			status = false;
1966		}
1967		glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_INTEGER, &p);
1968		if (p != array_integer)
1969		{
1970			m_context.getTestContext().getLog()
1971				<< tcu::TestLog::Message << "GL_VERTEX_ATTRIB_ARRAY_INTEGER(" << index << ") is " << p << " should be "
1972				<< array_integer << tcu::TestLog::EndMessage;
1973			status = false;
1974		}
1975		glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &p);
1976		if (p != array_divisor)
1977		{
1978			m_context.getTestContext().getLog()
1979				<< tcu::TestLog::Message << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR(" << index << ") is " << p << " should be "
1980				<< array_divisor << tcu::TestLog::EndMessage;
1981			status = false;
1982		}
1983		void* pp;
1984		glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &pp);
1985		if (reinterpret_cast<deUintptr>(pp) != array_pointer)
1986		{
1987			m_context.getTestContext().getLog()
1988				<< tcu::TestLog::Message << "GL_VERTEX_ATTRIB_ARRAY_POINTER(" << index << ") is " << pp << " should be "
1989				<< reinterpret_cast<void*>(array_pointer) << tcu::TestLog::EndMessage;
1990			status = false;
1991		}
1992		glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &p);
1993		if (p != array_buffer_binding)
1994		{
1995			m_context.getTestContext().getLog()
1996				<< tcu::TestLog::Message << "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING(" << index << ") is " << p
1997				<< " should be " << array_buffer_binding << tcu::TestLog::EndMessage;
1998			status = false;
1999		}
2000		glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_BINDING, &p);
2001		if (static_cast<GLint>(binding) != p)
2002		{
2003			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_VERTEX_ATTRIB_BINDING(" << index
2004												<< ") is " << p << " should be " << binding << tcu::TestLog::EndMessage;
2005			status = false;
2006		}
2007		glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, &p);
2008		if (p != relative_offset)
2009		{
2010			m_context.getTestContext().getLog()
2011				<< tcu::TestLog::Message << "GL_VERTEX_ATTRIB_RELATIVE_OFFSET(" << index << ") is " << p
2012				<< " should be " << relative_offset << tcu::TestLog::EndMessage;
2013			status = false;
2014		}
2015		return status;
2016	}
2017};
2018class VertexBindingState : public glcts::GLWrapper
2019{
2020public:
2021	int		 buffer;
2022	long int offset;
2023	int		 stride;
2024	int		 divisor;
2025	int		 index;
2026
2027	VertexBindingState(int bindingindex) : buffer(0), offset(0), stride(16), divisor(0), index(bindingindex)
2028	{
2029	}
2030	bool stateVerify()
2031	{
2032		bool  status = true;
2033		GLint p;
2034		glGetIntegeri_v(GL_VERTEX_BINDING_BUFFER, index, &p);
2035		if (p != buffer)
2036		{
2037			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_VERTEX_BINDING_BUFFER(" << index
2038												<< ") is " << p << " should be " << buffer << tcu::TestLog::EndMessage;
2039			status = false;
2040		}
2041		GLint64 p64;
2042		glGetInteger64i_v(GL_VERTEX_BINDING_OFFSET, index, &p64);
2043		if (p64 != offset)
2044		{
2045			m_context.getTestContext().getLog()
2046				<< tcu::TestLog::Message << "GL_VERTEX_BINDING_OFFSET(" << index << ") is " << p64 << " should be "
2047				<< offset << tcu::TestLog::EndMessage;
2048			status = false;
2049		}
2050		glGetIntegeri_v(GL_VERTEX_BINDING_STRIDE, index, &p);
2051		if (p != stride)
2052		{
2053			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_VERTEX_BINDING_STRIDE(" << index
2054												<< ") is " << p << " should be " << stride << tcu::TestLog::EndMessage;
2055			status = false;
2056		}
2057		glGetIntegeri_v(GL_VERTEX_BINDING_DIVISOR, index, &p);
2058		if (p != divisor)
2059		{
2060			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_VERTEX_BINDING_DIVISOR(" << index
2061												<< ") is " << p << " should be " << divisor << tcu::TestLog::EndMessage;
2062			status = false;
2063		}
2064		return status;
2065	}
2066};
2067//=============================================================================
2068// 1.5 BasicState1
2069//-----------------------------------------------------------------------------
2070class BasicState1 : public VertexAttribBindingBase
2071{
2072
2073	GLuint m_vao, m_vbo[3];
2074
2075	virtual long Setup()
2076	{
2077		glGenVertexArrays(1, &m_vao);
2078		glGenBuffers(3, m_vbo);
2079		return NO_ERROR;
2080	}
2081
2082	virtual long Cleanup()
2083	{
2084		glDeleteVertexArrays(1, &m_vao);
2085		glDeleteBuffers(3, m_vbo);
2086		return NO_ERROR;
2087	}
2088
2089	virtual long Run()
2090	{
2091		bool status = true;
2092		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[0]);
2093		glBufferData(GL_ARRAY_BUFFER, 10000, NULL, GL_DYNAMIC_COPY);
2094		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[1]);
2095		glBufferData(GL_ARRAY_BUFFER, 10000, NULL, GL_DYNAMIC_COPY);
2096		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[2]);
2097		glBufferData(GL_ARRAY_BUFFER, 10000, NULL, GL_DYNAMIC_COPY);
2098		glBindBuffer(GL_ARRAY_BUFFER, 0);
2099
2100		GLint p;
2101		glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &p);
2102		if (p < 16)
2103		{
2104			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_MAX_VERTEX_ATTRIB_BINDINGS is" << p
2105												<< "but must be at least 16." << tcu::TestLog::EndMessage;
2106			status = false;
2107		}
2108		glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &p);
2109		if (p < 2047)
2110		{
2111			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET is"
2112												<< p << "but must be at least 2047." << tcu::TestLog::EndMessage;
2113			status = false;
2114		}
2115		glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &p);
2116		if (p < 2048)
2117		{
2118			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_MAX_VERTEX_ATTRIB_STRIDE is" << p
2119												<< "but must be at least 2048." << tcu::TestLog::EndMessage;
2120			status = false;
2121		}
2122
2123		glBindVertexArray(m_vao);
2124		// check default state
2125		glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &p);
2126		if (0 != p)
2127		{
2128			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_ELEMENT_ARRAY_BUFFER_BINDING is" << p
2129												<< "should be 0." << tcu::TestLog::EndMessage;
2130			status = false;
2131		}
2132		for (GLuint i = 0; i < 16; ++i)
2133		{
2134			VertexAttribState va(i);
2135			if (!va.stateVerify())
2136				status = false;
2137		}
2138		for (GLuint i = 0; i < 16; ++i)
2139		{
2140			VertexBindingState vb(i);
2141			if (!vb.stateVerify())
2142				status = false;
2143		}
2144		if (!status)
2145		{
2146			m_context.getTestContext().getLog()
2147				<< tcu::TestLog::Message << "Default state check failed." << tcu::TestLog::EndMessage;
2148			status = false;
2149		}
2150
2151		VertexAttribState va0(0);
2152		va0.array_size		 = 2;
2153		va0.array_type		 = GL_BYTE;
2154		va0.array_normalized = 1;
2155		va0.relative_offset  = 16;
2156		VertexBindingState vb0(0);
2157		glVertexAttribFormat(0, 2, GL_BYTE, GL_TRUE, 16);
2158		if (!va0.stateVerify() || !vb0.stateVerify())
2159		{
2160			m_context.getTestContext().getLog()
2161				<< tcu::TestLog::Message << "glVertexAttribFormat state change check failed."
2162				<< tcu::TestLog::EndMessage;
2163			status = false;
2164		}
2165
2166		VertexAttribState va2(2);
2167		va2.array_size		= 3;
2168		va2.array_type		= GL_INT;
2169		va2.array_integer   = 1;
2170		va2.relative_offset = 512;
2171		VertexBindingState vb2(2);
2172		glVertexAttribIFormat(2, 3, GL_INT, 512);
2173		if (!va2.stateVerify() || !vb2.stateVerify())
2174		{
2175			m_context.getTestContext().getLog()
2176				<< tcu::TestLog::Message << "glVertexAttribIFormat state change check failed."
2177				<< tcu::TestLog::EndMessage;
2178			status = false;
2179		}
2180
2181		va0.array_buffer_binding = m_vbo[0];
2182		vb0.buffer				 = m_vbo[0];
2183		vb0.offset				 = 2048;
2184		vb0.stride				 = 128;
2185		glBindVertexBuffer(0, m_vbo[0], 2048, 128);
2186		if (!va0.stateVerify() || !vb0.stateVerify())
2187		{
2188			m_context.getTestContext().getLog()
2189				<< tcu::TestLog::Message << "glBindVertexBuffer state change check failed." << tcu::TestLog::EndMessage;
2190			status = false;
2191		}
2192
2193		va2.array_buffer_binding = m_vbo[2];
2194		vb2.buffer				 = m_vbo[2];
2195		vb2.offset				 = 64;
2196		vb2.stride				 = 256;
2197		glBindVertexBuffer(2, m_vbo[2], 64, 256);
2198		if (!va2.stateVerify() || !vb2.stateVerify())
2199		{
2200			m_context.getTestContext().getLog()
2201				<< tcu::TestLog::Message << "glBindVertexBuffer state change check failed." << tcu::TestLog::EndMessage;
2202			status = false;
2203		}
2204
2205		glVertexAttribBinding(2, 0);
2206		va2.binding				 = 0;
2207		va2.array_buffer_binding = m_vbo[0];
2208		if (!va0.stateVerify() || !vb0.stateVerify() || !va2.stateVerify() || !vb2.stateVerify())
2209		{
2210			m_context.getTestContext().getLog()
2211				<< tcu::TestLog::Message << "glVertexAttribBinding state change check failed."
2212				<< tcu::TestLog::EndMessage;
2213			status = false;
2214		}
2215
2216		VertexAttribState  va15(15);
2217		VertexBindingState vb15(15);
2218		glVertexAttribBinding(0, 15);
2219		va0.binding				 = 15;
2220		va0.array_buffer_binding = 0;
2221		if (!va0.stateVerify() || !vb0.stateVerify() || !va15.stateVerify() || !vb15.stateVerify())
2222		{
2223			m_context.getTestContext().getLog()
2224				<< tcu::TestLog::Message << "glVertexAttribBinding state change check failed."
2225				<< tcu::TestLog::EndMessage;
2226			status = false;
2227		}
2228
2229		glBindVertexBuffer(15, m_vbo[1], 16, 32);
2230		va0.array_buffer_binding  = m_vbo[1];
2231		va15.array_buffer_binding = m_vbo[1];
2232		vb15.buffer				  = m_vbo[1];
2233		vb15.offset				  = 16;
2234		vb15.stride				  = 32;
2235		if (!va0.stateVerify() || !vb0.stateVerify() || !va15.stateVerify() || !vb15.stateVerify())
2236		{
2237			m_context.getTestContext().getLog()
2238				<< tcu::TestLog::Message << "glBindVertexBuffer state change check failed." << tcu::TestLog::EndMessage;
2239			status = false;
2240		}
2241
2242		glVertexAttribFormat(15, 1, GL_HALF_FLOAT, GL_FALSE, 1024);
2243		va15.array_size		 = 1;
2244		va15.array_type		 = GL_HALF_FLOAT;
2245		va15.relative_offset = 1024;
2246		if (!va0.stateVerify() || !vb0.stateVerify() || !va2.stateVerify() || !vb2.stateVerify() ||
2247			!va15.stateVerify() || !vb15.stateVerify())
2248		{
2249			m_context.getTestContext().getLog()
2250				<< tcu::TestLog::Message << "glVertexAttribFormat state change check failed."
2251				<< tcu::TestLog::EndMessage;
2252			status = false;
2253		}
2254
2255		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[2]);
2256		glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_FALSE, 8, (void*)640);
2257		glBindBuffer(GL_ARRAY_BUFFER, 0);
2258		va0.array_size			 = 4;
2259		va0.array_type			 = GL_UNSIGNED_BYTE;
2260		va0.array_stride		 = 8;
2261		va0.array_pointer		 = 640;
2262		va0.relative_offset		 = 0;
2263		va0.array_normalized	 = 0;
2264		va0.binding				 = 0;
2265		va0.array_buffer_binding = m_vbo[2];
2266		vb0.buffer				 = m_vbo[2];
2267		vb0.offset				 = 640;
2268		vb0.stride				 = 8;
2269		va2.array_buffer_binding = m_vbo[2];
2270		if (!va0.stateVerify() || !vb0.stateVerify() || !va2.stateVerify() || !vb2.stateVerify() ||
2271			!va15.stateVerify() || !vb15.stateVerify())
2272		{
2273			m_context.getTestContext().getLog()
2274				<< tcu::TestLog::Message << "glVertexAttribPointer state change check failed."
2275				<< tcu::TestLog::EndMessage;
2276			status = false;
2277		}
2278
2279		glBindVertexBuffer(0, m_vbo[1], 80, 24);
2280		vb0.buffer				 = m_vbo[1];
2281		vb0.offset				 = 80;
2282		vb0.stride				 = 24;
2283		va2.array_buffer_binding = m_vbo[1];
2284		va0.array_buffer_binding = m_vbo[1];
2285		if (!va0.stateVerify() || !vb0.stateVerify() || !va2.stateVerify() || !vb2.stateVerify() ||
2286			!va15.stateVerify() || !vb15.stateVerify())
2287		{
2288			m_context.getTestContext().getLog()
2289				<< tcu::TestLog::Message << "glBindVertexBuffer state change check failed." << tcu::TestLog::EndMessage;
2290			status = false;
2291		}
2292
2293		if (status)
2294			return NO_ERROR;
2295		else
2296			return ERROR;
2297	}
2298};
2299//=============================================================================
2300// 1.6 BasicState2
2301//-----------------------------------------------------------------------------
2302class BasicState2 : public VertexAttribBindingBase
2303{
2304
2305	GLuint m_vao;
2306
2307	virtual long Setup()
2308	{
2309		glGenVertexArrays(1, &m_vao);
2310		return NO_ERROR;
2311	}
2312
2313	virtual long Cleanup()
2314	{
2315		glDeleteVertexArrays(1, &m_vao);
2316		return NO_ERROR;
2317	}
2318
2319	virtual long Run()
2320	{
2321		bool status = true;
2322		glBindVertexArray(m_vao);
2323
2324		for (GLuint i = 0; i < 16; ++i)
2325		{
2326			VertexAttribState  va(i);
2327			VertexBindingState vb(i);
2328			glVertexAttribDivisor(i, i + 7);
2329			va.array_divisor = i + 7;
2330			vb.divisor		 = i + 7;
2331			if (!va.stateVerify() || !vb.stateVerify())
2332			{
2333				m_context.getTestContext().getLog()
2334					<< tcu::TestLog::Message << "glVertexAttribDivisor state change check failed."
2335					<< tcu::TestLog::EndMessage;
2336				status = false;
2337			}
2338		}
2339		for (GLuint i = 0; i < 16; ++i)
2340		{
2341			VertexAttribState  va(i);
2342			VertexBindingState vb(i);
2343			glVertexBindingDivisor(i, i);
2344			va.array_divisor = i;
2345			vb.divisor		 = i;
2346			if (!va.stateVerify() || !vb.stateVerify())
2347			{
2348				m_context.getTestContext().getLog()
2349					<< tcu::TestLog::Message << "glVertexBindingDivisor state change check failed."
2350					<< tcu::TestLog::EndMessage;
2351				status = false;
2352			}
2353		}
2354
2355		glVertexAttribBinding(2, 5);
2356		VertexAttribState va5(5);
2357		va5.array_divisor = 5;
2358		VertexBindingState vb5(5);
2359		vb5.divisor = 5;
2360		VertexAttribState va2(2);
2361		va2.array_divisor = 5; // binding state seen thru mapping
2362		VertexBindingState vb2(2);
2363		vb2.divisor = 2;
2364		va2.binding = 5;
2365		if (!va5.stateVerify() || !vb5.stateVerify() || !va2.stateVerify() || !vb2.stateVerify())
2366		{
2367			m_context.getTestContext().getLog()
2368				<< tcu::TestLog::Message << "glVertexAttribBinding state change check failed."
2369				<< tcu::TestLog::EndMessage;
2370			status = false;
2371		}
2372
2373		glVertexAttribDivisor(2, 23);
2374		va2.binding		  = 2; // glVAD defaults mapping
2375		va2.array_divisor = 23;
2376		vb2.divisor		  = 23;
2377		if (!va5.stateVerify() || !vb5.stateVerify() || !va2.stateVerify() || !vb2.stateVerify())
2378		{
2379			m_context.getTestContext().getLog()
2380				<< tcu::TestLog::Message << "glVertexAttribDivisor state change check failed."
2381				<< tcu::TestLog::EndMessage;
2382			status = false;
2383		}
2384
2385		if (status)
2386			return NO_ERROR;
2387		else
2388			return ERROR;
2389	}
2390};
2391//=============================================================================
2392// 2.1 AdvancedBindingUpdate
2393//-----------------------------------------------------------------------------
2394class AdvancedBindingUpdate : public VertexAttribBindingBase
2395{
2396	bool   pipeline;
2397	GLuint m_vao[2], m_vbo[2], m_ebo[2], m_vsp, m_fsp, m_ppo;
2398
2399	virtual long Setup()
2400	{
2401		glGenVertexArrays(2, m_vao);
2402		glGenBuffers(2, m_vbo);
2403		glGenBuffers(2, m_ebo);
2404		if (pipeline)
2405		{
2406			m_vsp = m_fsp = 0;
2407			glGenProgramPipelines(1, &m_ppo);
2408		}
2409		else
2410		{
2411			m_ppo = 0;
2412		}
2413		return NO_ERROR;
2414	}
2415
2416	virtual long Cleanup()
2417	{
2418		glDeleteVertexArrays(2, m_vao);
2419		glDeleteBuffers(2, m_vbo);
2420		glDeleteBuffers(2, m_ebo);
2421		if (pipeline)
2422		{
2423			glDeleteProgram(m_vsp);
2424			glDeleteProgram(m_fsp);
2425			glDeleteProgramPipelines(1, &m_ppo);
2426		}
2427		else
2428		{
2429			glUseProgram(0);
2430			glDeleteProgram(m_ppo);
2431		}
2432		return NO_ERROR;
2433	}
2434
2435	virtual long Run()
2436	{
2437		const char* const glsl_vs =
2438			"#version 310 es" NL "layout(location = 0) in vec4 vs_in_position;" NL
2439			"layout(location = 1) in vec2 vs_in_color_rg;" NL "layout(location = 2) in float vs_in_color_b;" NL
2440			"layout(location = 3) in uvec3 vs_in_data0;" NL "layout(location = 4) in ivec2 vs_in_data1;" NL
2441			"out vec2 color_rg;" NL "out float color_b;" NL "flat out uvec3 data0;" NL "flat out ivec2 data1;" NL
2442			"void main() {" NL "  data0 = vs_in_data0;" NL "  data1 = vs_in_data1;" NL "  color_b = vs_in_color_b;" NL
2443			"  color_rg = vs_in_color_rg;" NL "  gl_Position = vs_in_position;" NL "}";
2444		const char* const glsl_fs =
2445			"#version 310 es" NL "precision highp float;" NL "precision highp int;" NL "in vec2 color_rg;" NL
2446			"in float color_b;" NL "flat in uvec3 data0;" NL "flat in ivec2 data1;" NL "out vec4 fs_out_color;" NL
2447			"uniform uvec3 g_expected_data0;" NL "uniform ivec2 g_expected_data1;" NL "void main() {" NL
2448			"  fs_out_color = vec4(color_rg, color_b, 1);" NL
2449			"  if (data0 != g_expected_data0) fs_out_color = vec4(1);" NL
2450			"  if (data1 != g_expected_data1) fs_out_color = vec4(1);" NL "}";
2451		if (pipeline)
2452		{
2453			m_vsp = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
2454			m_fsp = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs);
2455			if (!CheckProgram(m_vsp) || !CheckProgram(m_fsp))
2456				return ERROR;
2457			glUseProgramStages(m_ppo, GL_VERTEX_SHADER_BIT, m_vsp);
2458			glUseProgramStages(m_ppo, GL_FRAGMENT_SHADER_BIT, m_fsp);
2459		}
2460		else
2461		{
2462			m_ppo			 = glCreateProgram();
2463			const GLuint sh  = glCreateShader(GL_VERTEX_SHADER);
2464			const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
2465			glShaderSource(sh, 1, &glsl_vs, NULL);
2466			glShaderSource(fsh, 1, &glsl_fs, NULL);
2467			glCompileShader(sh);
2468			glCompileShader(fsh);
2469			glAttachShader(m_ppo, sh);
2470			glAttachShader(m_ppo, fsh);
2471			glDeleteShader(sh);
2472			glDeleteShader(fsh);
2473			glLinkProgram(m_ppo);
2474			if (!CheckProgram(m_ppo))
2475				return ERROR;
2476		}
2477
2478		const GLsizei  kStride[2] = { 52, 64 };
2479		const GLintptr kOffset[2] = { 0, 8 };
2480		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[0]);
2481		/* first VBO */
2482		{
2483			glBufferData(GL_ARRAY_BUFFER, kOffset[0] + 4 * kStride[0], NULL, GL_STATIC_DRAW);
2484			GLubyte* ptr = static_cast<GLubyte*>(
2485				glMapBufferRange(GL_ARRAY_BUFFER, 0, kOffset[0] + 4 * kStride[0], GL_MAP_WRITE_BIT));
2486			*reinterpret_cast<Vec2*>(&ptr[kOffset[0] + 0 * kStride[0]]) = Vec2(-1.0f, -1.0f);
2487			*reinterpret_cast<Vec2*>(&ptr[kOffset[0] + 1 * kStride[0]]) = Vec2(1.0f, -1.0f);
2488			*reinterpret_cast<Vec2*>(&ptr[kOffset[0] + 2 * kStride[0]]) = Vec2(1.0f, 1.0f);
2489			*reinterpret_cast<Vec2*>(&ptr[kOffset[0] + 3 * kStride[0]]) = Vec2(-1.0f, 1.0f);
2490			for (int i = 0; i < 4; ++i)
2491			{
2492				*reinterpret_cast<Vec2*>(&ptr[kOffset[0] + 8 + i * kStride[0]])   = Vec2(0.0f, 1.0f);
2493				*reinterpret_cast<float*>(&ptr[kOffset[0] + 16 + i * kStride[0]]) = 0.0f;
2494				*reinterpret_cast<UVec3*>(&ptr[kOffset[0] + 20 + i * kStride[0]]) = UVec3(1, 2, 3);
2495				*reinterpret_cast<IVec2*>(&ptr[kOffset[0] + 44 + i * kStride[0]]) = IVec2(1, 2);
2496			}
2497			glUnmapBuffer(GL_ARRAY_BUFFER);
2498		}
2499		glBindBuffer(GL_ARRAY_BUFFER, m_vbo[1]);
2500		/* second VBO */
2501		{
2502			glBufferData(GL_ARRAY_BUFFER, kOffset[1] + 4 * kStride[1], NULL, GL_STATIC_DRAW);
2503			GLubyte* ptr = static_cast<GLubyte*>(
2504				glMapBufferRange(GL_ARRAY_BUFFER, 0, kOffset[1] + 4 * kStride[1], GL_MAP_WRITE_BIT));
2505			*reinterpret_cast<Vec2*>(&ptr[kOffset[1] + 0 * kStride[1]]) = Vec2(-1.0f, 1.0f);
2506			*reinterpret_cast<Vec2*>(&ptr[kOffset[1] + 1 * kStride[1]]) = Vec2(1.0f, 1.0f);
2507			*reinterpret_cast<Vec2*>(&ptr[kOffset[1] + 2 * kStride[1]]) = Vec2(1.0f, -1.0f);
2508			*reinterpret_cast<Vec2*>(&ptr[kOffset[1] + 3 * kStride[1]]) = Vec2(-1.0f, -1.0f);
2509			for (int i = 0; i < 4; ++i)
2510			{
2511				*reinterpret_cast<Vec2*>(&ptr[kOffset[1] + 8 + i * kStride[1]])   = Vec2(0.0f, 0.0f);
2512				*reinterpret_cast<float*>(&ptr[kOffset[1] + 16 + i * kStride[1]]) = 1.0f;
2513				*reinterpret_cast<UVec3*>(&ptr[kOffset[1] + 20 + i * kStride[1]]) = UVec3(4, 5, 6);
2514				*reinterpret_cast<IVec2*>(&ptr[kOffset[1] + 44 + i * kStride[1]]) = IVec2(3, 4);
2515			}
2516			glUnmapBuffer(GL_ARRAY_BUFFER);
2517		}
2518		glBindBuffer(GL_ARRAY_BUFFER, 0);
2519
2520		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo[0]);
2521		/* first EBO */
2522		{
2523			GLushort data[4] = { 0, 1, 3, 2 };
2524			glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2525		}
2526		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo[1]);
2527		/* second EBO */
2528		{
2529			GLuint data[4] = { 3, 2, 0, 1 };
2530			glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2531		}
2532		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2533
2534		glBindVertexArray(m_vao[0]);
2535		glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, 0);
2536		glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE, 8);
2537		glVertexAttribFormat(2, 1, GL_FLOAT, GL_FALSE, 16);
2538		glVertexAttribIFormat(3, 3, GL_UNSIGNED_INT, 20);
2539		glVertexAttribIFormat(4, 2, GL_INT, 44);
2540		for (GLuint i = 0; i < 5; ++i)
2541		{
2542			glVertexAttribBinding(i, 0);
2543			glEnableVertexAttribArray(i);
2544		}
2545		glBindVertexArray(m_vao[1]);
2546		glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, 0);
2547		glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE, 8);
2548		glVertexAttribFormat(2, 1, GL_FLOAT, GL_FALSE, 16);
2549		glVertexAttribIFormat(3, 3, GL_UNSIGNED_INT, 20);
2550		glVertexAttribIFormat(4, 2, GL_INT, 44);
2551		glVertexAttribBinding(0, 1);
2552		glVertexAttribBinding(1, 8);
2553		glVertexAttribBinding(2, 1);
2554		glVertexAttribBinding(3, 1);
2555		glVertexAttribBinding(4, 8);
2556		glEnableVertexAttribArray(0);
2557		glEnableVertexAttribArray(1);
2558		glEnableVertexAttribArray(2);
2559		glEnableVertexAttribArray(3);
2560		glEnableVertexAttribArray(4);
2561		glBindVertexBuffer(1, m_vbo[1], kOffset[1], kStride[1]);
2562		glBindVertexBuffer(8, m_vbo[0], kOffset[0], kStride[0]);
2563		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo[1]);
2564		glBindVertexArray(0);
2565
2566		glClear(GL_COLOR_BUFFER_BIT);
2567		GLuint ppo;
2568		if (pipeline)
2569		{
2570			glBindProgramPipeline(m_ppo);
2571			ppo = m_fsp;
2572		}
2573		else
2574		{
2575			glUseProgram(m_ppo);
2576			ppo = m_ppo;
2577		}
2578		glBindVertexArray(m_vao[0]);
2579
2580		// Bind first VBO
2581		glProgramUniform3ui(ppo, glGetUniformLocation(ppo, "g_expected_data0"), 1, 2, 3);
2582		glProgramUniform2i(ppo, glGetUniformLocation(ppo, "g_expected_data1"), 1, 2);
2583		glBindVertexBuffer(0, m_vbo[0], kOffset[0], kStride[0]);
2584		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo[0]);
2585		glDrawElementsInstanced(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1);
2586
2587		bool status = true;
2588		if (!CheckFB(Vec3(0, 1, 0)))
2589			status = false;
2590		if (!status)
2591			return ERROR;
2592
2593		// Bind second VBO (change all vertex attribs with one call)
2594		glProgramUniform3ui(ppo, glGetUniformLocation(ppo, "g_expected_data0"), 4, 5, 6);
2595		glProgramUniform2i(ppo, glGetUniformLocation(ppo, "g_expected_data1"), 3, 4);
2596
2597		glBindVertexBuffer(0, m_vbo[1], kOffset[1], kStride[1]);
2598		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo[1]);
2599		glDrawElementsInstanced(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0, 1);
2600
2601		if (!CheckFB(Vec3(0, 0, 1)))
2602			status = false;
2603		if (!status)
2604			return ERROR;
2605
2606		// Change attrib bindings (all attribs from one buffer)
2607		glBindVertexBuffer(0, 0, 0, 0); // "unbind" buffer
2608
2609		glProgramUniform3ui(ppo, glGetUniformLocation(ppo, "g_expected_data0"), 1, 2, 3);
2610		glProgramUniform2i(ppo, glGetUniformLocation(ppo, "g_expected_data1"), 1, 2);
2611
2612		for (GLuint i = 0; i < 5; ++i)
2613			glVertexAttribBinding(i, 15);
2614		glBindVertexBuffer(15, m_vbo[0], kOffset[0], kStride[0]);
2615		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo[0]);
2616		glDrawElementsInstanced(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1);
2617
2618		if (!CheckFB(Vec3(0, 1, 0)))
2619			status = false;
2620		if (!status)
2621			return ERROR;
2622
2623		// Change attrib bindings (attribs from two buffers)
2624		glBindVertexBuffer(15, 0, 0, 0); // "unbind" buffer
2625
2626		glProgramUniform3ui(ppo, glGetUniformLocation(ppo, "g_expected_data0"), 1, 2, 3);
2627		glProgramUniform2i(ppo, glGetUniformLocation(ppo, "g_expected_data1"), 3, 4);
2628
2629		glBindVertexBuffer(7, m_vbo[0], kOffset[0], kStride[0]);
2630		glBindVertexBuffer(12, m_vbo[1], kOffset[1], kStride[1]);
2631		glVertexAttribBinding(0, 7);
2632		glVertexAttribBinding(1, 12);
2633		glVertexAttribBinding(2, 12);
2634		glVertexAttribBinding(3, 7);
2635		glVertexAttribBinding(4, 12);
2636		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo[0]);
2637		glDrawElementsInstanced(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1);
2638
2639		if (!CheckFB(Vec3(0, 0, 1)))
2640			status = false;
2641		if (!status)
2642			return ERROR;
2643
2644		// Disable one of the attribs
2645		glClear(GL_COLOR_BUFFER_BIT);
2646		glProgramUniform2i(ppo, glGetUniformLocation(ppo, "g_expected_data1"), 0, 0);
2647		glDisableVertexAttribArray(4);
2648		glVertexAttribI4i(4, 0, 0, 0, 0);
2649		glDrawElementsInstanced(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1);
2650
2651		if (!CheckFB(Vec3(0, 0, 1)))
2652			status = false;
2653		if (!status)
2654			return ERROR;
2655
2656		// Change VAO
2657		glProgramUniform3ui(ppo, glGetUniformLocation(ppo, "g_expected_data0"), 4, 5, 6);
2658		glProgramUniform2i(ppo, glGetUniformLocation(ppo, "g_expected_data1"), 1, 2);
2659
2660		glBindVertexArray(m_vao[1]);
2661		glDrawElementsInstanced(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0, 1);
2662
2663		if (!CheckFB(Vec3(0, 1, 1)))
2664			status = false;
2665		if (!status)
2666			return ERROR;
2667
2668		return NO_ERROR;
2669	}
2670
2671public:
2672	AdvancedBindingUpdate() : pipeline(true)
2673	{
2674	}
2675};
2676//=============================================================================
2677// 2.3 AdvancedIterations
2678//-----------------------------------------------------------------------------
2679class AdvancedIterations : public VertexAttribBindingBase
2680{
2681
2682	GLuint m_po, m_vao[2], m_xfo[2], m_buffer[2];
2683
2684	virtual long Setup()
2685	{
2686		m_po = 0;
2687		glGenVertexArrays(2, m_vao);
2688		glGenTransformFeedbacks(2, m_xfo);
2689		glGenBuffers(2, m_buffer);
2690		return NO_ERROR;
2691	}
2692
2693	virtual long Cleanup()
2694	{
2695		glDisable(GL_RASTERIZER_DISCARD);
2696		glUseProgram(0);
2697		glDeleteProgram(m_po);
2698		glDeleteVertexArrays(2, m_vao);
2699		glDeleteTransformFeedbacks(2, m_xfo);
2700		glDeleteBuffers(2, m_buffer);
2701		return NO_ERROR;
2702	}
2703
2704	virtual long Run()
2705	{
2706		const char* const glsl_vs = "#version 310 es" NL "in ivec4 vs_in_data;" NL "flat out ivec4 data;" NL
2707									"void main() {" NL "  data = vs_in_data + 1;" NL "}";
2708		const char* const glsl_fs =
2709			"#version 310 es" NL "precision mediump float;" NL "flat in ivec4 data;" NL "out vec4 fs_out_color;" NL
2710			"void main() {" NL "  fs_out_color = vec4(data);" NL "}";
2711		m_po = glCreateProgram();
2712		/* attach shader */
2713		{
2714			const GLuint sh  = glCreateShader(GL_VERTEX_SHADER);
2715			const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
2716			glShaderSource(sh, 1, &glsl_vs, NULL);
2717			glShaderSource(fsh, 1, &glsl_fs, NULL);
2718			glCompileShader(sh);
2719			glCompileShader(fsh);
2720			glAttachShader(m_po, sh);
2721			glAttachShader(m_po, fsh);
2722			glDeleteShader(sh);
2723			glDeleteShader(fsh);
2724		}
2725		if (!RelinkProgram(1))
2726			return ERROR;
2727
2728		glBindBuffer(GL_ARRAY_BUFFER, m_buffer[0]);
2729		IVec4 zero(0);
2730		glBufferData(GL_ARRAY_BUFFER, 16, &zero, GL_STATIC_DRAW);
2731		glBindBuffer(GL_ARRAY_BUFFER, 0);
2732
2733		glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer[1]);
2734		glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 16, &zero, GL_DYNAMIC_READ);
2735		glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
2736
2737		glBindVertexArray(m_vao[0]);
2738		glVertexAttribIFormat(1, 4, GL_INT, 0);
2739		glEnableVertexAttribArray(1);
2740		glBindVertexBuffer(1, m_buffer[0], 0, 16);
2741		glBindVertexArray(m_vao[1]);
2742		glVertexAttribIFormat(1, 4, GL_INT, 0);
2743		glEnableVertexAttribArray(1);
2744		glBindVertexBuffer(1, m_buffer[1], 0, 16);
2745		glBindVertexArray(0);
2746
2747		glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfo[0]);
2748		glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer[1]);
2749		glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfo[1]);
2750		glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer[0]);
2751		glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
2752
2753		glEnable(GL_RASTERIZER_DISCARD);
2754		glUseProgram(m_po);
2755
2756		for (int i = 0; i < 10; ++i)
2757		{
2758			glBindVertexArray(m_vao[i % 2]);
2759			glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfo[i % 2]);
2760			glBeginTransformFeedback(GL_POINTS);
2761			glDrawArrays(GL_POINTS, 0, 1);
2762			glEndTransformFeedback();
2763		}
2764		/* */
2765		{
2766			IVec4* data =
2767				static_cast<IVec4*>(glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
2768			if (!IsEqual(*data, IVec4(10)))
2769			{
2770				m_context.getTestContext().getLog()
2771					<< tcu::TestLog::Message << "Data is: " << (*data)[0] << " " << (*data)[1] << " " << (*data)[2]
2772					<< " " << (*data)[3] << ", data should be: 10 10 10 10." << tcu::TestLog::EndMessage;
2773				return ERROR;
2774			}
2775			glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2776		}
2777
2778		if (!RelinkProgram(5))
2779			return ERROR;
2780		glBindVertexArray(m_vao[0]);
2781		glDisableVertexAttribArray(1);
2782		glBindVertexBuffer(1, 0, 0, 0);
2783		glVertexAttribIFormat(5, 4, GL_INT, 0);
2784		glEnableVertexAttribArray(5);
2785		glBindVertexBuffer(5, m_buffer[0], 0, 16);
2786		glBindVertexArray(m_vao[1]);
2787		glDisableVertexAttribArray(1);
2788		glBindVertexBuffer(1, 0, 0, 0);
2789		glVertexAttribIFormat(5, 4, GL_INT, 0);
2790		glEnableVertexAttribArray(5);
2791		glBindVertexBuffer(7, m_buffer[1], 0, 16);
2792		glVertexAttribBinding(5, 7);
2793		glBindVertexArray(0);
2794
2795		for (int i = 0; i < 10; ++i)
2796		{
2797			glBindVertexArray(m_vao[i % 2]);
2798			glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfo[i % 2]);
2799			glBeginTransformFeedback(GL_POINTS);
2800			glDrawArrays(GL_POINTS, 0, 1);
2801			glEndTransformFeedback();
2802		}
2803		/* */
2804		{
2805			IVec4* data =
2806				static_cast<IVec4*>(glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
2807			if (!IsEqual(*data, IVec4(20)))
2808			{
2809				m_context.getTestContext().getLog()
2810					<< tcu::TestLog::Message << "Data is: " << (*data)[0] << " " << (*data)[1] << " " << (*data)[2]
2811					<< " " << (*data)[3] << ", data should be: 20 20 20 20." << tcu::TestLog::EndMessage;
2812				return ERROR;
2813			}
2814			glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2815		}
2816
2817		if (!RelinkProgram(11))
2818			return ERROR;
2819		glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
2820		glBindVertexArray(m_vao[0]);
2821		glDisableVertexAttribArray(5);
2822		glBindVertexBuffer(5, 0, 0, 0);
2823		glVertexAttribIFormat(11, 4, GL_INT, 0);
2824		glEnableVertexAttribArray(11);
2825		for (int i = 0; i < 10; ++i)
2826		{
2827			glBindVertexBuffer(11, m_buffer[i % 2], 0, 16);
2828			glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer[(i + 1) % 2]);
2829			glBeginTransformFeedback(GL_POINTS);
2830			glDrawArrays(GL_POINTS, 0, 1);
2831			glEndTransformFeedback();
2832		}
2833		/* */
2834		{
2835			IVec4* data =
2836				static_cast<IVec4*>(glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
2837			if (!IsEqual(*data, IVec4(30)))
2838			{
2839				m_context.getTestContext().getLog()
2840					<< tcu::TestLog::Message << "Data is: " << (*data)[0] << " " << (*data)[1] << " " << (*data)[2]
2841					<< " " << (*data)[3] << ", data should be: 30 30 30 30." << tcu::TestLog::EndMessage;
2842				return ERROR;
2843			}
2844		}
2845
2846		return NO_ERROR;
2847	}
2848
2849	bool RelinkProgram(GLuint index)
2850	{
2851		glBindAttribLocation(m_po, index, "vs_in_data");
2852		/* setup XFB */
2853		{
2854			const GLchar* const v[1] = { "data" };
2855			glTransformFeedbackVaryings(m_po, 1, v, GL_INTERLEAVED_ATTRIBS);
2856		}
2857		glLinkProgram(m_po);
2858		if (!CheckProgram(m_po))
2859			return false;
2860		return true;
2861	}
2862};
2863//=============================================================================
2864// 2.4 AdvancedLargeStrideAndOffsetsNewAndLegacyAPI
2865//-----------------------------------------------------------------------------
2866class AdvancedLargeStrideAndOffsetsNewAndLegacyAPI : public VertexAttribBindingBase
2867{
2868	bool   pipeline;
2869	GLuint m_vsp, m_fsp, m_ppo, m_ssbo, m_vao, m_vbo;
2870
2871	virtual long Setup()
2872	{
2873		m_vsp = 0;
2874		if (pipeline)
2875		{
2876			m_vsp = m_fsp = 0;
2877			glGenProgramPipelines(1, &m_ppo);
2878		}
2879		else
2880		{
2881			m_ppo = 0;
2882		}
2883		glGenBuffers(1, &m_ssbo);
2884		glGenVertexArrays(1, &m_vao);
2885		glGenBuffers(1, &m_vbo);
2886		return NO_ERROR;
2887	}
2888
2889	virtual long Cleanup()
2890	{
2891		glDisable(GL_RASTERIZER_DISCARD);
2892		if (pipeline)
2893		{
2894			glDeleteProgram(m_vsp);
2895			glDeleteProgram(m_fsp);
2896			glDeleteProgramPipelines(1, &m_ppo);
2897		}
2898		else
2899		{
2900			glUseProgram(0);
2901			glDeleteProgram(m_ppo);
2902		}
2903		glDeleteBuffers(1, &m_ssbo);
2904		glDeleteVertexArrays(1, &m_vao);
2905		glDeleteBuffers(1, &m_vbo);
2906		return NO_ERROR;
2907	}
2908
2909	virtual long Run()
2910	{
2911		if (!IsSSBOInVSFSAvailable(2))
2912			return NOT_SUPPORTED;
2913		const char* const glsl_vs =
2914			"#version 310 es" NL "layout(location = 0) in vec2 vs_in_attrib0;" NL
2915			"layout(location = 4) in ivec2 vs_in_attrib1;" NL "layout(location = 8) in uvec2 vs_in_attrib2;" NL
2916			"layout(location = 15) in float vs_in_attrib3;" NL "layout(std430, binding = 1) buffer Output {" NL
2917			"  vec2 attrib0[4];" NL "  ivec2 attrib1[4];" NL "  uvec2 attrib2[4];" NL "  float attrib3[4];" NL
2918			"} g_output;" NL "void main() {" NL
2919			"  g_output.attrib0[2 * gl_InstanceID + gl_VertexID] = vs_in_attrib0;" NL
2920			"  g_output.attrib1[2 * gl_InstanceID + gl_VertexID] = vs_in_attrib1;" NL
2921			"  g_output.attrib2[2 * gl_InstanceID + gl_VertexID] = vs_in_attrib2;" NL
2922			"  g_output.attrib3[2 * gl_InstanceID + gl_VertexID] = vs_in_attrib3;" NL "}";
2923		const char* const glsl_fs = "#version 310 es" NL "precision mediump float;" NL "out vec4 fs_out_color;" NL
2924									"void main() {" NL "  fs_out_color = vec4(0.5,0.5,0.5,1.0);" NL "}";
2925		if (pipeline)
2926		{
2927			m_vsp = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
2928			m_fsp = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs);
2929			if (!CheckProgram(m_vsp) || !CheckProgram(m_fsp))
2930				return ERROR;
2931			glUseProgramStages(m_ppo, GL_VERTEX_SHADER_BIT, m_vsp);
2932			glUseProgramStages(m_ppo, GL_FRAGMENT_SHADER_BIT, m_fsp);
2933		}
2934		else
2935		{
2936			m_ppo			 = glCreateProgram();
2937			const GLuint sh  = glCreateShader(GL_VERTEX_SHADER);
2938			const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
2939			glShaderSource(sh, 1, &glsl_vs, NULL);
2940			glShaderSource(fsh, 1, &glsl_fs, NULL);
2941			glCompileShader(sh);
2942			glCompileShader(fsh);
2943			glAttachShader(m_ppo, sh);
2944			glAttachShader(m_ppo, fsh);
2945			glDeleteShader(sh);
2946			glDeleteShader(fsh);
2947			glLinkProgram(m_ppo);
2948			if (!CheckProgram(m_ppo))
2949				return ERROR;
2950		}
2951
2952		/* vbo */
2953		{
2954			glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
2955			glBufferData(GL_ARRAY_BUFFER, 100000, NULL, GL_STATIC_DRAW);
2956			GLubyte* ptr = static_cast<GLubyte*>(glMapBufferRange(GL_ARRAY_BUFFER, 0, 100000, GL_MAP_WRITE_BIT));
2957			// attrib0
2958			*reinterpret_cast<Vec2*>(&ptr[16 + 0 * 2048]) = Vec2(1.0f, 2.0f);
2959			*reinterpret_cast<Vec2*>(&ptr[16 + 1 * 2048]) = Vec2(3.0f, 4.0f);
2960			// attrib1
2961			*reinterpret_cast<IVec2*>(&ptr[128 + 0 * 2048]) = IVec2(5, 6);
2962			*reinterpret_cast<IVec2*>(&ptr[128 + 1 * 2048]) = IVec2(7, 8);
2963			// attrib2
2964			*reinterpret_cast<UVec2*>(&ptr[1024 + 0 * 2048]) = UVec2(9, 10);
2965			*reinterpret_cast<UVec2*>(&ptr[1024 + 1 * 2048]) = UVec2(11, 12);
2966			// attrib3
2967			*reinterpret_cast<float*>(&ptr[2032 + 0 * 2048]) = 13.0f;
2968			*reinterpret_cast<float*>(&ptr[2032 + 1 * 2048]) = 14.0f;
2969			glUnmapBuffer(GL_ARRAY_BUFFER);
2970			glBindBuffer(GL_ARRAY_BUFFER, 0);
2971		}
2972		// vao
2973		glBindVertexArray(m_vao);
2974		glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, 16);
2975		glVertexAttribIFormat(8, 2, GL_UNSIGNED_INT, 1024);
2976		glVertexAttribFormat(15, 1, GL_FLOAT, GL_FALSE, 2032);
2977		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
2978		glVertexAttribIPointer(4, 2, GL_INT, 2048, reinterpret_cast<void*>(128));
2979		glBindBuffer(GL_ARRAY_BUFFER, 0);
2980		glVertexAttribBinding(8, 3);
2981		glVertexAttribBinding(15, 3);
2982		glBindVertexBuffer(0, m_vbo, 0, 2048);
2983		glBindVertexBuffer(3, m_vbo, 0, 2048);
2984		glEnableVertexAttribArray(0);
2985		glEnableVertexAttribArray(4);
2986		glEnableVertexAttribArray(8);
2987		glEnableVertexAttribArray(15);
2988		glBindVertexArray(0);
2989
2990		// ssbo
2991		std::vector<GLubyte> data((sizeof(Vec2) + sizeof(IVec2) + sizeof(UVec2) + sizeof(float)) * 4, 0xff);
2992		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_ssbo);
2993		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)data.size(), &data[0], GL_DYNAMIC_DRAW);
2994
2995		glEnable(GL_RASTERIZER_DISCARD);
2996		if (pipeline)
2997			glBindProgramPipeline(m_ppo);
2998		else
2999			glUseProgram(m_ppo);
3000		glBindVertexArray(m_vao);
3001		glDrawArraysInstanced(GL_POINTS, 0, 2, 2);
3002
3003		/* */
3004		{
3005			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
3006			GLubyte* ptr = static_cast<GLubyte*>(
3007				glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)data.size(), GL_MAP_READ_BIT));
3008			// attrib0
3009			Vec2 i0_v0_a0 = *reinterpret_cast<Vec2*>(&ptr[0]);
3010			Vec2 i0_v1_a0 = *reinterpret_cast<Vec2*>(&ptr[8]);
3011			Vec2 i1_v0_a0 = *reinterpret_cast<Vec2*>(&ptr[16]);
3012			Vec2 i1_v1_a0 = *reinterpret_cast<Vec2*>(&ptr[24]);
3013			if (!IsEqual(i0_v0_a0, Vec2(1.0f, 2.0f)))
3014				return ERROR;
3015			if (!IsEqual(i0_v1_a0, Vec2(3.0f, 4.0f)))
3016				return ERROR;
3017			if (!IsEqual(i1_v0_a0, Vec2(1.0f, 2.0f)))
3018				return ERROR;
3019			if (!IsEqual(i1_v1_a0, Vec2(3.0f, 4.0f)))
3020				return ERROR;
3021			// attrib1
3022			IVec2 i0_v0_a1 = *reinterpret_cast<IVec2*>(&ptr[32]);
3023			IVec2 i0_v1_a1 = *reinterpret_cast<IVec2*>(&ptr[40]);
3024			IVec2 i1_v0_a1 = *reinterpret_cast<IVec2*>(&ptr[48]);
3025			IVec2 i1_v1_a1 = *reinterpret_cast<IVec2*>(&ptr[56]);
3026			if (!IsEqual(i0_v0_a1, IVec2(5, 6)))
3027				return ERROR;
3028			if (!IsEqual(i0_v1_a1, IVec2(7, 8)))
3029				return ERROR;
3030			if (!IsEqual(i1_v0_a1, IVec2(5, 6)))
3031				return ERROR;
3032			if (!IsEqual(i1_v1_a1, IVec2(7, 8)))
3033				return ERROR;
3034			// attrib2
3035			UVec2 i0_v0_a2 = *reinterpret_cast<UVec2*>(&ptr[64]);
3036			UVec2 i0_v1_a2 = *reinterpret_cast<UVec2*>(&ptr[72]);
3037			UVec2 i1_v0_a2 = *reinterpret_cast<UVec2*>(&ptr[80]);
3038			UVec2 i1_v1_a2 = *reinterpret_cast<UVec2*>(&ptr[88]);
3039			if (!IsEqual(i0_v0_a2, UVec2(9, 10)))
3040				return ERROR;
3041			if (!IsEqual(i0_v1_a2, UVec2(11, 12)))
3042				return ERROR;
3043			if (!IsEqual(i1_v0_a2, UVec2(9, 10)))
3044				return ERROR;
3045			if (!IsEqual(i1_v1_a2, UVec2(11, 12)))
3046				return ERROR;
3047			// attrib3
3048			float i0_v0_a3 = *reinterpret_cast<float*>(&ptr[96]);
3049			float i0_v1_a3 = *reinterpret_cast<float*>(&ptr[100]);
3050			float i1_v0_a3 = *reinterpret_cast<float*>(&ptr[104]);
3051			float i1_v1_a3 = *reinterpret_cast<float*>(&ptr[108]);
3052			if (i0_v0_a3 != 13.0f)
3053				return ERROR;
3054			if (i0_v1_a3 != 14.0f)
3055				return ERROR;
3056			if (i1_v0_a3 != 13.0f)
3057				return ERROR;
3058			if (i1_v1_a3 != 14.0f)
3059				return ERROR;
3060			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3061		}
3062		return NO_ERROR;
3063	}
3064
3065public:
3066	AdvancedLargeStrideAndOffsetsNewAndLegacyAPI() : pipeline(true)
3067	{
3068	}
3069};
3070//=============================================================================
3071// 4.1 NegativeBindVertexBuffer
3072//-----------------------------------------------------------------------------
3073class NegativeBindVertexBuffer : public VertexAttribBindingBase
3074{
3075
3076	GLuint m_vao, m_vbo;
3077
3078	virtual long Setup()
3079	{
3080		glGenVertexArrays(1, &m_vao);
3081		glGenBuffers(1, &m_vbo);
3082		return NO_ERROR;
3083	}
3084
3085	virtual long Cleanup()
3086	{
3087		glDeleteVertexArrays(1, &m_vao);
3088		glDeleteBuffers(1, &m_vbo);
3089		return NO_ERROR;
3090	}
3091
3092	virtual long Run()
3093	{
3094		/*
3095		 Errors
3096		 An INVALID_OPERATION error is generated if buffer is not zero or a name
3097		 returned from a previous call to GenBuffers, or if such a name has since been
3098		 deleted with DeleteBuffers.
3099		 An INVALID_VALUE error is generated if bindingindex is greater than or
3100		 equal to the value of MAX_VERTEX_ATTRIB_BINDINGS.
3101		 OpenGL 4.4 (Core Profile) - July 21, 2013
3102		 10.3. VERTEX ARRAYS 315
3103		 An INVALID_VALUE error is generated if stride or offset is negative, or if
3104		 stride is greater than the value of MAX_VERTEX_ATTRIB_STRIDE.
3105		 An INVALID_OPERATION error is generated if no vertex array object is
3106		 bound.
3107		 */
3108		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
3109		glBufferData(GL_ARRAY_BUFFER, 1000, NULL, GL_STATIC_DRAW);
3110		glBindBuffer(GL_ARRAY_BUFFER, 0);
3111
3112		glBindVertexArray(m_vao);
3113
3114		glBindVertexBuffer(0, 1234, 0, 12);
3115		if (glGetError() != GL_INVALID_OPERATION)
3116		{
3117			m_context.getTestContext().getLog()
3118				<< tcu::TestLog::Message << "INVALID_OPERATION should be generated (buffer name not genned)."
3119				<< tcu::TestLog::EndMessage;
3120			return ERROR;
3121		}
3122
3123		GLint p;
3124		glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &p);
3125		glBindVertexBuffer(p + 1, m_vbo, 0, 12);
3126		if (glGetError() != GL_INVALID_VALUE)
3127		{
3128			m_context.getTestContext().getLog()
3129				<< tcu::TestLog::Message
3130				<< "INVALID_VALUE should be generated (bindingIndex greater than GL_MAX_VERTEX_ATTRIB_BINDINGS)."
3131				<< tcu::TestLog::EndMessage;
3132			return ERROR;
3133		}
3134
3135		glBindVertexBuffer(0, m_vbo, -10, 12);
3136		if (glGetError() != GL_INVALID_VALUE)
3137		{
3138			m_context.getTestContext().getLog()
3139				<< tcu::TestLog::Message << "INVALID_VALUE should be generated (negative offset)."
3140				<< tcu::TestLog::EndMessage;
3141			return ERROR;
3142		}
3143		glBindVertexBuffer(0, m_vbo, 0, -12);
3144		if (glGetError() != GL_INVALID_VALUE)
3145		{
3146			m_context.getTestContext().getLog()
3147				<< tcu::TestLog::Message << "INVALID_VALUE should be generated (negative stride)."
3148				<< tcu::TestLog::EndMessage;
3149			return ERROR;
3150		}
3151
3152		glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &p);
3153		glBindVertexBuffer(0, m_vbo, 0, p + 4);
3154		if (glGetError() != GL_INVALID_VALUE)
3155		{
3156			m_context.getTestContext().getLog()
3157				<< tcu::TestLog::Message
3158				<< "INVALID_VALUE should be generated (stride greater than GL_MAX_VERTEX_ATTRIB_STRIDE)."
3159				<< tcu::TestLog::EndMessage;
3160			return ERROR;
3161		}
3162
3163		glBindVertexArray(0);
3164		glBindVertexBuffer(0, m_vbo, 0, 12);
3165		if (glGetError() != GL_INVALID_OPERATION)
3166		{
3167			m_context.getTestContext().getLog()
3168				<< tcu::TestLog::Message << "INVALID_OPERATION should be generated (default VAO)."
3169				<< tcu::TestLog::EndMessage;
3170			return ERROR;
3171		}
3172
3173		return NO_ERROR;
3174	}
3175};
3176//=============================================================================
3177// 4.2 NegativeVertexAttribFormat
3178//-----------------------------------------------------------------------------
3179class NegativeVertexAttribFormat : public VertexAttribBindingBase
3180{
3181
3182	GLuint m_vao, m_vbo;
3183
3184	virtual long Setup()
3185	{
3186		glGenVertexArrays(1, &m_vao);
3187		glGenBuffers(1, &m_vbo);
3188		return NO_ERROR;
3189	}
3190
3191	virtual long Cleanup()
3192	{
3193		glDeleteVertexArrays(1, &m_vao);
3194		glDeleteBuffers(1, &m_vbo);
3195		return NO_ERROR;
3196	}
3197
3198	virtual long Run()
3199	{
3200		/*
3201		 Errors
3202		 An INVALID_VALUE error is generated if attribindex is greater than or
3203		 equal to the value of MAX_VERTEX_ATTRIBS.
3204		 An INVALID_VALUE error is generated if size is not one of the values
3205		 shown in table 10.2 for the corresponding command.
3206		 An INVALID_ENUM error is generated if type is not one of the parameter
3207		 token names from table 8.2 corresponding to one of the allowed GL data types
3208		 for that command as shown in table 10.2.
3209		 An INVALID_OPERATION error is generated under any of the following
3210		 conditions:
3211		 - if no vertex array object is currently bound (see section 10.4);
3212		 - type is INT_2_10_10_10_REV or UNSIGNED_INT_2_10_10_10_-
3213		 REV, and size is not 4;
3214		 An INVALID_VALUE error is generated if relativeoffset is larger than the
3215		 value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.
3216		 */
3217		glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
3218		glBufferData(GL_ARRAY_BUFFER, 1000, NULL, GL_STATIC_DRAW);
3219		glBindBuffer(GL_ARRAY_BUFFER, 0);
3220
3221		glBindVertexArray(m_vao);
3222
3223		GLint p;
3224		glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &p);
3225		glVertexAttribFormat(p + 1, 4, GL_FLOAT, GL_FALSE, 0);
3226		if (glGetError() != GL_INVALID_VALUE)
3227		{
3228			m_context.getTestContext().getLog()
3229				<< tcu::TestLog::Message
3230				<< "INVALID_VALUE should be generated (attribindex greater than GL_MAX_VERTEX_ATTRIBS)."
3231				<< tcu::TestLog::EndMessage;
3232			return ERROR;
3233		}
3234		glVertexAttribIFormat(p + 2, 4, GL_INT, 0);
3235		if (glGetError() != GL_INVALID_VALUE)
3236		{
3237			m_context.getTestContext().getLog()
3238				<< tcu::TestLog::Message
3239				<< "INVALID_VALUE should be generated (attribindex greater than GL_MAX_VERTEX_ATTRIBS)."
3240				<< tcu::TestLog::EndMessage;
3241			return ERROR;
3242		}
3243		glVertexAttribFormat(0, 0, GL_FLOAT, GL_FALSE, 0);
3244		if (glGetError() != GL_INVALID_VALUE)
3245		{
3246			m_context.getTestContext().getLog()
3247				<< tcu::TestLog::Message << "INVALID_VALUE should be generated (invalid number of components)."
3248				<< tcu::TestLog::EndMessage;
3249			return ERROR;
3250		}
3251		glVertexAttribFormat(0, 5, GL_FLOAT, GL_FALSE, 0);
3252		if (glGetError() != GL_INVALID_VALUE)
3253		{
3254			m_context.getTestContext().getLog()
3255				<< tcu::TestLog::Message << "INVALID_VALUE should be generated (invalid number of components)."
3256				<< tcu::TestLog::EndMessage;
3257			return ERROR;
3258		}
3259		glVertexAttribIFormat(0, 5, GL_INT, 0);
3260		if (glGetError() != GL_INVALID_VALUE)
3261		{
3262			m_context.getTestContext().getLog()
3263				<< tcu::TestLog::Message << "INVALID_VALUE should be generated (invalid number of components)."
3264				<< tcu::TestLog::EndMessage;
3265			return ERROR;
3266		}
3267		glVertexAttribFormat(0, 4, GL_R32F, GL_FALSE, 0);
3268		if (glGetError() != GL_INVALID_ENUM)
3269		{
3270			m_context.getTestContext().getLog()
3271				<< tcu::TestLog::Message << "INVALID_ENUM should be generated (invalid type)."
3272				<< tcu::TestLog::EndMessage;
3273			return ERROR;
3274		}
3275		glVertexAttribIFormat(0, 4, GL_FLOAT, 0);
3276		if (glGetError() != GL_INVALID_ENUM)
3277		{
3278			m_context.getTestContext().getLog()
3279				<< tcu::TestLog::Message << "INVALID_ENUM should be generated (invalid type)."
3280				<< tcu::TestLog::EndMessage;
3281			return ERROR;
3282		}
3283		glVertexAttribFormat(0, 3, GL_INT_2_10_10_10_REV, GL_FALSE, 0);
3284		if (glGetError() != GL_INVALID_OPERATION)
3285		{
3286			m_context.getTestContext().getLog()
3287				<< tcu::TestLog::Message
3288				<< "INVALID_OPERATION should be generated (invalid number of components for packed type)."
3289				<< tcu::TestLog::EndMessage;
3290			return ERROR;
3291		}
3292		glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &p);
3293		glVertexAttribFormat(0, 4, GL_FLOAT, GL_FALSE, p + 10);
3294		if (glGetError() != GL_INVALID_VALUE)
3295		{
3296			m_context.getTestContext().getLog()
3297				<< tcu::TestLog::Message << "INVALID_VALUE should be generated (relativeoffset greater than "
3298											"GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)."
3299				<< tcu::TestLog::EndMessage;
3300			return ERROR;
3301		}
3302		glVertexAttribIFormat(0, 4, GL_INT, p + 10);
3303		if (glGetError() != GL_INVALID_VALUE)
3304		{
3305			m_context.getTestContext().getLog()
3306				<< tcu::TestLog::Message << "INVALID_VALUE should be generated (relativeoffset greater than "
3307											"GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)."
3308				<< tcu::TestLog::EndMessage;
3309			return ERROR;
3310		}
3311		glBindVertexArray(0);
3312		glVertexAttribFormat(0, 4, GL_FLOAT, GL_FALSE, 0);
3313		if (glGetError() != GL_INVALID_OPERATION)
3314		{
3315			m_context.getTestContext().getLog()
3316				<< tcu::TestLog::Message << "INVALID_OPERATION should be generated (default VAO)."
3317				<< tcu::TestLog::EndMessage;
3318			return ERROR;
3319		}
3320		glVertexAttribIFormat(0, 4, GL_INT, 0);
3321		if (glGetError() != GL_INVALID_OPERATION)
3322		{
3323			m_context.getTestContext().getLog()
3324				<< tcu::TestLog::Message << "INVALID_OPERATION should be generated (default VAO)."
3325				<< tcu::TestLog::EndMessage;
3326			return ERROR;
3327		}
3328		return NO_ERROR;
3329	}
3330};
3331
3332//=============================================================================
3333// 4.3 NegativeVertexAttribBinding
3334//-----------------------------------------------------------------------------
3335class NegativeVertexAttribBinding : public VertexAttribBindingBase
3336{
3337	GLuint m_vao;
3338
3339	virtual long Setup()
3340	{
3341		glGenVertexArrays(1, &m_vao);
3342		return NO_ERROR;
3343	}
3344
3345	virtual long Cleanup()
3346	{
3347		glDeleteVertexArrays(1, &m_vao);
3348		return NO_ERROR;
3349	}
3350
3351	virtual long Run()
3352	{
3353		/*
3354		 Errors
3355		 An INVALID_VALUE error is generated if attribindex is greater than or
3356		 equal to the value of MAX_VERTEX_ATTRIBS.
3357		 An INVALID_VALUE error is generated if bindingindex is greater than or
3358		 equal to the value of MAX_VERTEX_ATTRIB_BINDINGS.
3359		 An INVALID_OPERATION error is generated if no vertex array object is
3360		 bound.
3361		 */
3362		glBindVertexArray(m_vao);
3363		GLint p;
3364		glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &p);
3365		glVertexAttribBinding(p + 1, 0);
3366		if (glGetError() != GL_INVALID_VALUE)
3367		{
3368			m_context.getTestContext().getLog()
3369				<< tcu::TestLog::Message
3370				<< "INVALID_VALUE should be generated (attribindex greater than GL_MAX_VERTEX_ATTRIBS)."
3371				<< tcu::TestLog::EndMessage;
3372			return ERROR;
3373		}
3374		glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &p);
3375		glVertexAttribBinding(0, p + 1);
3376		if (glGetError() != GL_INVALID_VALUE)
3377		{
3378			m_context.getTestContext().getLog()
3379				<< tcu::TestLog::Message
3380				<< "INVALID_VALUE should be generated (bindingIndex greater than GL_MAX_VERTEX_ATTRIB_BINDINGS)."
3381				<< tcu::TestLog::EndMessage;
3382			return ERROR;
3383		}
3384		glBindVertexArray(0);
3385		glVertexAttribBinding(0, 0);
3386		if (glGetError() != GL_INVALID_OPERATION)
3387		{
3388			m_context.getTestContext().getLog()
3389				<< tcu::TestLog::Message << "INVALID_OPERATION should be generated (default VAO)."
3390				<< tcu::TestLog::EndMessage;
3391			return ERROR;
3392		}
3393		return NO_ERROR;
3394	}
3395};
3396//=============================================================================
3397// 4.4 NegativeVertexAttribDivisor
3398//-----------------------------------------------------------------------------
3399class NegativeVertexAttribDivisor : public VertexAttribBindingBase
3400{
3401
3402	GLuint m_vao;
3403
3404	virtual long Setup()
3405	{
3406		glGenVertexArrays(1, &m_vao);
3407		return NO_ERROR;
3408	}
3409
3410	virtual long Cleanup()
3411	{
3412		glDeleteVertexArrays(1, &m_vao);
3413		return NO_ERROR;
3414	}
3415
3416	virtual long Run()
3417	{
3418		/*
3419		 Errors
3420		 An INVALID_VALUE error is generated if index is greater than or equal to
3421		 the value of MAX_VERTEX_ATTRIBS.
3422		 An INVALID_OPERATION error is generated if no vertex array object is
3423		 bound.
3424		 */
3425		glBindVertexArray(m_vao);
3426		GLint p;
3427		glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &p);
3428		glVertexBindingDivisor(p + 1, 1);
3429		if (glGetError() != GL_INVALID_VALUE)
3430		{
3431			m_context.getTestContext().getLog()
3432				<< tcu::TestLog::Message
3433				<< "INVALID_VALUE should be generated (bindingIndex greater than GL_MAX_VERTEX_ATTRIBS)."
3434				<< tcu::TestLog::EndMessage;
3435			return ERROR;
3436		}
3437		glBindVertexArray(0);
3438		glVertexBindingDivisor(0, 1);
3439		if (glGetError() != GL_INVALID_OPERATION)
3440		{
3441			m_context.getTestContext().getLog()
3442				<< tcu::TestLog::Message << "INVALID_OPERATION should be generated (default VAO)."
3443				<< tcu::TestLog::EndMessage;
3444			return ERROR;
3445		}
3446		return NO_ERROR;
3447	}
3448};
3449//=============================================================================
3450
3451} // namespace
3452VertexAttribBindingTests::VertexAttribBindingTests(glcts::Context& context)
3453	: TestCaseGroup(context, "vertex_attrib_binding", "")
3454{
3455}
3456
3457VertexAttribBindingTests::~VertexAttribBindingTests(void)
3458{
3459}
3460
3461void VertexAttribBindingTests::init()
3462{
3463	using namespace glcts;
3464	addChild(new TestSubcase(m_context, "basic-usage", TestSubcase::Create<BasicUsage>));
3465	addChild(new TestSubcase(m_context, "basic-input-case1", TestSubcase::Create<BasicInputCase1>));
3466	addChild(new TestSubcase(m_context, "basic-input-case2", TestSubcase::Create<BasicInputCase2>));
3467	addChild(new TestSubcase(m_context, "basic-input-case3", TestSubcase::Create<BasicInputCase3>));
3468	addChild(new TestSubcase(m_context, "basic-input-case4", TestSubcase::Create<BasicInputCase4>));
3469	addChild(new TestSubcase(m_context, "basic-input-case5", TestSubcase::Create<BasicInputCase5>));
3470	addChild(new TestSubcase(m_context, "basic-input-case6", TestSubcase::Create<BasicInputCase6>));
3471	addChild(new TestSubcase(m_context, "basic-input-case8", TestSubcase::Create<BasicInputCase8>));
3472	addChild(new TestSubcase(m_context, "basic-input-case9", TestSubcase::Create<BasicInputCase9>));
3473	addChild(new TestSubcase(m_context, "basic-input-case11", TestSubcase::Create<BasicInputCase11>));
3474	addChild(new TestSubcase(m_context, "basic-input-case12", TestSubcase::Create<BasicInputCase12>));
3475	addChild(new TestSubcase(m_context, "basic-inputI-case1", TestSubcase::Create<BasicInputICase1>));
3476	addChild(new TestSubcase(m_context, "basic-inputI-case2", TestSubcase::Create<BasicInputICase2>));
3477	addChild(new TestSubcase(m_context, "basic-inputI-case3", TestSubcase::Create<BasicInputICase3>));
3478	addChild(new TestSubcase(m_context, "basic-state1", TestSubcase::Create<BasicState1>));
3479	addChild(new TestSubcase(m_context, "basic-state2", TestSubcase::Create<BasicState2>));
3480	addChild(new TestSubcase(m_context, "advanced-bindingUpdate", TestSubcase::Create<AdvancedBindingUpdate>));
3481	addChild(new TestSubcase(m_context, "advanced-iterations", TestSubcase::Create<AdvancedIterations>));
3482	addChild(new TestSubcase(m_context, "advanced-largeStrideAndOffsetsNewAndLegacyAPI",
3483							 TestSubcase::Create<AdvancedLargeStrideAndOffsetsNewAndLegacyAPI>));
3484	addChild(new TestSubcase(m_context, "negative-bindVertexBuffer", TestSubcase::Create<NegativeBindVertexBuffer>));
3485	addChild(
3486		new TestSubcase(m_context, "negative-vertexAttribFormat", TestSubcase::Create<NegativeVertexAttribFormat>));
3487	addChild(
3488		new TestSubcase(m_context, "negative-vertexAttribBinding", TestSubcase::Create<NegativeVertexAttribBinding>));
3489	addChild(
3490		new TestSubcase(m_context, "negative-vertexAttribDivisor", TestSubcase::Create<NegativeVertexAttribDivisor>));
3491}
3492}
3493