• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /**
25  */ /*!
26  * \file  esextcDrawElementsBaseVertexTests.cpp
27  * \brief Implements conformance tests for "draw elements base vertex" functionality
28  *        for both ES and GL.
29  */ /*-------------------------------------------------------------------*/
30 
31 #include "esextcDrawElementsBaseVertexTests.hpp"
32 #include "gluContextInfo.hpp"
33 #include "gluDefs.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 #include "tcuRenderTarget.hpp"
37 #include "tcuTestLog.hpp"
38 
39 #include <string>
40 #include <vector>
41 
42 namespace glcts
43 {
44 /** Constructor.
45  *
46  *  @param context     Rendering context
47  *  @param name        Test name
48  *  @param description Test description
49  */
DrawElementsBaseVertexTestBase(glcts::Context & context,const ExtParameters & extParams,const char * name,const char * description)50 DrawElementsBaseVertexTestBase::DrawElementsBaseVertexTestBase(glcts::Context& context, const ExtParameters& extParams,
51 															   const char* name, const char* description)
52 	: TestCaseBase(context, extParams, name, description)
53 	, m_is_draw_elements_base_vertex_supported(false)
54 	, m_is_ext_multi_draw_arrays_supported(false)
55 	, m_is_geometry_shader_supported(false)
56 	, m_is_tessellation_shader_supported(false)
57 	, m_is_vertex_attrib_binding_supported(false)
58 	, m_bo_id(0)
59 	, m_bo_id_2(0)
60 	, m_fbo_id(0)
61 	, m_fs_id(0)
62 	, m_gs_id(0)
63 	, m_po_id(0)
64 	, m_po_color_attribute_location(-1)
65 	, m_po_uses_gs_stage(false)
66 	, m_po_uses_tc_te_stages(false)
67 	, m_po_uses_vertex_attrib_binding(false)
68 	, m_po_vertex_attribute_location(-1)
69 	, m_tc_id(0)
70 	, m_te_id(0)
71 	, m_to_base_id(0)
72 	, m_to_ref_id(0)
73 	, m_vao_id(0)
74 	, m_vs_id(0)
75 	, m_bo_negative_data_index_size(-1)
76 	, m_bo_negative_data_vertex_size(-1)
77 	, m_draw_call_color_offset(DE_NULL)
78 	, m_draw_call_index_offset(DE_NULL)
79 	, m_draw_call_index2_offset(DE_NULL)
80 	, m_draw_call_index3_offset(DE_NULL)
81 	, m_draw_call_index4_offset(DE_NULL)
82 	, m_draw_call_index5_offset(DE_NULL)
83 	, m_draw_call_vertex_offset(DE_NULL)
84 	, m_draw_call_vertex2_offset(DE_NULL)
85 	, m_to_height(128)
86 	, m_to_width(128)
87 	, m_to_base_data(DE_NULL)
88 	, m_to_ref_data(DE_NULL)
89 {
90 	static const glw::GLuint functional_index_data[] = /* used for a number of Functional Tests */
91 		{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 };
92 	static const glw::GLuint functional2_index_data[] = /* used for Functional Test IV */
93 		{ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
94 		  30, 31, 32, 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16 };
95 	static const glw::GLubyte functional3_index_data[] = /* used for Functional Test IX */
96 		{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
97 	static const glw::GLushort functional4_index_data[] = /* used for Functional Test IX */
98 		{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
99 	static const glw::GLuint functional5_index_data[] = /* used for Functional Test IX */
100 		{ 2147483647 + 3u,								/* 2^31 + 2 */
101 		  2147483647 + 4u,
102 		  2147483647 + 5u,
103 		  2147483647 + 6u,
104 		  2147483647 + 7u,
105 		  2147483647 + 8u,
106 		  2147483647 + 9u,
107 		  2147483647 + 10u,
108 		  2147483647 + 11u,
109 		  2147483647 + 12u,
110 		  2147483647 + 13u,
111 		  2147483647 + 14u,
112 		  257, // regular draw call indices for ubyte ref image
113 		  258,
114 		  259,
115 		  260,
116 		  261,
117 		  262,
118 		  263,
119 		  264,
120 		  265,
121 		  266,
122 		  267,
123 		  268,
124 		  65537, // regular draw call indices for ushort ref image
125 		  65538,
126 		  65539,
127 		  65540,
128 		  65541,
129 		  65542,
130 		  65543,
131 		  65544,
132 		  65545,
133 		  65546,
134 		  65547,
135 		  65548,
136 		  0, // regular draw call indices for uint ref image
137 		  1,
138 		  2,
139 		  3,
140 		  4,
141 		  5,
142 		  6,
143 		  7,
144 		  8,
145 		  9,
146 		  10,
147 		  11 };
148 	static const glw::GLfloat functional_color_data[] = /* used for "vertex attrib binding" Functional Test */
149 		{
150 		  0.1f, 0.2f, 0.2f, 0.3f, 0.3f, 0.4f, 0.4f, 0.5f, 0.5f, 0.6f, 0.6f, 0.7f, 0.7f, 0.8f, 0.8f, 0.9f, 0.9f,
151 		  1.0f, 1.0f, 0.9f, 0.9f, 0.8f, 0.8f, 0.7f, 0.7f, 0.6f, 0.6f, 0.5f, 0.5f, 0.4f, 0.4f, 0.3f, 0.3f, 0.2f,
152 		  0.2f, 0.1f, 0.1f, 0.0f, 0.0f, 0.1f, 0.1f, 0.2f, 0.2f, 0.4f, 0.3f, 0.9f, 0.4f, 0.8f, 0.5f, 1.0f, 0.6f,
153 		  0.8f, 0.7f, 0.1f, 0.8f, 0.3f, 0.9f, 0.5f, 1.0f, 0.0f, 0.2f, 0.0f, 0.0f, 0.3f, 0.1f, 1.0f,
154 		};
155 	static const glw::GLfloat functional_vertex_data[] = /* used by a number of Functional Tests */
156 		{
157 		  0.0f,  0.0f,  -0.1f, -0.1f, 0.2f,  0.8f,  -0.3f, -0.3f, 0.4f,  -0.4f, 0.5f,  0.5f, -0.6f, 0.6f,
158 		  0.7f,  -0.7f, -0.8f, 0.8f,  0.9f,  -0.9f, -1.0f, -1.0f, 1.0f,  -1.0f, 0.0f,  1.0f, -0.9f, 0.1f,
159 		  0.8f,  -0.2f, -0.7f, 0.3f,  -0.6f, -0.4f, 0.5f,  -0.5f, -0.4f, -0.6f, 0.3f,  0.7f, -0.2f, -0.8f,
160 		  -0.1f, -0.9f, 0.0f,  0.0f,  0.5f,  0.5f,  -0.6f, 0.6f,  0.7f,  -0.7f, -0.8f, 0.8f, 0.9f,  -0.9f,
161 		  -1.0f, -1.0f, 1.0f,  -1.0f, 0.0f,  1.0f,  -0.9f, 0.1f,  0.8f,  -0.2f,
162 		};
163 	static const glw::GLfloat functional2_vertex_data[] = /* used by a number of Functional Tests */
164 		{
165 		  -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.3f, 0.3f, 0.4f, 0.4f, 0.5f, 0.5f, 0.6f, 0.6f, 0.7f, 0.7f,
166 		  0.8f,  0.8f,  0.9f, 0.9f,  0.1f, 0.2f, 0.2f, 0.1f, 0.1f, 0.2f, 0.9f, 0.1f, 0.8f, 0.2f, 0.7f, 0.3f,
167 		  0.6f,  0.4f,  0.5f, 0.5f,  0.4f, 0.6f, 0.3f, 0.7f, 0.2f, 0.8f, 0.1f, 0.9f, 0.0f, 0.0f,
168 
169 		};
170 	static const glw::GLuint negative_index_data[]  = { 0, 1, 2 };
171 	static const float		 negative_vertex_data[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f };
172 
173 	m_bo_functional_data_color		  = functional_color_data;
174 	m_bo_functional_data_color_size   = sizeof(functional_color_data);
175 	m_bo_functional_data_index		  = functional_index_data;
176 	m_bo_functional_data_index_size   = sizeof(functional_index_data);
177 	m_bo_functional_data_vertex		  = functional_vertex_data;
178 	m_bo_functional_data_vertex_size  = sizeof(functional_vertex_data);
179 	m_bo_functional2_data_index		  = functional2_index_data;
180 	m_bo_functional2_data_index_size  = sizeof(functional2_index_data);
181 	m_bo_functional3_data_index		  = functional3_index_data;
182 	m_bo_functional3_data_index_size  = sizeof(functional3_index_data);
183 	m_bo_functional4_data_index		  = functional4_index_data;
184 	m_bo_functional4_data_index_size  = sizeof(functional4_index_data);
185 	m_bo_functional5_data_index		  = functional5_index_data;
186 	m_bo_functional5_data_index_size  = sizeof(functional5_index_data);
187 	m_bo_functional2_data_vertex	  = functional2_vertex_data;
188 	m_bo_functional2_data_vertex_size = sizeof(functional2_vertex_data);
189 	m_bo_negative_data_index		  = negative_index_data;
190 	m_bo_negative_data_index_size	 = sizeof(negative_index_data);
191 	m_bo_negative_data_vertex		  = negative_vertex_data;
192 	m_bo_negative_data_vertex_size	= sizeof(negative_vertex_data);
193 }
194 
195 /** Creates & initializes a number of shader objects, assigns user-provided
196  *  code to relevant shader objects and compiles them. If all shaders are
197  *  compiled successfully, they are later attached to a program object, id
198  *  of which is stored in m_po_id. Finally, the program object is linked.
199  *
200  *  If the compilation process or the linking process fails for any reason,
201  *  the method throws a TestError exception.
202  *
203  *  Fragment shader object ID is stored under m_fs_id.
204  *  Geometry shader object ID is stored under m_gs_id.
205  *  Tessellation control shader object ID is stored under m_tc_id.
206  *  Tessellation evaluation shader object ID is stored under m_te_id.
207  *  Vertex shader object ID is stored under m_vs_id.
208  *
209  *  @param fs_code Code to use for the fragment shader. Must not be NULL.
210  *  @param gs_code Code to use for the geometry shader. Can be NULL.
211  *  @param tc_code Code to use for the tessellation control shader. Can be NULL.
212  *  @param te_code Code to use for the tessellation evaluation shader. Can be NULL.
213  *  @param vs_code Code to use for the vertex shader. Must not be NULL.
214  *
215  */
buildProgram(const char * fs_code,const char * vs_code,const char * tc_code,const char * te_code,const char * gs_code)216 void DrawElementsBaseVertexTestBase::buildProgram(const char* fs_code, const char* vs_code, const char* tc_code,
217 												  const char* te_code, const char* gs_code)
218 {
219 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
220 
221 	/* Create program & shader objects */
222 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
223 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
224 
225 	if (tc_code != DE_NULL)
226 	{
227 		m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
228 	}
229 
230 	if (te_code != DE_NULL)
231 	{
232 		m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
233 	}
234 
235 	if (gs_code != DE_NULL)
236 	{
237 		m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
238 	}
239 
240 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
241 
242 	m_po_id = gl.createProgram();
243 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
244 
245 	/* Assign source code to the shader objects */
246 	gl.shaderSource(m_fs_id, 1,			/* count */
247 					&fs_code, DE_NULL); /* length */
248 	gl.shaderSource(m_vs_id, 1,			/* count */
249 					&vs_code, DE_NULL); /* length */
250 
251 	if (m_tc_id != 0)
252 	{
253 		gl.shaderSource(m_tc_id, 1,			/* count */
254 						&tc_code, DE_NULL); /* length */
255 	}
256 
257 	if (m_te_id != 0)
258 	{
259 		gl.shaderSource(m_te_id, 1,			/* count */
260 						&te_code, DE_NULL); /* length */
261 	}
262 
263 	if (m_gs_id != 0)
264 	{
265 		gl.shaderSource(m_gs_id, 1,			/* count */
266 						&gs_code, DE_NULL); /* length */
267 	}
268 
269 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
270 
271 	/* Try to compile the shaders */
272 	const glw::GLuint  so_ids[] = { m_fs_id, m_vs_id, m_tc_id, m_te_id, m_gs_id };
273 	const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
274 
275 	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
276 	{
277 		glw::GLint  compile_status = GL_FALSE;
278 		glw::GLuint so_id		   = so_ids[n_so_id];
279 
280 		if (so_id != 0)
281 		{
282 			gl.compileShader(so_id);
283 			GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
284 
285 			gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
286 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
287 
288 			if (compile_status == GL_FALSE)
289 			{
290 				TCU_FAIL("Shader compilation failed");
291 			} /* if (compile_status == GL_FALSE) */
292 		}	 /* if (so_id != 0) */
293 	}		  /* for (all shader objects) */
294 
295 	/* Attach the shaders to the program object */
296 	gl.attachShader(m_po_id, m_fs_id);
297 	gl.attachShader(m_po_id, m_vs_id);
298 
299 	if (m_tc_id != 0)
300 	{
301 		gl.attachShader(m_po_id, m_tc_id);
302 	}
303 
304 	if (m_te_id != 0)
305 	{
306 		gl.attachShader(m_po_id, m_te_id);
307 	}
308 
309 	if (m_gs_id != 0)
310 	{
311 		gl.attachShader(m_po_id, m_gs_id);
312 	}
313 
314 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
315 
316 	/* Set up TFO */
317 	const glw::GLchar* tf_varyings[] = { "gl_Position" };
318 
319 	gl.transformFeedbackVaryings(m_po_id, 1, /* count */
320 								 tf_varyings, GL_SEPARATE_ATTRIBS);
321 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
322 
323 	/* Try to link the program object */
324 	glw::GLint link_status = GL_FALSE;
325 
326 	gl.linkProgram(m_po_id);
327 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
328 
329 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
330 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
331 
332 	if (link_status == GL_FALSE)
333 	{
334 		TCU_FAIL("Program linking failed.");
335 	}
336 
337 	/* Retrieve attribute locations */
338 	m_po_color_attribute_location =
339 		gl.getAttribLocation(m_po_id, "in_color"); /* != -1 only for "vertex attrib binding" tests */
340 	m_po_vertex_attribute_location = gl.getAttribLocation(m_po_id, "vertex");
341 
342 	DE_ASSERT(m_po_vertex_attribute_location != -1);
343 }
344 
345 /** Verifies contents of the base & reference textures. This method can work
346  *  in two modes:
347  *
348  *  a) If @param should_be_equal is true, the method will throw a TestError exception
349  *     if the two textures are not a match.
350  *  b) If @param should_be_equal is false, the method will throw a TestError exception
351  *     if the two extures are a match.
352  *
353  *  Furthermore, in order to verify that the basevertex & regular draw calls actually
354  *  generated at least one sample, the method verifies that at least one texel in both
355  *  of the textures has been modified. If all texels in any of the textures are found
356  *  to be (0, 0, 0) (alpha channel is ignored), TestError exception will be generated.
357  *
358  *  @param should_be_equal Please see description for more details.
359  **/
compareBaseAndReferenceTextures(bool should_be_equal)360 void DrawElementsBaseVertexTestBase::compareBaseAndReferenceTextures(bool should_be_equal)
361 {
362 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
363 
364 	/* Read contents of both base and reference textures */
365 	gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_base_id, 0); /* level */
366 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
367 
368 	gl.readPixels(0, /* x */
369 				  0, /* y */
370 				  m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_base_data);
371 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
372 
373 	gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_ref_id, 0); /* level */
374 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
375 	gl.readPixels(0, /* x */
376 				  0, /* y */
377 				  m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_ref_data);
378 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
379 
380 	/* Both tests should be a match */
381 	const unsigned char* base_data_ptr				   = m_to_base_data;
382 	bool				 all_base_rgb_texels_zero	  = true;
383 	bool				 all_reference_rgb_texels_zero = true;
384 	const unsigned int   n_texels					   = m_to_width * m_to_height;
385 	const unsigned char* ref_data_ptr				   = m_to_ref_data;
386 	bool				 textures_identical			   = true;
387 
388 	for (unsigned int n_texel = 0; n_texel < n_texels; ++n_texel)
389 	{
390 		/* Verify something was rendered to one of the render-targets. Note we
391 		 * omit alpha channel, since the clear color is set to 0xFF by default */
392 		if (base_data_ptr[0] != 0 || base_data_ptr[1] != 0 || base_data_ptr[2] != 0)
393 		{
394 			all_base_rgb_texels_zero = false;
395 		}
396 
397 		if (ref_data_ptr[0] != 0 || ref_data_ptr[1] != 0 || ref_data_ptr[2] != 0)
398 		{
399 			all_reference_rgb_texels_zero = false;
400 		}
401 
402 		if (base_data_ptr[0] != ref_data_ptr[0] || base_data_ptr[1] != ref_data_ptr[1] ||
403 			base_data_ptr[2] != ref_data_ptr[2] || base_data_ptr[3] != ref_data_ptr[3])
404 		{
405 			if (should_be_equal)
406 			{
407 				const unsigned int y = n_texel / m_to_width;
408 				const unsigned int x = n_texel % m_to_width;
409 
410 				m_testCtx.getLog() << tcu::TestLog::Message << "Pixels at (" << x << ", " << y
411 								   << ") do not match. Found:"
412 								   << "(" << (unsigned int)base_data_ptr[0] << ", " << (unsigned int)base_data_ptr[1]
413 								   << ", " << (unsigned int)base_data_ptr[2] << ", " << (unsigned int)base_data_ptr[3]
414 								   << "), expected:"
415 								   << "(" << (unsigned int)ref_data_ptr[0] << ", " << (unsigned int)ref_data_ptr[1]
416 								   << ", " << (unsigned int)ref_data_ptr[2] << ", " << (unsigned int)ref_data_ptr[3]
417 								   << ")." << tcu::TestLog::EndMessage;
418 
419 				TCU_FAIL("Pixel mismatch");
420 			}
421 			else
422 			{
423 				/* Base and reference textures are *not* identical. */
424 				textures_identical = false;
425 			}
426 		}
427 
428 		base_data_ptr += 4; /* components */
429 		ref_data_ptr += 4;  /* components */
430 	}						/* for (all texels) */
431 
432 	if (all_base_rgb_texels_zero)
433 	{
434 		TCU_FAIL("Draw call used to render contents of the base texture did not change the texture");
435 	}
436 
437 	if (all_reference_rgb_texels_zero)
438 	{
439 		TCU_FAIL("Draw call used to render contents of the reference texture did not change the texture");
440 	}
441 
442 	if (!should_be_equal && textures_identical)
443 	{
444 		TCU_FAIL("Textures are a match, even though they should not be identical.");
445 	}
446 }
447 
448 /** Updates m_draw_call_color_offset, m_draw_call_index*_offset and m_draw_call_vertex*_offset
449  *  members with valid values, depending on the input arguments.
450  *
451  *  @param use_clientside_index_data  true if client-side index data buffer is going to be
452  *                                    used for the test-issued draw calls, false otherwise.
453  *  @param use_clientside_vertex_data true if client-side color & vertex data buffer is going
454  *                                    to be used for the test-issued draw calls, false
455  *                                    otherwise.
456  */
computeVBODataOffsets(bool use_clientside_index_data,bool use_clientside_vertex_data)457 void DrawElementsBaseVertexTestBase::computeVBODataOffsets(bool use_clientside_index_data,
458 														   bool use_clientside_vertex_data)
459 {
460 	if (use_clientside_index_data)
461 	{
462 		m_draw_call_index_offset  = m_bo_functional_data_index;
463 		m_draw_call_index2_offset = m_bo_functional2_data_index;
464 		m_draw_call_index3_offset = m_bo_functional3_data_index;
465 		m_draw_call_index4_offset = m_bo_functional4_data_index;
466 		m_draw_call_index5_offset = m_bo_functional5_data_index;
467 	}
468 	else
469 	{
470 		/* Note that these assignments correspond to how the buffer object storage is constructed.
471 		 * If you need to update these offsets, don't forget to update the glBufferSubData() calls
472 		 */
473 		m_draw_call_index_offset =
474 			(const glw::GLuint*)(deUintptr)(m_bo_functional_data_vertex_size + m_bo_functional2_data_vertex_size);
475 		m_draw_call_index2_offset = (const glw::GLuint*)(deUintptr)(
476 			m_bo_functional_data_vertex_size + m_bo_functional2_data_vertex_size + m_bo_functional_data_index_size);
477 		m_draw_call_index3_offset =
478 			(const glw::GLubyte*)(deUintptr)(m_bo_functional_data_vertex_size + m_bo_functional2_data_vertex_size +
479 											 m_bo_functional_data_index_size + m_bo_functional2_data_index_size);
480 		m_draw_call_index4_offset = (const glw::GLushort*)(deUintptr)(
481 			m_bo_functional_data_vertex_size + m_bo_functional2_data_vertex_size + m_bo_functional_data_index_size +
482 			m_bo_functional2_data_index_size + m_bo_functional3_data_index_size);
483 		m_draw_call_index5_offset = (const glw::GLuint*)(deUintptr)(
484 			m_bo_functional_data_vertex_size + m_bo_functional2_data_vertex_size + m_bo_functional_data_index_size +
485 			m_bo_functional2_data_index_size + m_bo_functional3_data_index_size + m_bo_functional4_data_index_size);
486 	}
487 
488 	if (use_clientside_vertex_data)
489 	{
490 		m_draw_call_color_offset   = m_bo_functional_data_color;
491 		m_draw_call_vertex_offset  = m_bo_functional_data_vertex;
492 		m_draw_call_vertex2_offset = m_bo_functional2_data_vertex;
493 	}
494 	else
495 	{
496 		/* Note: same observation as above holds. */
497 		m_draw_call_color_offset = (const glw::GLfloat*)(deUintptr)(
498 			m_bo_functional_data_vertex_size + m_bo_functional2_data_vertex_size + m_bo_functional_data_index_size +
499 			m_bo_functional2_data_index_size + m_bo_functional3_data_index_size + m_bo_functional4_data_index_size +
500 			m_bo_functional5_data_index_size);
501 		m_draw_call_vertex_offset  = DE_NULL;
502 		m_draw_call_vertex2_offset = (const glw::GLfloat*)(deUintptr)m_bo_functional_data_vertex_size;
503 	}
504 }
505 
deinit()506 void DrawElementsBaseVertexTestBase::deinit()
507 {
508 	/* TCU_FAIL will skip the per test object de-initialization, we need to
509 	 * take care of it here
510 	 */
511 	deinitPerTestObjects();
512 }
513 
514 /** Deinitializes all ES objects created by the test. */
deinitPerTestObjects()515 void DrawElementsBaseVertexTestBase::deinitPerTestObjects()
516 {
517 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
518 
519 	deinitProgramAndShaderObjects();
520 
521 	if (m_bo_id != 0)
522 	{
523 		gl.deleteBuffers(1, &m_bo_id);
524 
525 		m_bo_id = 0;
526 	}
527 
528 	if (m_bo_id_2 != 0)
529 	{
530 		gl.deleteBuffers(1, &m_bo_id_2);
531 
532 		m_bo_id_2 = 0;
533 	}
534 
535 	if (m_fbo_id != 0)
536 	{
537 		gl.deleteFramebuffers(1, &m_fbo_id);
538 
539 		m_fbo_id = 0;
540 	}
541 
542 	if (m_to_base_data != DE_NULL)
543 	{
544 		delete[] m_to_base_data;
545 
546 		m_to_base_data = DE_NULL;
547 	}
548 
549 	if (m_to_base_id != 0)
550 	{
551 		gl.deleteTextures(1, &m_to_base_id);
552 
553 		m_to_base_id = 0;
554 	}
555 
556 	if (m_to_ref_data != DE_NULL)
557 	{
558 		delete[] m_to_ref_data;
559 
560 		m_to_ref_data = DE_NULL;
561 	}
562 
563 	if (m_to_ref_id != 0)
564 	{
565 		gl.deleteTextures(1, &m_to_ref_id);
566 
567 		m_to_ref_id = 0;
568 	}
569 
570 	if (m_vao_id != 0)
571 	{
572 		gl.deleteVertexArrays(1, &m_vao_id);
573 
574 		m_vao_id = 0;
575 	}
576 
577 	if (m_vs_id != 0)
578 	{
579 		gl.deleteShader(m_vs_id);
580 
581 		m_vs_id = 0;
582 	}
583 
584 	/* Restore the default GL_PACK_ALIGNMENT setting */
585 	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
586 }
587 
588 /** Deinitializes all program & shader objects that may have been initialized
589  *  by the test.
590  */
deinitProgramAndShaderObjects()591 void DrawElementsBaseVertexTestBase::deinitProgramAndShaderObjects()
592 {
593 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
594 
595 	if (m_fs_id != 0)
596 	{
597 		gl.deleteShader(m_fs_id);
598 
599 		m_fs_id = 0;
600 	}
601 
602 	if (m_gs_id != 0)
603 	{
604 		gl.deleteShader(m_gs_id);
605 
606 		m_gs_id = 0;
607 	}
608 
609 	if (m_po_id != 0)
610 	{
611 		gl.deleteProgram(m_po_id);
612 
613 		m_po_id = 0;
614 	}
615 
616 	if (m_tc_id != 0)
617 	{
618 		gl.deleteShader(m_tc_id);
619 
620 		m_tc_id = 0;
621 	}
622 
623 	if (m_te_id != 0)
624 	{
625 		gl.deleteShader(m_te_id);
626 
627 		m_te_id = 0;
628 	}
629 }
630 
631 /** Executes all test cases stored in m_test_cases.
632  *
633  *  This method throws a TestError exception upon test failure.
634  **/
executeTestCases()635 void DrawElementsBaseVertexTestBase::executeTestCases()
636 {
637 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
638 
639 	/* Iterate over all test cases */
640 	for (_test_cases_const_iterator test_cases_iterator = m_test_cases.begin();
641 		 test_cases_iterator != m_test_cases.end(); ++test_cases_iterator)
642 	{
643 		const _test_case& test_case = *test_cases_iterator;
644 
645 		/* What is the size of a single index value? */
646 		unsigned int index_size = 0;
647 
648 		switch (test_case.index_type)
649 		{
650 		case GL_UNSIGNED_BYTE:
651 			index_size = 1;
652 			break;
653 		case GL_UNSIGNED_SHORT:
654 			index_size = 2;
655 			break;
656 		case GL_UNSIGNED_INT:
657 			index_size = 4;
658 			break;
659 
660 		default:
661 		{
662 			TCU_FAIL("Unrecognized index type");
663 		}
664 		} /* switch (test_case.index_type) */
665 
666 		/* Set up the work environment */
667 		setUpFunctionalTestObjects(test_case.use_clientside_vertex_data, test_case.use_clientside_index_data,
668 								   test_case.use_tessellation_shader_stage, test_case.use_geometry_shader_stage,
669 								   test_case.use_vertex_attrib_binding, test_case.use_overflow_test_vertices);
670 
671 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_base_id, 0); /* level */
672 		GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed");
673 
674 		gl.clear(GL_COLOR_BUFFER_BIT);
675 		GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
676 
677 		switch (test_case.function_type)
678 		{
679 		case FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX:
680 		{
681 			gl.drawElementsBaseVertex(test_case.primitive_mode, 3, /* count */
682 									  test_case.index_type, test_case.index_offset, test_case.basevertex);
683 
684 			break;
685 		}
686 
687 		case FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX:
688 		{
689 			gl.drawElementsInstancedBaseVertex(test_case.primitive_mode, 3,						/* count */
690 											   test_case.index_type, test_case.index_offset, 3, /* instancecount */
691 											   test_case.basevertex);
692 
693 			break;
694 		}
695 
696 		case FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX:
697 		{
698 			gl.drawRangeElementsBaseVertex(test_case.primitive_mode, test_case.range_start, test_case.range_end,
699 										   3, /* count */
700 										   test_case.index_type, test_case.index_offset, test_case.basevertex);
701 
702 			break;
703 		}
704 
705 		case FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX:
706 		{
707 			const glw::GLint basevertex_array[] = { test_case.basevertex, test_case.basevertex, test_case.basevertex };
708 
709 			gl.multiDrawElementsBaseVertex(
710 				test_case.primitive_mode, test_case.multi_draw_call_count_array, test_case.index_type,
711 				(const glw::GLvoid**)test_case.multi_draw_call_indices_array, 3, /* primcount */
712 				basevertex_array);
713 
714 			break;
715 		}
716 
717 		default:
718 		{
719 			TCU_FAIL("Unsupported function index");
720 		}
721 		} /* switch (n_function) */
722 
723 		if (gl.getError() != GL_NO_ERROR)
724 		{
725 			std::stringstream error_sstream;
726 
727 			error_sstream << getFunctionName(test_case.function_type) << " call failed";
728 			TCU_FAIL(error_sstream.str().c_str());
729 		}
730 
731 		/* Now, render the same triangle using glDrawElements() to the reference texture */
732 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_ref_id, 0); /* level */
733 		GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed");
734 
735 		gl.clear(GL_COLOR_BUFFER_BIT);
736 		GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
737 
738 		glw::GLenum regular_draw_call_index_type = test_case.index_type;
739 		if (test_case.regular_draw_call_index_type != 0)
740 		{
741 			/* Need to use a different index type for regular draw call */
742 			regular_draw_call_index_type = test_case.regular_draw_call_index_type;
743 
744 			switch (test_case.regular_draw_call_index_type)
745 			{
746 			case GL_UNSIGNED_BYTE:
747 				index_size = 1;
748 				break;
749 			case GL_UNSIGNED_SHORT:
750 				index_size = 2;
751 				break;
752 			case GL_UNSIGNED_INT:
753 				index_size = 4;
754 				break;
755 
756 			default:
757 			{
758 				TCU_FAIL("Unrecognized index type");
759 			}
760 			}
761 		}
762 
763 		glw::GLubyte* regular_draw_call_offset =
764 			(glw::GLubyte*)test_case.index_offset + index_size * test_case.regular_draw_call_offset;
765 		if (test_case.use_overflow_test_vertices)
766 		{
767 			/* Special case for overflow test */
768 			regular_draw_call_offset = (glw::GLubyte*)test_case.regular_draw_call_offset2;
769 		}
770 
771 		switch (test_case.function_type)
772 		{
773 		case FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX: /* pass-through */
774 		case FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX:
775 		{
776 			gl.drawElements(test_case.primitive_mode, 3,							 /* count */
777 							regular_draw_call_index_type, regular_draw_call_offset); /* as per test spec */
778 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements() call failed");
779 
780 			break;
781 		}
782 
783 		case FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX:
784 		{
785 			gl.drawElementsInstanced(test_case.primitive_mode, 3,								 /* count */
786 									 regular_draw_call_index_type, regular_draw_call_offset, 3); /* instancecount */
787 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsInstanced() call failed");
788 
789 			break;
790 		}
791 
792 		case FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX:
793 		{
794 			/* Normally we'd just use glMultiDrawElements() here but it's not a part
795 			 * of ES3.1 core spec and we're trying to avoid any dependencies in the test.
796 			 * No damage done under GL, either.
797 			 */
798 			for (unsigned int n_draw_call = 0; n_draw_call < 3; /* drawcount */
799 				 ++n_draw_call)
800 			{
801 				gl.drawElements(test_case.primitive_mode, test_case.multi_draw_call_count_array[n_draw_call],
802 								regular_draw_call_index_type,
803 								(const glw::GLvoid*)test_case.regular_multi_draw_call_offseted_array[n_draw_call]);
804 
805 				GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements() call failed.");
806 			}
807 
808 			break;
809 		}
810 
811 		default:
812 		{
813 			TCU_FAIL("Unrecognized function index");
814 		}
815 		} /* switch (n_function) */
816 
817 		/* Compare the two textures and make sure they are either a match or not,
818 		 * depending on whether basevertex values match the offsets used for regular
819 		 * draw calls.
820 		 */
821 		compareBaseAndReferenceTextures(test_case.should_base_texture_match_reference_texture);
822 
823 		/* ES Resources are allocated per test objects, we need to release them here */
824 		deinitPerTestObjects();
825 	} /* for (all test cases) */
826 }
827 
828 /* Returns name of the function represented by _function_type.
829  *
830  * @param function_type Function type to use for the query.
831  *
832  * @return As per description, or "[?]" (without the quotation marks)
833  *         if @param function_type was not recognized.
834  */
getFunctionName(_function_type function_type)835 std::string DrawElementsBaseVertexTestBase::getFunctionName(_function_type function_type)
836 {
837 	std::string result = "[?]";
838 
839 	switch (function_type)
840 	{
841 	case FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX:
842 	{
843 		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
844 		{
845 			result = "glDrawElementsBaseVertexEXT()";
846 		}
847 		else
848 		{
849 			result = "glDrawElementsBaseVertex()";
850 		}
851 
852 		break;
853 	}
854 
855 	case FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX:
856 	{
857 		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
858 		{
859 			result = "glDrawElementsInstancedBaseVertexEXT()";
860 		}
861 		else
862 		{
863 			result = "glDrawElementsInstancedBaseVertex()";
864 		}
865 
866 		break;
867 	}
868 
869 	case FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX:
870 	{
871 		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
872 		{
873 			result = "glDrawRangeElementsBaseVertexEXT()";
874 		}
875 		else
876 		{
877 			result = "glDrawRangeElementsBaseVertex()";
878 		}
879 
880 		break;
881 	}
882 
883 	case FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX:
884 	{
885 		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
886 		{
887 			result = "glMultiDrawElementsBaseVertexEXT()";
888 		}
889 		else
890 		{
891 			result = "glMultiDrawElementsBaseVertex()";
892 		}
893 
894 		break;
895 	}
896 
897 	default:
898 	{
899 		TCU_FAIL("Unknown function type");
900 	}
901 	} /* switch (function_type) */
902 
903 	return result;
904 }
905 
906 /** Initializes extension-specific function pointers and caches information about
907  *  extension availability.
908  *
909  *  Function pointers for the following extensions are retrieved & stored:
910  *
911  *  - GL_EXT_draw_elements_base_vertex (ES) or GL_ARB_draw_elements_base_vertex (GL)
912  *  - GL_EXT_multi_draw_arrays         (ES & GL)
913  *
914  *  Availability of the following extensions is checked & cached:
915  *
916  *  - GL_EXT_draw_elements_base_vertex (ES) or GL_ARB_draw_elements_base_vertex (GL)
917  *  - GL_EXT_geometry_shader           (ES) or GL_ARB_geometry_shader4          (GL)
918  *  - GL_EXT_multi_draw_arrays         (ES & GL)
919  *  - GL_EXT_tessellation_shader       (ES) or GL_ARB_tessellation_shader (GL)
920  */
init()921 void DrawElementsBaseVertexTestBase::init()
922 {
923 	TestCaseBase::init();
924 
925 	const glu::ContextInfo& context_info = m_context.getContextInfo();
926 
927 	if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
928 		 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
929 		  context_info.isExtensionSupported("GL_EXT_draw_elements_base_vertex"))) ||
930 		context_info.isExtensionSupported("GL_ARB_draw_elements_base_vertex"))
931 	{
932 #if defined(DE_DEBUG) && !defined(DE_COVERAGE_BUILD)
933 		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
934 #endif
935 
936 		m_is_draw_elements_base_vertex_supported = true;
937 
938 		DE_ASSERT(gl.drawElementsBaseVertex != NULL);
939 		DE_ASSERT(gl.drawElementsInstancedBaseVertex != NULL);
940 		DE_ASSERT(gl.drawRangeElementsBaseVertex != NULL);
941 
942 		/* NOTE: glMultiDrawElementsBaseVertex() is a part of the draw_elements_base_vertex extension in GL,
943 		 *       but requires a separate extension under ES.
944 		 */
945 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()) ||
946 			context_info.isExtensionSupported("GL_EXT_multi_draw_arrays"))
947 		{
948 			m_is_ext_multi_draw_arrays_supported = true;
949 
950 			DE_ASSERT(gl.multiDrawElementsBaseVertex != NULL);
951 		} /* if (GL_EXT_multi_draw_arrays is supported or GL context is being tested) */
952 
953 		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
954 		{
955 			/* This conformance test needs to be adjusted in order to run under < ES3.1 contexts */
956 			DE_ASSERT(glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 1)));
957 		}
958 		else
959 		{
960 			m_is_vertex_attrib_binding_supported = context_info.isExtensionSupported("GL_ARB_vertex_attrib_binding");
961 		}
962 	} /* if (GL_{ARB, EXT}_draw_elements_base_vertex is supported) */
963 
964 	if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
965 		 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
966 		  context_info.isExtensionSupported("GL_EXT_geometry_shader"))) ||
967 		context_info.isExtensionSupported("GL_ARB_geometry_shader4"))
968 	{
969 		m_is_geometry_shader_supported = true;
970 	}
971 
972 	if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
973 		 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
974 		  context_info.isExtensionSupported("GL_EXT_tessellation_shader"))) ||
975 		context_info.isExtensionSupported("GL_ARB_tessellation_shader"))
976 	{
977 		m_is_tessellation_shader_supported = true;
978 	}
979 
980 	if (!m_is_draw_elements_base_vertex_supported)
981 	{
982 		throw tcu::NotSupportedError("draw_elements_base_vertex functionality is not supported");
983 	}
984 }
985 
986 /** Sets up all ES objects required to run a single functional test case iteration.
987  *
988  *  @param use_clientside_vertex_data    true if the test case requires client-side buffers to
989  *                                       back the color/vertex vertex attribute arrays; false
990  *                                       to use buffer object storage.
991  *  @param use_clientside_index_data     true if the test case requires client-side buffers to
992  *                                       be used as index data source; false to use buffer object
993  *                                       storage.
994  *  @param use_tessellation_shader_stage true if the program object used for the test should include
995  *                                       tessellation control & evaluation shader stages; false to
996  *                                       not to include these shader stages in the pipeline.
997  *  @param use_geometry_shader_stage     true if the program object used for the test should include
998  *                                       geometry shader stage; false to not to include the shader
999  *                                       stage in the pipeline.
1000  *  @param use_vertex_attrib_binding     true if vertex attribute bindings should be used for
1001  *                                       vertex array object configuration. This also modifies the
1002  *                                       vertex shader, so that instead of calculating vertex color
1003  *                                       on a per-vertex basis, contents of the "color" input
1004  *                                       will be used as a data source for the color data.
1005  *                                       false to use a vertex attribute array configured with
1006  *                                       a casual glVertexAttribPointer() call.
1007  * @param use_overflow_test_vertices     true if using an especially large vertex array to test
1008  *                                       overflow behavior.
1009  *
1010  *  This method can throw an exception if any of the ES calls fail.
1011  **/
setUpFunctionalTestObjects(bool use_clientside_vertex_data,bool use_clientside_index_data,bool use_tessellation_shader_stage,bool use_geometry_shader_stage,bool use_vertex_attrib_binding,bool use_overflow_test_vertices)1012 void DrawElementsBaseVertexTestBase::setUpFunctionalTestObjects(
1013 	bool use_clientside_vertex_data, bool use_clientside_index_data, bool use_tessellation_shader_stage,
1014 	bool use_geometry_shader_stage, bool use_vertex_attrib_binding, bool use_overflow_test_vertices)
1015 {
1016 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1017 
1018 	/* Set up a texture object that we will use as a color attachment */
1019 	gl.genTextures(1, &m_to_base_id);
1020 	gl.genTextures(1, &m_to_ref_id);
1021 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed.");
1022 
1023 	const glw::GLuint  to_ids[] = { m_to_base_id, m_to_ref_id };
1024 	const unsigned int n_to_ids = sizeof(to_ids) / sizeof(to_ids[0]);
1025 
1026 	for (unsigned int n_to_id = 0; n_to_id < n_to_ids; ++n_to_id)
1027 	{
1028 		gl.bindTexture(GL_TEXTURE_2D, to_ids[n_to_id]);
1029 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
1030 
1031 		gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
1032 						GL_RGBA8, m_to_width, m_to_height);
1033 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
1034 	}
1035 
1036 	/* Also set up some buffers we will use for data comparison */
1037 	m_to_base_data = new unsigned char[m_to_width * m_to_height * 4 /* components */];
1038 	m_to_ref_data  = new unsigned char[m_to_width * m_to_height * 4 /* components */];
1039 
1040 	/* Finally, for glReadPixels() operations, we need to make sure that pack alignment is set to 1 */
1041 	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
1042 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
1043 
1044 	/* Proceed with framebuffer object initialization. Since we will be rendering to different
1045 	 * render-targets, there's not much point in attaching any of the textures at this point.
1046 	 */
1047 	gl.genFramebuffers(1, &m_fbo_id);
1048 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
1049 
1050 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
1051 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebufer() call failed");
1052 
1053 	gl.viewport(0, /* x */
1054 				0, /* y */
1055 				m_to_width, m_to_height);
1056 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed");
1057 
1058 	/* Set up buffer object we will use for the draw calls. Use the data
1059 	 * from the test specification.
1060 	 *
1061 	 * NOTE: If you need to change the data layout here, make sure you also update
1062 	 *       m_draw_call_color_offset, m_draw_call_index*_offset, and
1063 	 *       m_draw_call_vertex*_offset setter calls elsewhere.
1064 	 **/
1065 	if (m_bo_id == 0)
1066 	{
1067 		unsigned int current_offset = 0;
1068 
1069 		gl.genBuffers(1, &m_bo_id);
1070 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1071 
1072 		gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1073 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1074 
1075 		gl.bufferData(GL_ARRAY_BUFFER,
1076 					  m_bo_functional_data_index_size + m_bo_functional_data_vertex_size +
1077 						  m_bo_functional2_data_vertex_size + m_bo_functional2_data_index_size +
1078 						  m_bo_functional3_data_index_size + m_bo_functional4_data_index_size +
1079 						  m_bo_functional5_data_index_size + m_bo_functional_data_color_size,
1080 					  DE_NULL, /* data */
1081 					  GL_STATIC_DRAW);
1082 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1083 
1084 		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_vertex_size,
1085 						 m_bo_functional_data_vertex);
1086 		current_offset += m_bo_functional_data_vertex_size;
1087 
1088 		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional2_data_vertex_size,
1089 						 m_bo_functional2_data_vertex);
1090 		current_offset += m_bo_functional2_data_vertex_size;
1091 
1092 		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_index_size, m_bo_functional_data_index);
1093 		current_offset += m_bo_functional_data_index_size;
1094 
1095 		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional2_data_index_size,
1096 						 m_bo_functional2_data_index);
1097 		current_offset += m_bo_functional2_data_index_size;
1098 
1099 		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional3_data_index_size,
1100 						 m_bo_functional3_data_index);
1101 		current_offset += m_bo_functional3_data_index_size;
1102 
1103 		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional4_data_index_size,
1104 						 m_bo_functional4_data_index);
1105 		current_offset += m_bo_functional4_data_index_size;
1106 
1107 		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional5_data_index_size,
1108 						 m_bo_functional5_data_index);
1109 		current_offset += m_bo_functional5_data_index_size;
1110 
1111 		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_color_size, m_bo_functional_data_color);
1112 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
1113 	}
1114 
1115 	if (use_overflow_test_vertices && m_bo_id_2 == 0)
1116 	{
1117 		/* Create a special buffer that only has vertex data in a few slots */
1118 		gl.genBuffers(1, &m_bo_id_2);
1119 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
1120 
1121 		gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_2);
1122 		gl.bufferData(GL_ARRAY_BUFFER, 2 * 65550 * sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
1123 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
1124 
1125 		/*
1126 		 * Upload to offset 0:     regular draw call indices for making sure ubyte
1127 		 *                         and ushort indices don't wrap around too early
1128 		 * Upload to offset 256:   base draw call indices of type ubyte
1129 		 * Upload to offset 65536: base draw call indices of type ushort
1130 		 */
1131 		glw::GLfloat badVtx[] = { 0.9f,  0.9f,  -0.9f, 0.9f,  -0.9f, -0.9f, 0.9f,  -0.9f, 0.9f,  0.9f,  -0.9f, 0.9f,
1132 								  -0.9f, -0.9f, 0.9f,  -0.9f, 0.9f,  0.9f,  -0.9f, 0.9f,  -0.9f, -0.9f, 0.9f,  -0.9f };
1133 		gl.bufferSubData(GL_ARRAY_BUFFER, 0, sizeof(badVtx), badVtx);
1134 		gl.bufferSubData(GL_ARRAY_BUFFER, 2 * 256 * sizeof(glw::GLfloat), 2 * 12 * sizeof(glw::GLfloat),
1135 						 m_bo_functional_data_vertex);
1136 		gl.bufferSubData(GL_ARRAY_BUFFER, 2 * 65536 * sizeof(glw::GLfloat), 2 * 12 * sizeof(glw::GLfloat),
1137 						 m_bo_functional_data_vertex);
1138 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed");
1139 	}
1140 
1141 	/* Set up the test program object */
1142 	if (m_po_id == 0 || m_po_uses_gs_stage != use_geometry_shader_stage ||
1143 		m_po_uses_tc_te_stages != use_tessellation_shader_stage ||
1144 		m_po_uses_vertex_attrib_binding != use_vertex_attrib_binding)
1145 
1146 	{
1147 		static const char* functional_fs_code = "${VERSION}\n"
1148 												"\n"
1149 												"precision highp float;\n"
1150 												"\n"
1151 												"in  vec4 FS_COLOR_INPUT_NAME;\n"
1152 												"out vec4 result;\n"
1153 												"\n"
1154 												"void main()\n"
1155 												"{\n"
1156 												"    result = FS_COLOR_INPUT_NAME;\n"
1157 												"}\n";
1158 		static const char* functional_gs_code = "${VERSION}\n"
1159 												"${GEOMETRY_SHADER_REQUIRE}\n"
1160 												"\n"
1161 												"layout(triangles)                        in;\n"
1162 												"layout(triangle_strip, max_vertices = 3) out;\n"
1163 												"\n"
1164 												"in  vec4 GS_COLOR_INPUT_NAME[];\n"
1165 												"out vec4 FS_COLOR_INPUT_NAME;\n"
1166 												"\n"
1167 												"void main()\n"
1168 												"{\n"
1169 												"    for (int n = 0; n < 3; ++n)\n"
1170 												"    {\n"
1171 												"        gl_Position         = vec4(gl_in[n].gl_Position.x, "
1172 												"-gl_in[n].gl_Position.y, gl_in[n].gl_Position.zw);\n"
1173 												"        FS_COLOR_INPUT_NAME = GS_COLOR_INPUT_NAME[n];\n"
1174 												"\n"
1175 												"        EmitVertex();\n"
1176 												"    }\n"
1177 												"\n"
1178 												"    EndPrimitive();\n"
1179 												"}\n";
1180 		static const char* functional_tc_code =
1181 			"${VERSION}\n"
1182 			"${TESSELLATION_SHADER_REQUIRE}\n"
1183 			"\n"
1184 			"in  vec4 TC_COLOR_INPUT_NAME[];\n"
1185 			"out vec4 TE_COLOR_INPUT_NAME[];\n"
1186 			"\n"
1187 			"layout(vertices = 3) out;\n"
1188 			"\n"
1189 			"void main()\n"
1190 			"{\n"
1191 			"    gl_out             [gl_InvocationID].gl_Position = gl_in              [gl_InvocationID].gl_Position;\n"
1192 			"    TE_COLOR_INPUT_NAME[gl_InvocationID]             = TC_COLOR_INPUT_NAME[gl_InvocationID];\n"
1193 			"\n"
1194 			"    gl_TessLevelInner[0] = 3.0;\n"
1195 			"    gl_TessLevelOuter[0] = 3.0;\n"
1196 			"    gl_TessLevelOuter[1] = 3.0;\n"
1197 			"    gl_TessLevelOuter[2] = 3.0;\n"
1198 			"}\n";
1199 		static const char* functional_te_code =
1200 			"${VERSION}\n"
1201 			"\n"
1202 			"${TESSELLATION_SHADER_REQUIRE}\n"
1203 			"\n"
1204 			"layout(triangles, equal_spacing, cw) in;\n"
1205 			"\n"
1206 			"in  vec4 TE_COLOR_INPUT_NAME[];\n"
1207 			"out vec4 TE_COLOR_OUTPUT_NAME;\n"
1208 			"\n"
1209 			"void main()\n"
1210 			"{\n"
1211 			"    vec2 p1 = gl_in[0].gl_Position.xy;\n"
1212 			"    vec2 p2 = gl_in[1].gl_Position.xy;\n"
1213 			"    vec2 p3 = gl_in[2].gl_Position.xy;\n"
1214 			"\n"
1215 			"    TE_COLOR_OUTPUT_NAME = TE_COLOR_INPUT_NAME[0] + TE_COLOR_INPUT_NAME[1] + TE_COLOR_INPUT_NAME[2];\n"
1216 			"    gl_Position          = vec4(gl_TessCoord.x * p1.x + gl_TessCoord.y * p2.x + gl_TessCoord.z * p3.x,\n"
1217 			"                                gl_TessCoord.x * p1.y + gl_TessCoord.y * p2.y + gl_TessCoord.z * p3.y,\n"
1218 			"                                0.0,\n"
1219 			"                                1.0);\n"
1220 			"}\n";
1221 		static const char* functional_vs_code = "${VERSION}\n"
1222 												"\n"
1223 												"out vec4 VS_COLOR_OUTPUT_NAME;\n"
1224 												"in  vec4 vertex;\n"
1225 												"\n"
1226 												"OPTIONAL_USE_VERTEX_ATTRIB_BINDING_DEFINITIONS\n"
1227 												"\n"
1228 												"void main()\n"
1229 												"{\n"
1230 												"    float vertex_id_float = float(gl_VertexID);\n"
1231 												"\n"
1232 												"#ifdef USE_VERTEX_ATTRIB_BINDING\n"
1233 												"    vec4  color           = in_color;\n"
1234 												"#else\n"
1235 												"    vec4  color           = vec4(vertex_id_float / 7.0,\n"
1236 												"                                 vertex_id_float / 3.0,\n"
1237 												"                                 vertex_id_float / 17.0,\n"
1238 												"                                 1.0);\n"
1239 												"#endif\n"
1240 												"    float scale           = (gl_InstanceID == 0) ? 1.0 :\n"
1241 												"                            (gl_InstanceID == 1) ? 0.8 :\n"
1242 												"                                                   0.5;\n"
1243 												"\n"
1244 												"    VS_COLOR_OUTPUT_NAME = color;\n"
1245 												"    gl_Position          = vec4(vertex.xy * scale, vertex.zw);\n"
1246 												"}\n";
1247 
1248 		/* Release a program object if one has already been set up for the running test */
1249 		deinitProgramAndShaderObjects();
1250 
1251 		/* Replace the tokens with actual variable names */
1252 		std::string fs_body					  = specializeShader(1, &functional_fs_code);
1253 		std::string fs_color_input_name_token = "FS_COLOR_INPUT_NAME";
1254 		std::string fs_color_input_name_token_value;
1255 		std::string gs_body					  = specializeShader(1, &functional_gs_code);
1256 		std::string gs_color_input_name_token = "GS_COLOR_INPUT_NAME";
1257 		std::string gs_color_input_name_token_value;
1258 		std::string tc_body					  = specializeShader(1, &functional_tc_code);
1259 		std::string tc_color_input_name_token = "TC_COLOR_INPUT_NAME";
1260 		std::string tc_color_input_name_token_value;
1261 		std::string te_body					  = specializeShader(1, &functional_te_code);
1262 		std::string te_color_input_name_token = "TE_COLOR_INPUT_NAME";
1263 		std::string te_color_input_name_token_value;
1264 		std::string te_color_output_name_token = "TE_COLOR_OUTPUT_NAME";
1265 		std::string te_color_output_name_token_value;
1266 		std::string vs_body					   = specializeShader(1, &functional_vs_code);
1267 		std::string vs_color_output_name_token = "VS_COLOR_OUTPUT_NAME";
1268 		std::string vs_color_output_name_token_value;
1269 		std::string vs_optional_use_vertex_attrib_binding_definitions_token =
1270 			"OPTIONAL_USE_VERTEX_ATTRIB_BINDING_DEFINITIONS";
1271 		std::string vs_optional_use_vertex_attrib_binding_definitions_token_value;
1272 
1273 		std::string*	   bodies[] = { &fs_body, &gs_body, &tc_body, &te_body, &vs_body };
1274 		const unsigned int n_bodies = sizeof(bodies) / sizeof(bodies[0]);
1275 
1276 		std::string* token_value_pairs[] = { &fs_color_input_name_token,
1277 											 &fs_color_input_name_token_value,
1278 											 &gs_color_input_name_token,
1279 											 &gs_color_input_name_token_value,
1280 											 &tc_color_input_name_token,
1281 											 &tc_color_input_name_token_value,
1282 											 &te_color_input_name_token,
1283 											 &te_color_input_name_token_value,
1284 											 &te_color_output_name_token,
1285 											 &te_color_output_name_token_value,
1286 											 &vs_color_output_name_token,
1287 											 &vs_color_output_name_token_value,
1288 											 &vs_optional_use_vertex_attrib_binding_definitions_token,
1289 											 &vs_optional_use_vertex_attrib_binding_definitions_token_value };
1290 		const unsigned int n_token_value_pairs =
1291 			sizeof(token_value_pairs) / sizeof(token_value_pairs[0]) / 2 /* token+value */;
1292 
1293 		if (!use_tessellation_shader_stage)
1294 		{
1295 			if (!use_geometry_shader_stage)
1296 			{
1297 				/* Geometry & tessellation shader stages are not required.
1298 				 *
1299 				 * NOTE: This code-path is also used by Functional Test VII which verifies that
1300 				 *       vertex attribute bindings work correctly with basevertex draw calls.
1301 				 *       The test only uses FS & VS in its rendering pipeline and consumes a color
1302 				 *       taken from an enabled vertex attribute array instead of a vector value
1303 				 *       calculated in vertex shader stage,
1304 				 */
1305 				vs_color_output_name_token_value = "out_vs_color";
1306 				fs_color_input_name_token_value  = vs_color_output_name_token_value;
1307 
1308 				if (use_vertex_attrib_binding)
1309 				{
1310 					vs_optional_use_vertex_attrib_binding_definitions_token_value =
1311 						"#define USE_VERTEX_ATTRIB_BINDING\n"
1312 						"in vec4 in_color;\n";
1313 				}
1314 			} /* if (!use_geometry_shader_stage) */
1315 			else
1316 			{
1317 				/* Geometry shader stage is needed, but tessellation shader stage
1318 				 * can be skipped */
1319 				fs_color_input_name_token_value  = "out_fs_color";
1320 				gs_color_input_name_token_value  = "out_vs_color";
1321 				vs_color_output_name_token_value = "out_vs_color";
1322 
1323 				DE_ASSERT(!use_vertex_attrib_binding);
1324 			}
1325 		} /* if (!use_tessellation_shader_stage) */
1326 		else
1327 		{
1328 			DE_ASSERT(!use_vertex_attrib_binding);
1329 
1330 			if (!use_geometry_shader_stage)
1331 			{
1332 				/* Tessellation shader stage is needed, but geometry shader stage
1333 				 * can be skipped */
1334 				fs_color_input_name_token_value  = "out_fs_color";
1335 				tc_color_input_name_token_value  = "out_vs_color";
1336 				te_color_input_name_token_value  = "out_tc_color";
1337 				te_color_output_name_token_value = "out_fs_color";
1338 				vs_color_output_name_token_value = "out_vs_color";
1339 			} /* if (!use_geometry_shader_stage) */
1340 			else
1341 			{
1342 				/* Both tessellation and geometry shader stages are needed */
1343 				fs_color_input_name_token_value  = "out_fs_color";
1344 				gs_color_input_name_token_value  = "out_te_color";
1345 				tc_color_input_name_token_value  = "out_vs_color";
1346 				te_color_input_name_token_value  = "out_tc_color";
1347 				te_color_output_name_token_value = "out_te_color";
1348 				vs_color_output_name_token_value = "out_vs_color";
1349 			}
1350 		}
1351 
1352 		for (unsigned int n_body = 0; n_body < n_bodies; ++n_body)
1353 		{
1354 			std::string* body_ptr = bodies[n_body];
1355 
1356 			for (unsigned int n_token_value_pair = 0; n_token_value_pair < n_token_value_pairs; ++n_token_value_pair)
1357 			{
1358 				std::string token		   = *token_value_pairs[2 * n_token_value_pair + 0];
1359 				std::size_t token_location = std::string::npos;
1360 				std::string value		   = *token_value_pairs[2 * n_token_value_pair + 1];
1361 
1362 				while ((token_location = body_ptr->find(token)) != std::string::npos)
1363 				{
1364 					body_ptr->replace(token_location, token.length(), value);
1365 				} /* while (tokens are found) */
1366 			}	 /* for (all token+value pairs) */
1367 		}		  /* for (all bodies) */
1368 
1369 		/* Build the actual program */
1370 		buildProgram(fs_body.c_str(), vs_body.c_str(), use_tessellation_shader_stage ? tc_body.c_str() : DE_NULL,
1371 					 use_tessellation_shader_stage ? te_body.c_str() : DE_NULL,
1372 					 use_geometry_shader_stage ? gs_body.c_str() : DE_NULL);
1373 
1374 		m_po_uses_gs_stage				= use_geometry_shader_stage;
1375 		m_po_uses_tc_te_stages			= use_tessellation_shader_stage;
1376 		m_po_uses_vertex_attrib_binding = use_vertex_attrib_binding;
1377 	}
1378 
1379 	/* Set up the vertex array object */
1380 	if (m_vao_id != 0)
1381 	{
1382 		gl.deleteVertexArrays(1, &m_vao_id);
1383 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
1384 
1385 		m_vao_id = 0;
1386 	}
1387 
1388 	if (!use_clientside_vertex_data)
1389 	{
1390 		gl.genVertexArrays(1, &m_vao_id);
1391 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1392 	}
1393 	gl.bindVertexArray(m_vao_id);
1394 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1395 
1396 	if (m_po_color_attribute_location != -1)
1397 	{
1398 		DE_ASSERT(use_vertex_attrib_binding);
1399 
1400 		gl.enableVertexAttribArray(m_po_color_attribute_location);
1401 	}
1402 
1403 	gl.enableVertexAttribArray(m_po_vertex_attribute_location);
1404 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call(s) failed.");
1405 
1406 	/* Configure the VAO */
1407 	if (use_clientside_index_data)
1408 	{
1409 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1410 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1411 	}
1412 	else
1413 	{
1414 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id);
1415 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1416 	}
1417 
1418 	if (use_clientside_vertex_data)
1419 	{
1420 		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1421 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1422 	}
1423 	else
1424 	{
1425 		gl.bindBuffer(GL_ARRAY_BUFFER, use_overflow_test_vertices ? m_bo_id_2 : m_bo_id);
1426 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1427 	}
1428 
1429 	if (!use_vertex_attrib_binding)
1430 	{
1431 		DE_ASSERT(m_po_color_attribute_location == -1);
1432 
1433 		gl.vertexAttribPointer(m_po_vertex_attribute_location, 2, /* size */
1434 							   GL_FLOAT, GL_FALSE,				  /* normalized */
1435 							   0,								  /* stride */
1436 							   m_draw_call_vertex_offset);
1437 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
1438 	} /* if (!use_vertex_attrib_binding) */
1439 	else
1440 	{
1441 		DE_ASSERT(m_po_color_attribute_location != -1);
1442 		DE_ASSERT(m_draw_call_vertex_offset < m_draw_call_color_offset);
1443 
1444 		gl.vertexAttribFormat(m_po_color_attribute_location, 2, /* size */
1445 							  GL_FLOAT,							/* type */
1446 							  GL_FALSE,							/* normalized */
1447 							  (glw::GLuint)((const glw::GLubyte*)m_draw_call_color_offset -
1448 											(const glw::GLubyte*)m_draw_call_vertex_offset));
1449 		gl.vertexAttribFormat(m_po_vertex_attribute_location, 2, /* size */
1450 							  GL_FLOAT,							 /* type */
1451 							  GL_FALSE,							 /* normalized */
1452 							  0);								 /* relativeoffset */
1453 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribFormat() call(s) failed.");
1454 
1455 		gl.vertexAttribBinding(m_po_color_attribute_location, 0);  /* bindingindex */
1456 		gl.vertexAttribBinding(m_po_vertex_attribute_location, 0); /* bindingindex */
1457 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribBinding() call(s) failed.");
1458 
1459 		gl.bindVertexBuffer(0, /* bindingindex */
1460 							(use_clientside_vertex_data) ? 0 : (use_overflow_test_vertices ? m_bo_id_2 : m_bo_id),
1461 							(glw::GLintptr)m_draw_call_vertex_offset, sizeof(float) * 2);
1462 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexBuffer() call failed.");
1463 	}
1464 
1465 	/* Bind the program object to the rendering context */
1466 	gl.useProgram(m_po_id);
1467 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1468 }
1469 
1470 /** Sets up all ES objects required to run a single negative test case iteration.
1471  *
1472  *  @param use_clientside_vertex_data    true if the test case requires client-side buffers to
1473  *                                       back the color/vertex vertex attribute arrays; false
1474  *                                       to use buffer object storage.
1475  *  @param use_clientside_index_data     true if the test case requires client-side buffers to
1476  *                                       be used as index data source; false to use buffer object
1477  *                                       storage.
1478  */
setUpNegativeTestObjects(bool use_clientside_vertex_data,bool use_clientside_index_data)1479 void DrawElementsBaseVertexTestBase::setUpNegativeTestObjects(bool use_clientside_vertex_data,
1480 															  bool use_clientside_index_data)
1481 {
1482 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1483 
1484 	/* Set up buffer object we will use for the draw calls. Use the data
1485 	 * from the test specification */
1486 	if (m_bo_id == 0)
1487 	{
1488 		gl.genBuffers(1, &m_bo_id);
1489 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1490 
1491 		gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1492 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1493 
1494 		gl.bufferData(GL_ARRAY_BUFFER, m_bo_negative_data_index_size + m_bo_negative_data_vertex_size,
1495 					  DE_NULL, /* data */
1496 					  GL_STATIC_DRAW);
1497 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1498 
1499 		gl.bufferSubData(GL_ARRAY_BUFFER, 0, /* offset */
1500 						 m_bo_negative_data_vertex_size, m_bo_negative_data_vertex);
1501 		gl.bufferSubData(GL_ARRAY_BUFFER, m_bo_negative_data_vertex_size, /* offset */
1502 						 m_bo_negative_data_index_size, m_bo_negative_data_index);
1503 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
1504 	}
1505 
1506 	if (use_clientside_index_data)
1507 	{
1508 		m_draw_call_index_offset = m_bo_negative_data_index;
1509 	}
1510 	else
1511 	{
1512 		m_draw_call_index_offset = (const glw::GLuint*)(deUintptr)m_bo_negative_data_vertex_size;
1513 	}
1514 
1515 	if (use_clientside_vertex_data)
1516 	{
1517 		m_draw_call_vertex_offset = m_bo_negative_data_vertex;
1518 	}
1519 	else
1520 	{
1521 		m_draw_call_vertex_offset = DE_NULL;
1522 	}
1523 
1524 	/* Set up the test program object */
1525 	if (m_po_id == 0)
1526 	{
1527 		static const char* negative_fs_code = "${VERSION}\n"
1528 											  "precision highp float;\n"
1529 											  "\n"
1530 											  "out vec4 result;\n"
1531 											  "\n"
1532 											  "void main()\n"
1533 											  "{\n"
1534 											  "    result = vec4(1.0);\n"
1535 											  "}\n";
1536 		static const char* negative_vs_code = "${VERSION}\n"
1537 											  "\n"
1538 											  "in vec4 vertex;\n"
1539 											  "\n"
1540 											  "void main()\n"
1541 											  "{\n"
1542 											  "    gl_Position = vertex;\n"
1543 											  "}\n";
1544 
1545 		std::string fs_specialized_code		= specializeShader(1, &negative_fs_code);
1546 		const char* fs_specialized_code_raw = fs_specialized_code.c_str();
1547 		std::string vs_specialized_code		= specializeShader(1, &negative_vs_code);
1548 		const char* vs_specialized_code_raw = vs_specialized_code.c_str();
1549 
1550 		buildProgram(fs_specialized_code_raw, vs_specialized_code_raw, DE_NULL, /* tc_code */
1551 					 DE_NULL,													/* te_code */
1552 					 DE_NULL);													/* gs_code */
1553 	}
1554 
1555 	/* Set up a vertex array object */
1556 	if (m_vao_id == 0)
1557 	{
1558 		gl.genVertexArrays(1, &m_vao_id);
1559 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1560 
1561 		gl.bindVertexArray(m_vao_id);
1562 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1563 
1564 		gl.enableVertexAttribArray(m_po_vertex_attribute_location);
1565 		GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
1566 	}
1567 
1568 	/* Configure the VAO */
1569 	if (use_clientside_index_data)
1570 	{
1571 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1572 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1573 	}
1574 	else
1575 	{
1576 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id);
1577 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1578 	}
1579 
1580 	if (use_clientside_vertex_data)
1581 	{
1582 		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1583 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1584 
1585 		gl.bindVertexArray(0);
1586 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1587 	}
1588 	else
1589 	{
1590 		gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1591 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1592 	}
1593 
1594 	gl.vertexAttribPointer(m_po_vertex_attribute_location, 2, /* size */
1595 						   GL_FLOAT, GL_FALSE,				  /* normalized */
1596 						   0,								  /* stride */
1597 						   m_draw_call_vertex_offset);
1598 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
1599 
1600 	/* Bind the program object to the rendering context */
1601 	gl.useProgram(m_po_id);
1602 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1603 }
1604 
1605 /** Constructor.
1606  *
1607  *  @param context Rendering context handle.
1608  **/
DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior(Context & context,const ExtParameters & extParams)1609 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior(
1610 	Context& context, const ExtParameters& extParams)
1611 	: DrawElementsBaseVertexTestBase(context, extParams, "basevertex_behavior1",
1612 									 "Verifies basevertex draw calls work correctly for a number of "
1613 									 "different rendering pipeline and VAO configurations")
1614 {
1615 	/* Left blank on purpose */
1616 }
1617 
1618 /** Sets up test case descriptors for the test instance. These will later be used
1619  *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1620  *  the actual testing.
1621  **/
setUpTestCases()1622 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::setUpTestCases()
1623 {
1624 	/* Set up test case descriptors */
1625 	const glw::GLint   basevertex_values[] = { 10, 0 };
1626 	const unsigned int n_basevertex_values = sizeof(basevertex_values) / sizeof(basevertex_values[0]);
1627 
1628 	/* The test needs to be run in two iterations, using client-side memory and buffer object
1629 	 * for index data respectively
1630 	 */
1631 	for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1632 	{
1633 		/* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1634 		 *  See section 11.1.3.9 in OpenGL ES 3.1 spec
1635 		 */
1636 		bool use_clientside_vertex_data = 0;
1637 		bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
1638 
1639 		/* OpenGL does not support client-side data. */
1640 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1641 		{
1642 			if (use_clientside_index_data || use_clientside_vertex_data)
1643 			{
1644 				continue;
1645 			}
1646 		}
1647 
1648 		/* Compute the offsets */
1649 		computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1650 
1651 		/* There are two index data sets we need to iterate over */
1652 		const glw::GLuint* index_offsets[] = { m_draw_call_index_offset, m_draw_call_index2_offset };
1653 		const unsigned int n_index_offsets = sizeof(index_offsets) / sizeof(index_offsets[0]);
1654 
1655 		for (unsigned int n_index_offset = 0; n_index_offset < n_index_offsets; ++n_index_offset)
1656 		{
1657 			const glw::GLuint* current_index_offset = index_offsets[n_index_offset];
1658 
1659 			/* We need to test four different functions:
1660 			 *
1661 			 * a)    glDrawElementsBaseVertex()             (GL)
1662 			 *    or glDrawElementsBaseVertexEXT()          (ES)
1663 			 * b)    glDrawRangeElementsBaseVertex()        (GL)
1664 			 *    or glDrawRangeElementsBaseVertexEXT()     (ES)
1665 			 * c)    glDrawElementsInstancedBaseVertex()    (GL)
1666 			 *    or glDrawElementsInstancedBaseVertexEXT() (ES)
1667 			 * d)    glMultiDrawElementsBaseVertex()        (GL)
1668 			 *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
1669 			 **/
1670 			for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1671 			{
1672 				/* Do not try to use the multi draw call if relevant extension is
1673 				 * not supported. */
1674 				if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1675 				{
1676 					continue;
1677 				}
1678 
1679 				/* We need to run the test for a number of different basevertex values. */
1680 				for (unsigned int n_basevertex_value = 0; n_basevertex_value < n_basevertex_values;
1681 					 ++n_basevertex_value)
1682 				{
1683 					/* Finally, we want to verify that basevertex draw calls work correctly both when vertex attribute
1684 					 * bindings are enabled and disabled */
1685 					bool		 vertex_attrib_binding_statuses[] = { false, true };
1686 					unsigned int n_vertex_attrib_binding_statuses =
1687 						sizeof(vertex_attrib_binding_statuses) / sizeof(vertex_attrib_binding_statuses[0]);
1688 
1689 					for (unsigned int n_vertex_attrib_binding_status = 0;
1690 						 n_vertex_attrib_binding_status < n_vertex_attrib_binding_statuses;
1691 						 ++n_vertex_attrib_binding_status)
1692 					{
1693 						bool use_vertex_attrib_binding = vertex_attrib_binding_statuses[n_vertex_attrib_binding_status];
1694 
1695 						/* Under GL, "vertex attrib binding" functionality is only available if GL_ARB_vertex_attrib_binding
1696 						 * extension is supported.
1697 						 */
1698 						if (!m_is_vertex_attrib_binding_supported && use_vertex_attrib_binding)
1699 						{
1700 							continue;
1701 						}
1702 
1703 						/* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1704 						const glw::GLsizei multi_draw_call_count_array[3]   = { 3, 6, 3 };
1705 						const glw::GLuint* multi_draw_call_indices_array[3] = {
1706 							(glw::GLuint*)(current_index_offset), (glw::GLuint*)(current_index_offset + 3),
1707 							(glw::GLuint*)(current_index_offset + 9)
1708 						};
1709 
1710 						/* Reference texture should always reflect basevertex=10 behavior. */
1711 						const glw::GLuint  regular_draw_call_offset					 = basevertex_values[0];
1712 						const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1713 							multi_draw_call_indices_array[0] + regular_draw_call_offset,
1714 							multi_draw_call_indices_array[1] + regular_draw_call_offset,
1715 							multi_draw_call_indices_array[2] + regular_draw_call_offset,
1716 						};
1717 
1718 						/* Construct the test case descriptor */
1719 						_test_case new_test_case;
1720 
1721 						new_test_case.basevertex			   = basevertex_values[n_basevertex_value];
1722 						new_test_case.function_type			   = (_function_type)n_function;
1723 						new_test_case.index_offset			   = current_index_offset;
1724 						new_test_case.range_start			   = n_index_offset == 0 ? 0 : 10;
1725 						new_test_case.range_end				   = n_index_offset == 0 ? 22 : 32;
1726 						new_test_case.index_type			   = GL_UNSIGNED_INT;
1727 						new_test_case.primitive_mode		   = GL_TRIANGLES;
1728 						new_test_case.regular_draw_call_offset = basevertex_values[0];
1729 						new_test_case.should_base_texture_match_reference_texture =
1730 							((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
1731 						new_test_case.use_clientside_index_data		= use_clientside_index_data;
1732 						new_test_case.use_clientside_vertex_data	= use_clientside_vertex_data;
1733 						new_test_case.use_geometry_shader_stage		= false;
1734 						new_test_case.use_tessellation_shader_stage = false;
1735 						new_test_case.use_vertex_attrib_binding		= use_vertex_attrib_binding;
1736 
1737 						memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1738 							   sizeof(multi_draw_call_count_array));
1739 						memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1740 							   sizeof(multi_draw_call_indices_array));
1741 						memcpy(new_test_case.regular_multi_draw_call_offseted_array,
1742 							   regular_multi_draw_call_offseted_array, sizeof(regular_multi_draw_call_offseted_array));
1743 
1744 						m_test_cases.push_back(new_test_case);
1745 					} /* for (all vertex_attrib_binding statuses) */
1746 				}	 /* for (all basevertex values) */
1747 			}		  /* for (all four functions) */
1748 		}			  /* for (all index data sets) */
1749 	}				  /* for (all VAO iterations) */
1750 }
1751 
1752 /** Executes test iteration.
1753  *
1754  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1755  */
iterate()1756 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::iterate()
1757 {
1758 	setUpTestCases();
1759 	executeTestCases();
1760 
1761 	/* Test case passed */
1762 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1763 
1764 	return STOP;
1765 }
1766 
1767 /** Constructor.
1768  *
1769  *  @param context Rendering context handle.
1770  **/
DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2(Context & context,const ExtParameters & extParams)1771 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2(
1772 	Context& context, const ExtParameters& extParams)
1773 	: DrawElementsBaseVertexTestBase(context, extParams, "basevertex_behavior2",
1774 									 "Verifies basevertex draw calls work correctly for a number of "
1775 									 "different rendering pipeline and VAO configurations. Uses slightly "
1776 									 "different data set than basevertex_behavior.")
1777 {
1778 	/* Left blank on purpose */
1779 }
1780 
1781 /** Sets up test case descriptors for the test instance. These will later be used
1782  *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1783  *  the actual testing.
1784  **/
setUpTestCases()1785 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::setUpTestCases()
1786 {
1787 	/* Set up test case descriptors */
1788 	const glw::GLint basevertex = 5;
1789 
1790 	/* The test needs to be run in two iterations, using client-side memory and buffer object
1791 	 * for index data respectively
1792 	 */
1793 	for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1794 	{
1795 		/* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1796 		 *  See section 11.1.3.9 in OpenGL ES 3.1 spec
1797 		 */
1798 		bool use_clientside_vertex_data = 0;
1799 		bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
1800 
1801 		/* OpenGL does not support client-side data. */
1802 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1803 		{
1804 			if (use_clientside_index_data || use_clientside_vertex_data)
1805 			{
1806 				continue;
1807 			}
1808 		}
1809 
1810 		/* Compute the offsets */
1811 		computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1812 
1813 		/* We need to test four different functions:
1814 		 *
1815 		 * a)    glDrawElementsBaseVertex()             (GL)
1816 		 *    or glDrawElementsBaseVertexEXT()          (ES)
1817 		 * b)    glDrawRangeElementsBaseVertex()        (GL)
1818 		 *    or glDrawRangeElementsBaseVertexEXT()     (ES)
1819 		 * c)    glDrawElementsInstancedBaseVertex()    (GL)
1820 		 *    or glDrawElementsInstancedBaseVertexEXT() (ES)
1821 		 * d)    glMultiDrawElementsBaseVertex()        (GL)
1822 		 *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
1823 		 **/
1824 		for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1825 		{
1826 			/* Do not try to use the multi draw call if relevant extension is
1827 			 * not supported. */
1828 			if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1829 			{
1830 				continue;
1831 			}
1832 
1833 			/* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1834 			const glw::GLsizei multi_draw_call_count_array[3]   = { 3, 6, 3 };
1835 			const glw::GLuint* multi_draw_call_indices_array[3] = { (glw::GLuint*)(m_draw_call_index_offset),
1836 																	(glw::GLuint*)(m_draw_call_index_offset + 3),
1837 																	(glw::GLuint*)(m_draw_call_index_offset + 9) };
1838 
1839 			/* Reference texture should always reflect basevertex=10 behavior. */
1840 			const glw::GLuint  regular_draw_call_offset					 = 0;
1841 			const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1842 				multi_draw_call_indices_array[0] + regular_draw_call_offset,
1843 				multi_draw_call_indices_array[1] + regular_draw_call_offset,
1844 				multi_draw_call_indices_array[2] + regular_draw_call_offset,
1845 			};
1846 
1847 			/* Construct the test case descriptor */
1848 			_test_case new_test_case;
1849 
1850 			new_test_case.basevertex			   = basevertex;
1851 			new_test_case.function_type			   = (_function_type)n_function;
1852 			new_test_case.index_offset			   = m_draw_call_index_offset;
1853 			new_test_case.range_start			   = 0;
1854 			new_test_case.range_end				   = 22;
1855 			new_test_case.index_type			   = GL_UNSIGNED_INT;
1856 			new_test_case.primitive_mode		   = GL_TRIANGLES;
1857 			new_test_case.regular_draw_call_offset = regular_draw_call_offset;
1858 			new_test_case.should_base_texture_match_reference_texture =
1859 				((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
1860 			new_test_case.use_clientside_index_data		= use_clientside_index_data;
1861 			new_test_case.use_clientside_vertex_data	= use_clientside_vertex_data;
1862 			new_test_case.use_geometry_shader_stage		= false;
1863 			new_test_case.use_tessellation_shader_stage = false;
1864 			new_test_case.use_vertex_attrib_binding		= false;
1865 
1866 			memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1867 				   sizeof(multi_draw_call_count_array));
1868 			memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1869 				   sizeof(multi_draw_call_indices_array));
1870 			memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
1871 				   sizeof(regular_multi_draw_call_offseted_array));
1872 
1873 			m_test_cases.push_back(new_test_case);
1874 		} /* for (all four functions) */
1875 	}	 /* for (all VAO iterations) */
1876 }
1877 
1878 /** Executes test iteration.
1879  *
1880  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1881  */
iterate()1882 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::iterate()
1883 {
1884 	setUpTestCases();
1885 	executeTestCases();
1886 
1887 	/* Test case passed */
1888 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1889 
1890 	return STOP;
1891 }
1892 
1893 /** Constructor.
1894  *
1895  *  @param context Rendering context handle.
1896  **/
1897 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::
DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow(Context & context,const ExtParameters & extParams)1898 	DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow(Context& context, const ExtParameters& extParams)
1899 	: DrawElementsBaseVertexTestBase(context, extParams, "underflow",
1900 									 "Verifies basevertex draw calls work correctly for negative "
1901 									 "basevertex values")
1902 {
1903 	/* Left blank on purpose */
1904 }
1905 
1906 /** Sets up test case descriptors for the test instance. These will later be used
1907  *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1908  *  the actual testing.
1909  **/
setUpTestCases()1910 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::setUpTestCases()
1911 {
1912 	/* Set up test case descriptors */
1913 	const glw::GLint basevertex = -10;
1914 
1915 	/* The test needs to be run in two iterations, using client-side memory and buffer object
1916 	 * for index data respectively
1917 	 */
1918 	for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1919 	{
1920 		/* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1921 		 *  See section 11.1.3.9 in OpenGL ES 3.1 spec
1922 		 */
1923 		bool use_clientside_vertex_data = 0;
1924 		bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
1925 
1926 		/* OpenGL does not support client-side data. */
1927 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1928 		{
1929 			if (use_clientside_index_data || use_clientside_vertex_data)
1930 			{
1931 				continue;
1932 			}
1933 		}
1934 
1935 		/* Compute the offsets */
1936 		computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1937 
1938 		/* We need to test four different functions:
1939 		 *
1940 		 * a)    glDrawElementsBaseVertex()             (GL)
1941 		 *    or glDrawElementsBaseVertexEXT()          (ES)
1942 		 * b)    glDrawRangeElementsBaseVertex()        (GL)
1943 		 *    or glDrawRangeElementsBaseVertexEXT()     (ES)
1944 		 * c)    glDrawElementsInstancedBaseVertex()    (GL)
1945 		 *    or glDrawElementsInstancedBaseVertexEXT() (ES)
1946 		 * d)    glMultiDrawElementsBaseVertex()        (GL)
1947 		 *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
1948 		 **/
1949 		for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1950 		{
1951 			/* Do not try to use the multi draw call if relevant extension is
1952 			 * not supported. */
1953 			if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1954 			{
1955 				continue;
1956 			}
1957 
1958 			/* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1959 			unsigned int offset_from_10_to_0_index = 23; /* this offset moves us from the start index of 10 to a zero
1960 			 * index, given the second index data set we will be using.
1961 			 * Please see declaration of functional2_index_data if you
1962 			 * need to verify this by yourself. */
1963 
1964 			const glw::GLsizei multi_draw_call_count_array[3]   = { 3, 6, 3 };
1965 			const glw::GLuint* multi_draw_call_indices_array[3] = { (glw::GLuint*)(m_draw_call_index2_offset),
1966 																	(glw::GLuint*)(m_draw_call_index2_offset + 3),
1967 																	(glw::GLuint*)(m_draw_call_index2_offset + 9) };
1968 			const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1969 				multi_draw_call_indices_array[0] + offset_from_10_to_0_index,
1970 				multi_draw_call_indices_array[1] + offset_from_10_to_0_index,
1971 				multi_draw_call_indices_array[2] + offset_from_10_to_0_index,
1972 			};
1973 
1974 			/* Construct the test case descriptor */
1975 			_test_case new_test_case;
1976 
1977 			new_test_case.basevertex								  = basevertex;
1978 			new_test_case.function_type								  = (_function_type)n_function;
1979 			new_test_case.index_offset								  = m_draw_call_index2_offset;
1980 			new_test_case.range_start								  = 10;
1981 			new_test_case.range_end									  = 32;
1982 			new_test_case.index_type								  = GL_UNSIGNED_INT;
1983 			new_test_case.primitive_mode							  = GL_TRIANGLES;
1984 			new_test_case.regular_draw_call_offset					  = offset_from_10_to_0_index;
1985 			new_test_case.should_base_texture_match_reference_texture = true;
1986 			new_test_case.use_clientside_index_data					  = use_clientside_index_data;
1987 			new_test_case.use_clientside_vertex_data				  = use_clientside_vertex_data;
1988 			new_test_case.use_geometry_shader_stage					  = false;
1989 			new_test_case.use_tessellation_shader_stage				  = false;
1990 			new_test_case.use_vertex_attrib_binding					  = false;
1991 
1992 			memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1993 				   sizeof(multi_draw_call_count_array));
1994 			memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1995 				   sizeof(multi_draw_call_indices_array));
1996 			memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
1997 				   sizeof(regular_multi_draw_call_offseted_array));
1998 
1999 			m_test_cases.push_back(new_test_case);
2000 		} /* for (all four functions) */
2001 	}	 /* for (all VAO iterations) */
2002 }
2003 
2004 /** Executes test iteration.
2005  *
2006  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2007  */
iterate()2008 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::iterate()
2009 {
2010 	setUpTestCases();
2011 	executeTestCases();
2012 
2013 	/* Test case passed */
2014 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2015 
2016 	return STOP;
2017 }
2018 
2019 /** Constructor.
2020  *
2021  *  @param context Rendering context handle.
2022  **/
2023 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::
DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow(Context & context,const ExtParameters & extParams)2024 	DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow(Context& context, const ExtParameters& extParams)
2025 	: DrawElementsBaseVertexTestBase(context, extParams, "overflow",
2026 									 "Verifies basevertex draw calls work correctly for overflowing "
2027 									 "basevertex values")
2028 {
2029 	/* Left blank on purpose */
2030 }
2031 
2032 /** Sets up test case descriptors for the test instance. These will later be used
2033  *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
2034  *  the actual testing.
2035  **/
setUpTestCases()2036 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::setUpTestCases()
2037 {
2038 	/* The test needs to be run in two iterations, using client-side memory and buffer object
2039 	 * for index data respectively
2040 	 */
2041 	for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
2042 	{
2043 		/* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
2044 		 *  See section 11.1.3.9 in OpenGL ES 3.1 spec
2045 		 */
2046 		bool use_clientside_vertex_data = 0;
2047 		bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
2048 
2049 		/* OpenGL does not support client-side data. */
2050 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2051 		{
2052 			if (use_clientside_index_data || use_clientside_vertex_data)
2053 			{
2054 				continue;
2055 			}
2056 		}
2057 
2058 		/* Compute the offsets */
2059 		computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
2060 
2061 		/* We need to test four different functions:
2062 		 *
2063 		 * a)    glDrawElementsBaseVertex()             (GL)
2064 		 *    or glDrawElementsBaseVertexEXT()          (ES)
2065 		 * b)    glDrawRangeElementsBaseVertex()        (GL)
2066 		 *    or glDrawRangeElementsBaseVertexEXT()     (ES)
2067 		 * c)    glDrawElementsInstancedBaseVertex()    (GL)
2068 		 *    or glDrawElementsInstancedBaseVertexEXT() (ES)
2069 		 * d)    glMultiDrawElementsBaseVertex()        (GL)
2070 		 *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
2071 		 **/
2072 		for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
2073 		{
2074 			/* Do not try to use the multi draw call if relevant extension is
2075 			 * not supported. */
2076 			if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
2077 			{
2078 				continue;
2079 			}
2080 
2081 			const glw::GLenum index_types[] = { GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT };
2082 
2083 			const unsigned int n_index_types = sizeof(index_types) / sizeof(index_types[0]);
2084 
2085 			for (unsigned int n_index_type = 0; n_index_type < n_index_types; ++n_index_type)
2086 			{
2087 
2088 				glw::GLint			basevertex					 = -1;
2089 				const glw::GLubyte* index_offset				 = NULL;
2090 				int					index_size					 = 0;
2091 				glw::GLenum			index_type					 = index_types[n_index_type];
2092 				glw::GLenum			regular_draw_call_index_type = 0;
2093 				int					regular_draw_call_index_size = 0;
2094 				glw::GLboolean		use_overflow_test_vertices   = false;
2095 
2096 				/* To meet requirements of tests IX.1-IX.2 and IX.3, we need to use two basevertex deltas. */
2097 				const glw::GLint basevertex_deltas[] = {
2098 					0, /* IX.1-IX.2 */
2099 					1  /* IX.3 */
2100 				};
2101 				const unsigned int n_basevertex_deltas = sizeof(basevertex_deltas) / sizeof(basevertex_deltas[0]);
2102 
2103 				for (unsigned int n_basevertex_delta = 0; n_basevertex_delta < n_basevertex_deltas;
2104 					 ++n_basevertex_delta)
2105 				{
2106 					const glw::GLint basevertex_delta		   = basevertex_deltas[n_basevertex_delta];
2107 					glw::GLuint		 regular_draw_call_offset  = 0;
2108 					glw::GLuint*	 regular_draw_call_offset2 = NULL;
2109 					glw::GLuint		 range_start			   = 0;
2110 					glw::GLuint		 range_end				   = 0;
2111 					bool			 shouldMatch;
2112 
2113 					switch (index_type)
2114 					{
2115 					/*
2116 					 * UBYTE base draw indices: 0, 1, 2
2117 					 *              baseVertex: 256+0
2118 					 *    regular draw indices: 0, 1, 2
2119 					 *         expected result: ubyte indices should not wrap around at 8-bit width,
2120 					 *                          base draw result should not match regular draw result
2121 					 *
2122 					 * UBYTE base draw indices: 0, 1, 2
2123 					 *              baseVertex: 256+1
2124 					 *    regular draw indices: 257, 258, 259 (uint)
2125 					 *         expected result: ubyte indices should be upconverted to 32-bit uint,
2126 					 *                          base draw result should match regular draw result
2127 					 */
2128 					case GL_UNSIGNED_BYTE:
2129 					{
2130 						basevertex					 = 256 + basevertex_delta;
2131 						index_offset				 = (const glw::GLubyte*)m_draw_call_index3_offset;
2132 						index_size					 = 1;
2133 						range_start					 = 0;
2134 						range_end					 = 2;
2135 						regular_draw_call_index_type = (basevertex_delta == 0) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT;
2136 						regular_draw_call_index_size = (regular_draw_call_index_type == GL_UNSIGNED_BYTE) ? 1 : 4;
2137 						regular_draw_call_offset2 =
2138 							(basevertex_delta == 0) ?
2139 								(glw::GLuint*)(m_draw_call_index3_offset) :
2140 								(glw::GLuint*)(m_draw_call_index5_offset + 12); // 12th in functional5_index_data
2141 						shouldMatch				   = (basevertex_delta == 1) ? true : false;
2142 						use_overflow_test_vertices = true;
2143 						break;
2144 					}
2145 
2146 					/*
2147 						 * USHORT base draw indices: 0, 1, 2
2148 						 *               baseVertex: 65536+0
2149 						 *     regular draw indices: 0, 1, 2
2150 						 *          expected result: ubyte indices should not wrap around at 16-bit width,
2151 						 *                           base draw result should not match regular draw result
2152 						 *
2153 						 * USHORT base draw indices: 0, 1, 2
2154 						 *               baseVertex: 65536+1
2155 						 *     regular draw indices: 65537, 65538, 65539 (uint)
2156 						 *          expected result: ushort indices should be upconverted to 32-bit uint,
2157 						 *                           base draw result should match regular draw result
2158 						 */
2159 					case GL_UNSIGNED_SHORT:
2160 					{
2161 						basevertex					 = 65536 + basevertex_delta;
2162 						index_offset				 = (const glw::GLubyte*)m_draw_call_index4_offset;
2163 						index_size					 = 2;
2164 						range_start					 = 0;
2165 						range_end					 = 2;
2166 						regular_draw_call_index_type = (basevertex_delta == 0) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
2167 						regular_draw_call_index_size = (regular_draw_call_index_type == GL_UNSIGNED_SHORT) ? 2 : 4;
2168 						regular_draw_call_offset2 =
2169 							(basevertex_delta == 0) ?
2170 								(glw::GLuint*)(m_draw_call_index4_offset) :
2171 								(glw::GLuint*)(m_draw_call_index5_offset + 24); // 24th in functional5_index_data
2172 						shouldMatch				   = (basevertex_delta == 1) ? true : false;
2173 						use_overflow_test_vertices = true;
2174 						break;
2175 					}
2176 
2177 					/*
2178 						 * UINT base draw indices: 2^31+2, 2^31+3, 2^31+4
2179 						 *             baseVertex: 2^31-2
2180 						 *   regular draw indices: 0, 1, 2
2181 						 *        expected result: uint indices should wrap to {0, 1, 2},
2182 						 *                         base draw result should match regular draw result
2183 						 *
2184 						 * UINT base draw indices: 2^31+2, 2^31+3, 2^31+4
2185 						 *             baseVertex: 2^31-1
2186 						 *   regular draw indices: 0, 1, 2
2187 						 *        expected result: uint indices should wrap to {1, 2, 3},
2188 						 *                         base draw result should not match regular draw result
2189 						 */
2190 					case GL_UNSIGNED_INT:
2191 					{
2192 						basevertex					 = 2147483647 - 1 + basevertex_delta;
2193 						index_offset				 = (const glw::GLubyte*)m_draw_call_index5_offset;
2194 						index_size					 = 4;
2195 						range_start					 = 2147483647 + 3u; // 2^31+2
2196 						range_end					 = 2147483647 + 5u; // 2^31+4
2197 						regular_draw_call_index_type = GL_UNSIGNED_INT;
2198 						regular_draw_call_index_size = 4;
2199 						regular_draw_call_offset	 = 36; // 36th in functional5_index_data
2200 						shouldMatch					 = (basevertex_delta == 0) ? true : false;
2201 						use_overflow_test_vertices   = false;
2202 						break;
2203 					}
2204 
2205 					default:
2206 					{
2207 						TCU_FAIL("Unrecognized index type");
2208 					}
2209 					} /* switch (index_type) */
2210 
2211 					/* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
2212 					const glw::GLsizei  multi_draw_call_count_array[3]   = { 3, 6, 3 };
2213 					const glw::GLubyte* multi_draw_call_indices_array[3] = { index_offset,
2214 																			 index_offset + 3 * index_size,
2215 																			 index_offset + 9 * index_size };
2216 					const glw::GLubyte* regular_multi_draw_call_offseted_array[3];
2217 					if (use_overflow_test_vertices)
2218 					{
2219 						regular_multi_draw_call_offseted_array[0] = (glw::GLubyte*)regular_draw_call_offset2;
2220 						regular_multi_draw_call_offseted_array[1] =
2221 							(glw::GLubyte*)regular_draw_call_offset2 + 3 * regular_draw_call_index_size;
2222 						regular_multi_draw_call_offseted_array[2] =
2223 							(glw::GLubyte*)regular_draw_call_offset2 + 9 * regular_draw_call_index_size;
2224 					}
2225 					else
2226 					{
2227 						regular_multi_draw_call_offseted_array[0] =
2228 							multi_draw_call_indices_array[0] + index_size * regular_draw_call_offset;
2229 						regular_multi_draw_call_offseted_array[1] =
2230 							multi_draw_call_indices_array[1] + index_size * regular_draw_call_offset;
2231 						regular_multi_draw_call_offseted_array[2] =
2232 							multi_draw_call_indices_array[2] + index_size * regular_draw_call_offset;
2233 					}
2234 
2235 					/* Construct the test case descriptor */
2236 					_test_case new_test_case;
2237 
2238 					new_test_case.basevertex								  = basevertex;
2239 					new_test_case.function_type								  = (_function_type)n_function;
2240 					new_test_case.index_offset								  = (const glw::GLuint*)index_offset;
2241 					new_test_case.range_start								  = range_start;
2242 					new_test_case.range_end									  = range_end;
2243 					new_test_case.index_type								  = index_type;
2244 					new_test_case.primitive_mode							  = GL_TRIANGLES;
2245 					new_test_case.regular_draw_call_offset					  = regular_draw_call_offset;
2246 					new_test_case.regular_draw_call_offset2					  = regular_draw_call_offset2;
2247 					new_test_case.regular_draw_call_index_type				  = regular_draw_call_index_type;
2248 					new_test_case.should_base_texture_match_reference_texture = shouldMatch;
2249 					new_test_case.use_clientside_index_data					  = use_clientside_index_data;
2250 					new_test_case.use_clientside_vertex_data				  = use_clientside_vertex_data;
2251 					new_test_case.use_geometry_shader_stage					  = false;
2252 					new_test_case.use_tessellation_shader_stage				  = false;
2253 					new_test_case.use_vertex_attrib_binding					  = false;
2254 					new_test_case.use_overflow_test_vertices				  = use_overflow_test_vertices != GL_FALSE;
2255 
2256 					memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
2257 						   sizeof(multi_draw_call_count_array));
2258 					memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
2259 						   sizeof(multi_draw_call_indices_array));
2260 					memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
2261 						   sizeof(regular_multi_draw_call_offseted_array));
2262 
2263 					m_test_cases.push_back(new_test_case);
2264 				} /* for (all basevertex deltas) */
2265 			}	 /* for (all index types) */
2266 		}		  /* for (all four functions) */
2267 	}			  /* for (all VAO iterations) */
2268 }
2269 
2270 /** Executes test iteration.
2271  *
2272  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2273  */
iterate()2274 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::iterate()
2275 {
2276 	setUpTestCases();
2277 	executeTestCases();
2278 
2279 	/* Test case passed */
2280 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2281 
2282 	return STOP;
2283 }
2284 
2285 /** Constructor.
2286  *
2287  *  @param context Rendering context handle.
2288  **/
2289 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::
DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages(Context & context,const ExtParameters & extParams)2290 	DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages(Context&			  context,
2291 																			 const ExtParameters& extParams)
2292 	: DrawElementsBaseVertexTestBase(context, extParams, "AEP_shader_stages",
2293 									 "Verifies basevertex draw calls work correctly when geometry & "
2294 									 "tessellation shader stages are used in the rendering pipeline.")
2295 {
2296 	/* Left blank intentionally */
2297 }
2298 
2299 /** Sets up test case descriptors for the test instance. These will later be used
2300  *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
2301  *  the actual testing.
2302  **/
setUpTestCases()2303 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::setUpTestCases()
2304 {
2305 	/* Set up test case descriptors */
2306 	const glw::GLuint basevertex_values[] = {
2307 		10, /* VI.1-VI.4 */
2308 		0   /* VI.5 */
2309 	};
2310 	const unsigned int n_basevertex_values = sizeof(basevertex_values) / sizeof(basevertex_values[0]);
2311 
2312 	/* The test needs to be run in two iterations, using client-side memory and buffer object
2313 	 * for index data respectively
2314 	 */
2315 	for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
2316 	{
2317 		/* Skip client-side vertex array as gl_VertexID is undefined when zero buffer is bound to ARRAY_BUFFER */
2318 		bool use_clientside_vertex_data = 0;
2319 		bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
2320 
2321 		/* OpenGL does not support client-side data. */
2322 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2323 		{
2324 			if (use_clientside_index_data || use_clientside_vertex_data)
2325 			{
2326 				continue;
2327 			}
2328 		}
2329 
2330 		/* Compute the offsets */
2331 		computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
2332 
2333 		/* There are two index data sets we need to iterate over */
2334 		const glw::GLuint* index_offsets[] = { m_draw_call_index_offset, m_draw_call_index2_offset };
2335 		const unsigned int n_index_offsets = sizeof(index_offsets) / sizeof(index_offsets[0]);
2336 
2337 		for (unsigned int n_index_offset = 0; n_index_offset < n_index_offsets; ++n_index_offset)
2338 		{
2339 			const glw::GLuint* current_index_offset = index_offsets[n_index_offset];
2340 
2341 			/* We need to test four different functions:
2342 			 *
2343 			 * a)    glDrawElementsBaseVertex()             (GL)
2344 			 *    or glDrawElementsBaseVertexEXT()          (ES)
2345 			 * b)    glDrawRangeElementsBaseVertex()        (GL)
2346 			 *    or glDrawRangeElementsBaseVertexEXT()     (ES)
2347 			 * c)    glDrawElementsInstancedBaseVertex()    (GL)
2348 			 *    or glDrawElementsInstancedBaseVertexEXT() (ES)
2349 			 * d)    glMultiDrawElementsBaseVertex()        (GL)
2350 			 *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
2351 			 **/
2352 			for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
2353 			{
2354 				/* Iterate over all basevertex values */
2355 				for (unsigned int n_basevertex_value = 0; n_basevertex_value < n_basevertex_values;
2356 					 ++n_basevertex_value)
2357 				{
2358 
2359 					/* Iterate over all GS+(TC & TE) stage combinations */
2360 					for (unsigned int n_stage_combination = 0; n_stage_combination < 4; ++n_stage_combination)
2361 					{
2362 						bool should_include_gs	= (n_stage_combination & 1) != 0;
2363 						bool should_include_tc_te = (n_stage_combination & 2) != 0;
2364 
2365 						/* Skip iterations, for which we'd need to use extensions not supported
2366 						 * by the running implementation */
2367 						if (should_include_gs && !m_is_geometry_shader_supported)
2368 						{
2369 							continue;
2370 						}
2371 
2372 						if (should_include_tc_te && !m_is_tessellation_shader_supported)
2373 						{
2374 							continue;
2375 						}
2376 
2377 						/* Do not try to use the multi draw call if relevant extension is
2378 						 * not supported. */
2379 						if (!m_is_ext_multi_draw_arrays_supported &&
2380 							n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
2381 						{
2382 							continue;
2383 						}
2384 
2385 						/* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
2386 						const glw::GLsizei multi_draw_call_count_array[3]   = { 3, 6, 3 };
2387 						const glw::GLuint* multi_draw_call_indices_array[3] = {
2388 							(glw::GLuint*)(current_index_offset), (glw::GLuint*)(current_index_offset + 3),
2389 							(glw::GLuint*)(current_index_offset + 9)
2390 						};
2391 
2392 						/* Reference texture should always reflect basevertex=10 behavior. */
2393 						const glw::GLuint  regular_draw_call_offset					 = basevertex_values[0];
2394 						const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
2395 							multi_draw_call_indices_array[0] + regular_draw_call_offset,
2396 							multi_draw_call_indices_array[1] + regular_draw_call_offset,
2397 							multi_draw_call_indices_array[2] + regular_draw_call_offset,
2398 						};
2399 
2400 						/* Construct the test case descriptor */
2401 						_test_case new_test_case;
2402 
2403 						new_test_case.basevertex			   = basevertex_values[n_basevertex_value];
2404 						new_test_case.function_type			   = (_function_type)n_function;
2405 						new_test_case.index_offset			   = current_index_offset;
2406 						new_test_case.range_start			   = n_index_offset == 0 ? 0 : 10;
2407 						new_test_case.range_end				   = n_index_offset == 0 ? 22 : 32;
2408 						new_test_case.index_type			   = GL_UNSIGNED_INT;
2409 						new_test_case.primitive_mode		   = (should_include_tc_te) ? GL_PATCHES : GL_TRIANGLES;
2410 						new_test_case.regular_draw_call_offset = regular_draw_call_offset;
2411 						new_test_case.should_base_texture_match_reference_texture =
2412 							((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
2413 						new_test_case.use_clientside_index_data		= use_clientside_index_data;
2414 						new_test_case.use_clientside_vertex_data	= use_clientside_vertex_data;
2415 						new_test_case.use_geometry_shader_stage		= should_include_gs;
2416 						new_test_case.use_tessellation_shader_stage = should_include_tc_te;
2417 						new_test_case.use_vertex_attrib_binding		= false;
2418 
2419 						memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
2420 							   sizeof(multi_draw_call_count_array));
2421 						memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
2422 							   sizeof(multi_draw_call_indices_array));
2423 						memcpy(new_test_case.regular_multi_draw_call_offseted_array,
2424 							   regular_multi_draw_call_offseted_array, sizeof(regular_multi_draw_call_offseted_array));
2425 
2426 						m_test_cases.push_back(new_test_case);
2427 					} /* for (all shader stage combinations) */
2428 				}	 /* for (all basevertex values) */
2429 			}		  /* for (all four functions) */
2430 		}			  /* for (all index data sets) */
2431 	}				  /* for (all VAO iterations) */
2432 }
2433 
2434 /** Executes test iteration.
2435  *
2436  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2437  */
iterate()2438 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::iterate()
2439 {
2440 	/* This test should not be run on implementations that don't support both tessellation and geometry
2441 	 * shader stages
2442 	 */
2443 	if (!m_is_geometry_shader_supported && !m_is_tessellation_shader_supported)
2444 	{
2445 		throw tcu::NotSupportedError("Geometry shader and tessellation shader functionality is not supported");
2446 	}
2447 
2448 	setUpTestCases();
2449 	executeTestCases();
2450 
2451 	/* Test case passed */
2452 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2453 
2454 	return STOP;
2455 }
2456 
2457 /** Constructor.
2458  *
2459  *  @param context Rendering context handle.
2460  **/
DrawElementsBaseVertexNegativeActiveTransformFeedbackTest(Context & context,const ExtParameters & extParams)2461 DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::DrawElementsBaseVertexNegativeActiveTransformFeedbackTest(
2462 	Context& context, const ExtParameters& extParams)
2463 	: DrawElementsBaseVertexTestBase(context, extParams, "valid_active_tf",
2464 									 "Tries to do \"base vertex\" draw calls while Transform Feedback is active")
2465 	, m_bo_tf_result_id(0)
2466 {
2467 	/* Left blank on purpose */
2468 }
2469 
2470 /** Deinitializes all ES objects per test case if test fails and exit through exception path */
deinit()2471 void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::deinit()
2472 {
2473 	deinitPerTestObjects();
2474 }
2475 
2476 /** Deinitializes all ES objects that may have been created by the test */
deinitPerTestObjects()2477 void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::deinitPerTestObjects()
2478 {
2479 	/* Call the base class' deinitPerTestObjects() first. */
2480 	DrawElementsBaseVertexTestBase::deinitPerTestObjects();
2481 
2482 	/* Proceed with internal deinitialization */
2483 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2484 
2485 	if (m_bo_tf_result_id != 0)
2486 	{
2487 		gl.deleteBuffers(1, &m_bo_tf_result_id);
2488 
2489 		m_bo_tf_result_id = 0;
2490 	}
2491 }
2492 
2493 /** Initializes all ES objects used by the test. */
init()2494 void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::init()
2495 {
2496 	/* Call the base class' init() first. */
2497 	DrawElementsBaseVertexTestBase::init();
2498 
2499 	/* Proceed with internal initialization */
2500 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2501 
2502 	gl.genBuffers(1, &m_bo_tf_result_id);
2503 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
2504 
2505 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_tf_result_id);
2506 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
2507 
2508 	gl.bufferData(GL_ARRAY_BUFFER, 3 /* count */ * sizeof(float) * 4 /* components used by gl_Position */,
2509 				  DE_NULL, /* data */
2510 				  GL_STATIC_DRAW);
2511 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2512 
2513 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
2514 					  m_bo_tf_result_id);
2515 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
2516 }
2517 
2518 /** Executes test iteration.
2519  *
2520  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2521  */
iterate()2522 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::iterate()
2523 {
2524 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2525 
2526 	/* this test doesn't apply to OpenGL contexts */
2527 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2528 	{
2529 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
2530 		return STOP;
2531 	}
2532 
2533 	/* Set up the work environment */
2534 	setUpNegativeTestObjects(false,  /* use_clientside_vertex_data */
2535 							 false); /* use_clientside_index_data */
2536 
2537 	/* Kick off transform feedback */
2538 	gl.beginTransformFeedback(GL_TRIANGLES);
2539 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2540 
2541 	/* Try to perform indiced draw calls which are invalid when TF is active.
2542 	 */
2543 	glw::GLenum error_code = GL_NONE;
2544 
2545 	gl.drawElementsBaseVertex(GL_TRIANGLES, 3,								 /* count */
2546 							  GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
2547 
2548 	error_code = gl.getError();
2549 
2550 	/* The error for using DrawElements* commands while transform feedback is
2551 	 active is lifted in OES/EXT_geometry_shader. See issue 13 in the spec.
2552 	 */
2553 	glw::GLenum expected_error_code = m_is_geometry_shader_supported ? GL_NO_ERROR : GL_INVALID_OPERATION;
2554 
2555 	if (error_code != expected_error_code)
2556 	{
2557 		std::stringstream error_sstream;
2558 
2559 		error_sstream << "Invalid error code generated by " << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX);
2560 
2561 		m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX)
2562 						   << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2563 						   << tcu::TestLog::EndMessage;
2564 
2565 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2566 
2567 		goto end;
2568 	}
2569 
2570 	gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, 3,								 /* count */
2571 									   GL_UNSIGNED_INT, m_draw_call_index_offset, 1, /* instancecount */
2572 									   0);											 /* basevertex */
2573 
2574 	error_code = gl.getError();
2575 	if (error_code != expected_error_code)
2576 	{
2577 		std::stringstream error_sstream;
2578 
2579 		error_sstream << "Invalid error code generated by "
2580 					  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX);
2581 
2582 		m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX)
2583 						   << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2584 						   << tcu::TestLog::EndMessage;
2585 
2586 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2587 
2588 		goto end;
2589 	}
2590 
2591 	gl.drawRangeElementsBaseVertex(GL_TRIANGLES, 0, 2,							  /* end */
2592 								   3,											  /* count */
2593 								   GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
2594 
2595 	error_code = gl.getError();
2596 	if (error_code != expected_error_code)
2597 	{
2598 		std::stringstream error_sstream;
2599 
2600 		error_sstream << "Invalid error code generated by "
2601 					  << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX);
2602 
2603 		m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX)
2604 						   << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2605 						   << tcu::TestLog::EndMessage;
2606 
2607 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2608 
2609 		goto end;
2610 	}
2611 
2612 	/* Test case passed */
2613 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2614 
2615 end:
2616 	gl.endTransformFeedback();
2617 	return STOP;
2618 }
2619 
2620 /** Constructor.
2621  *
2622  *  @param context Rendering context handle.
2623  **/
DrawElementsBaseVertexNegativeInvalidCountArgumentTest(Context & context,const ExtParameters & extParams)2624 DrawElementsBaseVertexNegativeInvalidCountArgumentTest::DrawElementsBaseVertexNegativeInvalidCountArgumentTest(
2625 	Context& context, const ExtParameters& extParams)
2626 	: DrawElementsBaseVertexTestBase(context, extParams, "invalid_count_argument",
2627 									 "Tries to use invalid 'count' argument values for the \"base vertex\" draw calls")
2628 {
2629 	/* Left blank on purpose */
2630 }
2631 
2632 /** Executes test iteration.
2633  *
2634  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2635  */
iterate()2636 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidCountArgumentTest::iterate()
2637 {
2638 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2639 
2640 	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
2641 	 * in a slightly different manner.
2642 	 */
2643 	for (int iteration = 0; iteration < 4; ++iteration)
2644 	{
2645 		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
2646 		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2647 
2648 		/* OpenGL does not support client-side data. */
2649 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2650 		{
2651 			if (use_clientside_index_data || use_clientside_vertex_data)
2652 			{
2653 				continue;
2654 			}
2655 		}
2656 
2657 		/* Set up the work environment */
2658 		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2659 
2660 		/* Try to execute the invalid draw calls */
2661 		glw::GLenum error_code = GL_NONE;
2662 
2663 		gl.drawElementsBaseVertex(GL_TRIANGLES, -1,													 /* count */
2664 								  GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
2665 
2666 		error_code = gl.getError();
2667 		if (error_code != GL_INVALID_VALUE)
2668 		{
2669 			std::stringstream error_sstream;
2670 
2671 			error_sstream << "Invalid error code reported for an invalid "
2672 						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2673 
2674 			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2675 							   << ": expected GL_INVALID_VALUE, got:"
2676 								  "["
2677 							   << error_code << "]" << tcu::TestLog::EndMessage;
2678 
2679 			TCU_FAIL(error_sstream.str().c_str());
2680 		}
2681 
2682 		gl.drawRangeElementsBaseVertex(GL_TRIANGLES, /* mode */
2683 									   -1,			 /* start */
2684 									   2,			 /* end */
2685 									   1,			 /* count */
2686 									   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2687 									   0); /* basevertex */
2688 
2689 		error_code = gl.getError();
2690 		if (error_code != GL_INVALID_VALUE)
2691 		{
2692 			std::stringstream error_sstream;
2693 
2694 			error_sstream << "Invalid error code reported for an invalid "
2695 						  << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
2696 
2697 			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2698 							   << ": expected GL_INVALID_VALUE, got:"
2699 								  "["
2700 							   << error_code << "]" << tcu::TestLog::EndMessage;
2701 
2702 			TCU_FAIL(error_sstream.str().c_str());
2703 		}
2704 
2705 		gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, /* mode */
2706 										   -1,			 /* count */
2707 										   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2708 										   1,  /* instancecount */
2709 										   0); /* basevertex */
2710 
2711 		error_code = gl.getError();
2712 		if (error_code != GL_INVALID_VALUE)
2713 		{
2714 			std::stringstream error_sstream;
2715 
2716 			error_sstream << "Invalid error code reported for an invalid "
2717 						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2718 
2719 			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2720 							   << ": expected GL_INVALID_VALUE, got:"
2721 								  "["
2722 							   << error_code << "]" << tcu::TestLog::EndMessage;
2723 
2724 			TCU_FAIL(error_sstream.str().c_str());
2725 		}
2726 
2727 		if (m_is_ext_multi_draw_arrays_supported)
2728 		{
2729 			const glw::GLsizei count	 = -1;
2730 			const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
2731 
2732 			gl.multiDrawElementsBaseVertex(GL_TRIANGLES,						/* mode */
2733 										   &count, GL_UNSIGNED_INT, offsets, 1, /* primcount */
2734 										   0);									/* basevertex */
2735 
2736 			error_code = gl.getError();
2737 			if (error_code != GL_INVALID_VALUE)
2738 			{
2739 				std::stringstream error_sstream;
2740 
2741 				error_sstream << "Invalid error code reported for an invalid "
2742 							  << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2743 
2744 				m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2745 								   << ": expected GL_INVALID_VALUE, got:"
2746 									  "["
2747 								   << error_code << "]" << tcu::TestLog::EndMessage;
2748 
2749 				TCU_FAIL("Invalid error code reported for an invalid glMultiDrawElementsBaseVertexEXT() call.");
2750 			}
2751 		} /* if (m_is_ext_multi_draw_arrays_supported) */
2752 	}	 /* for (all iterations) */
2753 
2754 	/* Test case passed */
2755 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2756 
2757 	return STOP;
2758 }
2759 
2760 /** Constructor.
2761  *
2762  *  @param context Rendering context handle.
2763  **/
2764 DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest::
DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest(Context & context,const ExtParameters & extParams)2765 	DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest(Context& context, const ExtParameters& extParams)
2766 	: DrawElementsBaseVertexTestBase(context, extParams, "invalid_instancecount_argument",
2767 									 "Tries to use invalid 'instancecount' argument values for "
2768 									 "glDrawElementsInstancedBaseVertexEXT (ES) or "
2769 									 "glDrawElementsInstancedBaseVertex (GL) draw call")
2770 {
2771 	/* Left blank on purpose */
2772 }
2773 
2774 /** Executes test iteration.
2775  *
2776  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2777  */
iterate()2778 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest::iterate()
2779 {
2780 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2781 
2782 	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
2783 	 * in a slightly different manner.
2784 	 */
2785 	for (int iteration = 0; iteration < 4; ++iteration)
2786 	{
2787 		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
2788 		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2789 
2790 		/* OpenGL does not support client-side data. */
2791 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2792 		{
2793 			if (use_clientside_index_data || use_clientside_vertex_data)
2794 			{
2795 				continue;
2796 			}
2797 		}
2798 
2799 		/* Set up the work environment */
2800 		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2801 
2802 		/* Try to execute the invalid draw call */
2803 		glw::GLenum error_code = GL_NONE;
2804 
2805 		gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, /* mode */
2806 										   3,			 /* count */
2807 										   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2808 										   -1, /* instancecount */
2809 										   0); /* basevertex */
2810 
2811 		error_code = gl.getError();
2812 		if (error_code != GL_INVALID_VALUE)
2813 		{
2814 			std::stringstream error_sstream;
2815 
2816 			error_sstream << "Invalid error code reported for an invalid "
2817 						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2818 
2819 			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2820 							   << ": expected GL_INVALID_VALUE, got:"
2821 								  "["
2822 							   << error_code << "]" << tcu::TestLog::EndMessage;
2823 
2824 			TCU_FAIL(error_sstream.str().c_str());
2825 		}
2826 	} /* for (all test iterations) */
2827 
2828 	/* Test case passed */
2829 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2830 
2831 	return STOP;
2832 }
2833 
2834 /** Constructor.
2835  *
2836  *  @param context Rendering context handle.
2837  **/
DrawElementsBaseVertexNegativeInvalidModeArgumentTest(Context & context,const ExtParameters & extParams)2838 DrawElementsBaseVertexNegativeInvalidModeArgumentTest::DrawElementsBaseVertexNegativeInvalidModeArgumentTest(
2839 	Context& context, const ExtParameters& extParams)
2840 	: DrawElementsBaseVertexTestBase(context, extParams, "invalid_mode_argument",
2841 									 "Tries to use invalid 'mode' argument values for the \"base vertex\" draw calls")
2842 {
2843 	/* Left blank on purpose */
2844 }
2845 
2846 /** Executes test iteration.
2847  *
2848  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2849  */
iterate()2850 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidModeArgumentTest::iterate()
2851 {
2852 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2853 
2854 	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
2855 	 * in a slightly different manner.
2856 	 */
2857 	for (int iteration = 0; iteration < 4; ++iteration)
2858 	{
2859 		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
2860 		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2861 
2862 		/* OpenGL does not support client-side data. */
2863 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2864 		{
2865 			if (use_clientside_index_data || use_clientside_vertex_data)
2866 			{
2867 				continue;
2868 			}
2869 		}
2870 
2871 		/* Set up the work environment */
2872 		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2873 
2874 		/* Try to execute the invalid draw calls */
2875 		glw::GLenum error_code = GL_NONE;
2876 
2877 		gl.drawElementsBaseVertex(GL_GREATER,														 /* mode */
2878 								  3,																 /* count */
2879 								  GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
2880 
2881 		error_code = gl.getError();
2882 		if (error_code != GL_INVALID_ENUM)
2883 		{
2884 			std::stringstream error_sstream;
2885 
2886 			error_sstream << "Invalid error code reported for an invalid "
2887 						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2888 
2889 			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2890 							   << ": expected GL_INVALID_ENUM, got:"
2891 								  "["
2892 							   << error_code << "]" << tcu::TestLog::EndMessage;
2893 
2894 			TCU_FAIL(error_sstream.str().c_str());
2895 		}
2896 
2897 		gl.drawRangeElementsBaseVertex(GL_GREATER, /* mode */
2898 									   0,		   /* start */
2899 									   2,		   /* end */
2900 									   3,		   /* count */
2901 									   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2902 									   0); /* basevertex */
2903 
2904 		error_code = gl.getError();
2905 		if (error_code != GL_INVALID_ENUM)
2906 		{
2907 			std::stringstream error_sstream;
2908 
2909 			error_sstream << "Invalid error code reported for an invalid "
2910 						  << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
2911 
2912 			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2913 							   << ": expected GL_INVALID_ENUM, got:"
2914 								  "["
2915 							   << error_code << "]" << tcu::TestLog::EndMessage;
2916 
2917 			TCU_FAIL(error_sstream.str().c_str());
2918 		}
2919 
2920 		gl.drawElementsInstancedBaseVertex(GL_GREATER, /* mode */
2921 										   3,		   /* count */
2922 										   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2923 										   1,  /* instancecount */
2924 										   0); /* basevertex */
2925 
2926 		error_code = gl.getError();
2927 		if (error_code != GL_INVALID_ENUM)
2928 		{
2929 			std::stringstream error_sstream;
2930 
2931 			error_sstream << "Invalid error code reported for an invalid "
2932 						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2933 
2934 			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2935 							   << ": expected GL_INVALID_ENUM, got:"
2936 								  "["
2937 							   << error_code << "]" << tcu::TestLog::EndMessage;
2938 
2939 			TCU_FAIL(error_sstream.str().c_str());
2940 		}
2941 
2942 		if (m_is_ext_multi_draw_arrays_supported)
2943 		{
2944 			const glw::GLsizei count	 = 3;
2945 			const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
2946 
2947 			gl.multiDrawElementsBaseVertex(GL_GREATER,							/* mode */
2948 										   &count, GL_UNSIGNED_INT, offsets, 1, /* primcount */
2949 										   0);									/* basevertex */
2950 
2951 			error_code = gl.getError();
2952 			if (error_code != GL_INVALID_ENUM)
2953 			{
2954 				std::stringstream error_sstream;
2955 
2956 				error_sstream << "Invalid error code reported for an invalid "
2957 							  << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2958 
2959 				m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2960 								   << ": expected GL_INVALID_ENUM, got:"
2961 									  "["
2962 								   << error_code << "]" << tcu::TestLog::EndMessage;
2963 
2964 				TCU_FAIL(error_sstream.str().c_str());
2965 			}
2966 		} /* if (m_is_ext_multi_draw_arrays_supported) */
2967 	}	 /* for (all test iterations) */
2968 
2969 	/* Test case passed */
2970 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2971 
2972 	return STOP;
2973 }
2974 
2975 /** Constructor.
2976  *
2977  *  @param context Rendering context handle.
2978  **/
DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest(Context & context,const ExtParameters & extParams)2979 DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest::DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest(
2980 	Context& context, const ExtParameters& extParams)
2981 	: DrawElementsBaseVertexTestBase(
2982 		  context, extParams, "invalid_primcount_argument",
2983 		  "Tries to use invalid 'primcount' argument values for the \"base vertex\" draw calls")
2984 {
2985 	/* Left blank on purpose */
2986 }
2987 
2988 /** Executes test iteration.
2989  *
2990  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2991  */
iterate()2992 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest::iterate()
2993 {
2994 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2995 
2996 	/* This test requires presence of GL_EXT_multi_draw_arrays under ES contexts */
2997 	if (glu::isContextTypeES(m_context.getRenderContext().getType()))
2998 	{
2999 		if (!m_is_ext_multi_draw_arrays_supported)
3000 		{
3001 			throw tcu::NotSupportedError("GL_EXT_multi_draw_arrays is not supported");
3002 		}
3003 	}
3004 
3005 	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
3006 	 * in a slightly different manner.
3007 	 */
3008 	for (int iteration = 0; iteration < 4; ++iteration)
3009 	{
3010 		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
3011 		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3012 
3013 		/* OpenGL does not support client-side data. */
3014 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3015 		{
3016 			if (use_clientside_index_data || use_clientside_vertex_data)
3017 			{
3018 				continue;
3019 			}
3020 		}
3021 
3022 		/* Set up the work environment */
3023 		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3024 
3025 		/* Perform the test */
3026 		const glw::GLsizei count	  = 3;
3027 		glw::GLenum		   error_code = GL_NO_ERROR;
3028 		const glw::GLvoid* offsets[]  = { (const glw::GLvoid*)m_draw_call_index_offset };
3029 
3030 		gl.multiDrawElementsBaseVertex(GL_TRIANGLES,						 /* mode */
3031 									   &count, GL_UNSIGNED_INT, offsets, -1, /* primcount */
3032 									   0);									 /* basevertex */
3033 
3034 		error_code = gl.getError();
3035 		if (error_code != GL_INVALID_VALUE)
3036 		{
3037 			std::stringstream error_sstream;
3038 
3039 			error_sstream << "Invalid error code reported for an invalid "
3040 						  << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3041 
3042 			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3043 							   << ": expected GL_INVALID_VALUE, got:"
3044 								  "["
3045 							   << error_code << "]" << tcu::TestLog::EndMessage;
3046 
3047 			TCU_FAIL(error_sstream.str().c_str());
3048 		}
3049 	} /* for (all test iterations) */
3050 
3051 	/* Test case passed */
3052 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3053 
3054 	return STOP;
3055 }
3056 
3057 /** Constructor.
3058  *
3059  *  @param context Rendering context handle.
3060  **/
DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest(Context & context,const ExtParameters & extParams)3061 DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest::DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest(
3062 	Context& context, const ExtParameters& extParams)
3063 	: DrawElementsBaseVertexTestBase(context, extParams, "invalid_start_end_arguments",
3064 									 "Tries to use invalid 'start' and 'end' argument values for the "
3065 									 "glDrawRangeElementsBaseVertexEXT() (under ES) or "
3066 									 "glDrawRangeElementsBaseVertex() (under GL) draw call")
3067 {
3068 	/* Left blank on purpose */
3069 }
3070 
3071 /** Executes test iteration.
3072  *
3073  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3074  */
iterate()3075 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest::iterate()
3076 {
3077 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3078 
3079 	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
3080 	 * in a slightly different manner.
3081 	 */
3082 	for (int iteration = 0; iteration < 4; ++iteration)
3083 	{
3084 		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
3085 		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3086 
3087 		/* OpenGL does not support client-side data. */
3088 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3089 		{
3090 			if (use_clientside_index_data || use_clientside_vertex_data)
3091 			{
3092 				continue;
3093 			}
3094 		}
3095 
3096 		/* Set up the work environment */
3097 		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3098 
3099 		/* Try to execute the invalid draw call */
3100 		glw::GLenum error_code = GL_NONE;
3101 
3102 		gl.drawRangeElementsBaseVertex(GL_TRIANGLES, /* mode */
3103 									   3,			 /* start */
3104 									   0,			 /* end */
3105 									   3,			 /* count */
3106 									   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
3107 									   0); /* basevertex */
3108 
3109 		error_code = gl.getError();
3110 		if (error_code != GL_INVALID_VALUE)
3111 		{
3112 			std::stringstream error_sstream;
3113 
3114 			error_sstream << "Invalid error code reported for an invalid "
3115 						  << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
3116 
3117 			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3118 							   << ": expected GL_INVALID_VALUE, got:"
3119 								  "["
3120 							   << error_code << "]" << tcu::TestLog::EndMessage;
3121 
3122 			TCU_FAIL(error_sstream.str().c_str());
3123 		}
3124 	} /* for (all test iterations) */
3125 
3126 	/* Test case passed */
3127 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3128 
3129 	return STOP;
3130 }
3131 
3132 /** Constructor.
3133  *
3134  *  @param context Rendering context handle.
3135  **/
DrawElementsBaseVertexNegativeInvalidTypeArgumentTest(Context & context,const ExtParameters & extParams)3136 DrawElementsBaseVertexNegativeInvalidTypeArgumentTest::DrawElementsBaseVertexNegativeInvalidTypeArgumentTest(
3137 	Context& context, const ExtParameters& extParams)
3138 	: DrawElementsBaseVertexTestBase(context, extParams, "invalid_type_argument",
3139 									 "Tries to use invalid 'type' argument values for the \"base vertex\" draw calls")
3140 {
3141 	/* Left blank on purpose */
3142 }
3143 
3144 /** Executes test iteration.
3145  *
3146  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3147  */
iterate()3148 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidTypeArgumentTest::iterate()
3149 {
3150 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3151 
3152 	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
3153 	 * in a slightly different manner.
3154 	 */
3155 	for (int iteration = 0; iteration < 4; ++iteration)
3156 	{
3157 		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
3158 		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3159 
3160 		/* OpenGL does not support client-side data. */
3161 		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3162 		{
3163 			if (use_clientside_index_data || use_clientside_vertex_data)
3164 			{
3165 				continue;
3166 			}
3167 		}
3168 
3169 		/* Set up the work environment */
3170 		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3171 
3172 		/* Try to execute the invalid draw calls */
3173 		glw::GLenum error_code = GL_NONE;
3174 
3175 		gl.drawElementsBaseVertex(GL_TRIANGLES,												 /* mode */
3176 								  3,														 /* count */
3177 								  GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
3178 
3179 		error_code = gl.getError();
3180 		if (error_code != GL_INVALID_ENUM)
3181 		{
3182 			std::stringstream error_sstream;
3183 
3184 			error_sstream << "Invalid error code reported for an invalid "
3185 						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3186 
3187 			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3188 							   << ": expected GL_INVALID_ENUM, got:"
3189 								  "["
3190 							   << error_code << "]" << tcu::TestLog::EndMessage;
3191 
3192 			TCU_FAIL(error_sstream.str().c_str());
3193 		}
3194 
3195 		gl.drawRangeElementsBaseVertex(GL_TRIANGLES,											  /* mode */
3196 									   0,														  /* start */
3197 									   2,														  /* end */
3198 									   3,														  /* count */
3199 									   GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
3200 
3201 		error_code = gl.getError();
3202 		if (error_code != GL_INVALID_ENUM)
3203 		{
3204 			std::stringstream error_sstream;
3205 
3206 			error_sstream << "Invalid error code reported for an invalid "
3207 						  << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
3208 
3209 			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3210 							   << ": expected GL_INVALID_ENUM, got:"
3211 								  "["
3212 							   << error_code << "]" << tcu::TestLog::EndMessage;
3213 
3214 			TCU_FAIL(error_sstream.str().c_str());
3215 		}
3216 
3217 		gl.drawElementsInstancedBaseVertex(GL_TRIANGLES,											 /* mode */
3218 										   3,														 /* count */
3219 										   GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 1, /* instancecount */
3220 										   0);														 /* basevertex */
3221 
3222 		error_code = gl.getError();
3223 		if (error_code != GL_INVALID_ENUM)
3224 		{
3225 			std::stringstream error_sstream;
3226 
3227 			error_sstream << "Invalid error code reported for an invalid "
3228 						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
3229 
3230 			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3231 							   << ": expected GL_INVALID_ENUM, got:"
3232 								  "["
3233 							   << error_code << "]" << tcu::TestLog::EndMessage;
3234 
3235 			TCU_FAIL(error_sstream.str().c_str());
3236 		}
3237 
3238 		if (m_is_ext_multi_draw_arrays_supported)
3239 		{
3240 			const glw::GLsizei count	 = 3;
3241 			const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
3242 
3243 			gl.multiDrawElementsBaseVertex(GL_TRIANGLES,				/* mode */
3244 										   &count, GL_NONE, offsets, 1, /* primcount */
3245 										   0);							/* basevertex */
3246 
3247 			error_code = gl.getError();
3248 			if (error_code != GL_INVALID_ENUM)
3249 			{
3250 				std::stringstream error_sstream;
3251 
3252 				error_sstream << "Invalid error code reported for an invalid "
3253 							  << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3254 
3255 				m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3256 								   << ": expected GL_INVALID_ENUM, got:"
3257 									  "["
3258 								   << error_code << "]" << tcu::TestLog::EndMessage;
3259 
3260 				TCU_FAIL(error_sstream.str().c_str());
3261 			}
3262 		} /* if (m_is_ext_multi_draw_arrays_supported) */
3263 	}	 /* for (all test iterations) */
3264 
3265 	/* Test case passed */
3266 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3267 
3268 	return STOP;
3269 }
3270 
3271 /** Constructor.
3272  *
3273  *  @param context Rendering context.
3274  */
DrawElementsBaseVertexTests(glcts::Context & context,const ExtParameters & extParams)3275 DrawElementsBaseVertexTests::DrawElementsBaseVertexTests(glcts::Context& context, const ExtParameters& extParams)
3276 	: TestCaseGroupBase(context, extParams, "draw_elements_base_vertex_tests",
3277 						"Contains conformance tests that verify ES and GL implementation's support "
3278 						"for GL_EXT_draw_elements_base_vertex (ES) and "
3279 						"GL_ARB_draw_elements_base_vertex (GL) extensions.")
3280 {
3281 }
3282 
3283 /** Initializes the test group contents. */
init()3284 void DrawElementsBaseVertexTests::init()
3285 {
3286 	addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior(m_context, m_extParams));
3287 	addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2(m_context, m_extParams));
3288 	addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages(m_context, m_extParams));
3289 	addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow(m_context, m_extParams));
3290 	addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow(m_context, m_extParams));
3291 	addChild(new DrawElementsBaseVertexNegativeActiveTransformFeedbackTest(m_context, m_extParams));
3292 	addChild(new DrawElementsBaseVertexNegativeInvalidCountArgumentTest(m_context, m_extParams));
3293 	addChild(new DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest(m_context, m_extParams));
3294 	addChild(new DrawElementsBaseVertexNegativeInvalidModeArgumentTest(m_context, m_extParams));
3295 	addChild(new DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest(m_context, m_extParams));
3296 	addChild(new DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest(m_context, m_extParams));
3297 	addChild(new DrawElementsBaseVertexNegativeInvalidTypeArgumentTest(m_context, m_extParams));
3298 }
3299 
3300 } /* glcts namespace */
3301