1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 */ /*-------------------------------------------------------------------*/
26 * \file esextcDrawElementsBaseVertexTests.cpp
27 * \brief Implements conformance tests for "draw elements base vertex" functionality
29 */ /*-------------------------------------------------------------------*/
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"
46 * @param context Rendering context
47 * @param name Test name
48 * @param description Test 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)
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)
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)
87 , m_to_base_data(DE_NULL)
88 , m_to_ref_data(DE_NULL)
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 */
112 257, // regular draw call indices for ubyte ref image
124 65537, // regular draw call indices for ushort ref image
136 0, // regular draw call indices for uint ref image
148 static const glw::GLfloat functional_color_data[] = /* used for "vertex attrib binding" Functional Test */
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,
155 static const glw::GLfloat functional_vertex_data[] = /* used by a number of Functional Tests */
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,
163 static const glw::GLfloat functional2_vertex_data[] = /* used by a number of Functional Tests */
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,
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 };
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);
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.
200 * If the compilation process or the linking process fails for any reason,
201 * the method throws a TestError exception.
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.
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.
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)
219 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
221 /* Create program & shader objects */
222 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
223 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
225 if (tc_code != DE_NULL)
227 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
230 if (te_code != DE_NULL)
232 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
235 if (gs_code != DE_NULL)
237 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
240 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
242 m_po_id = gl.createProgram();
243 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
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 */
253 gl.shaderSource(m_tc_id, 1, /* count */
254 &tc_code, DE_NULL); /* length */
259 gl.shaderSource(m_te_id, 1, /* count */
260 &te_code, DE_NULL); /* length */
265 gl.shaderSource(m_gs_id, 1, /* count */
266 &gs_code, DE_NULL); /* length */
269 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
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]);
275 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
277 glw::GLint compile_status = GL_FALSE;
278 glw::GLuint so_id = so_ids[n_so_id];
282 gl.compileShader(so_id);
283 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
285 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
286 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
288 if (compile_status == GL_FALSE)
290 TCU_FAIL("Shader compilation failed");
291 } /* if (compile_status == GL_FALSE) */
292 } /* if (so_id != 0) */
293 } /* for (all shader objects) */
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);
301 gl.attachShader(m_po_id, m_tc_id);
306 gl.attachShader(m_po_id, m_te_id);
311 gl.attachShader(m_po_id, m_gs_id);
314 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
317 const glw::GLchar* tf_varyings[] = { "gl_Position" };
319 gl.transformFeedbackVaryings(m_po_id, 1, /* count */
320 tf_varyings, GL_SEPARATE_ATTRIBS);
321 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
323 /* Try to link the program object */
324 glw::GLint link_status = GL_FALSE;
326 gl.linkProgram(m_po_id);
327 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
329 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
330 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
332 if (link_status == GL_FALSE)
334 TCU_FAIL("Program linking failed.");
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");
342 DE_ASSERT(m_po_vertex_attribute_location != -1);
345 /** Verifies contents of the base & reference textures. This method can work
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.
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.
358 * @param should_be_equal Please see description for more details.
360 void DrawElementsBaseVertexTestBase::compareBaseAndReferenceTextures(bool should_be_equal)
362 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
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.");
368 gl.readPixels(0, /* x */
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.");
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 */
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.");
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;
388 for (unsigned int n_texel = 0; n_texel < n_texels; ++n_texel)
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)
394 all_base_rgb_texels_zero = false;
397 if (ref_data_ptr[0] != 0 || ref_data_ptr[1] != 0 || ref_data_ptr[2] != 0)
399 all_reference_rgb_texels_zero = false;
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])
407 const unsigned int y = n_texel / m_to_width;
408 const unsigned int x = n_texel % m_to_width;
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]
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;
419 TCU_FAIL("Pixel mismatch");
423 /* Base and reference textures are *not* identical. */
424 textures_identical = false;
428 base_data_ptr += 4; /* components */
429 ref_data_ptr += 4; /* components */
430 } /* for (all texels) */
432 if (all_base_rgb_texels_zero)
434 TCU_FAIL("Draw call used to render contents of the base texture did not change the texture");
437 if (all_reference_rgb_texels_zero)
439 TCU_FAIL("Draw call used to render contents of the reference texture did not change the texture");
442 if (!should_be_equal && textures_identical)
444 TCU_FAIL("Textures are a match, even though they should not be identical.");
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.
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
457 void DrawElementsBaseVertexTestBase::computeVBODataOffsets(bool use_clientside_index_data,
458 bool use_clientside_vertex_data)
460 if (use_clientside_index_data)
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;
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
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);
488 if (use_clientside_vertex_data)
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;
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;
506 void DrawElementsBaseVertexTestBase::deinit()
508 /* TCU_FAIL will skip the per test object de-initialization, we need to
509 * take care of it here
511 deinitPerTestObjects();
514 /** Deinitializes all ES objects created by the test. */
515 void DrawElementsBaseVertexTestBase::deinitPerTestObjects()
517 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
519 deinitProgramAndShaderObjects();
523 gl.deleteBuffers(1, &m_bo_id);
530 gl.deleteBuffers(1, &m_bo_id_2);
537 gl.deleteFramebuffers(1, &m_fbo_id);
542 if (m_to_base_data != DE_NULL)
544 delete[] m_to_base_data;
546 m_to_base_data = DE_NULL;
549 if (m_to_base_id != 0)
551 gl.deleteTextures(1, &m_to_base_id);
556 if (m_to_ref_data != DE_NULL)
558 delete[] m_to_ref_data;
560 m_to_ref_data = DE_NULL;
563 if (m_to_ref_id != 0)
565 gl.deleteTextures(1, &m_to_ref_id);
572 gl.deleteVertexArrays(1, &m_vao_id);
579 gl.deleteShader(m_vs_id);
584 /* Restore the default GL_PACK_ALIGNMENT setting */
585 gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
588 /** Deinitializes all program & shader objects that may have been initialized
591 void DrawElementsBaseVertexTestBase::deinitProgramAndShaderObjects()
593 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
597 gl.deleteShader(m_fs_id);
604 gl.deleteShader(m_gs_id);
611 gl.deleteProgram(m_po_id);
618 gl.deleteShader(m_tc_id);
625 gl.deleteShader(m_te_id);
631 /** Executes all test cases stored in m_test_cases.
633 * This method throws a TestError exception upon test failure.
635 void DrawElementsBaseVertexTestBase::executeTestCases()
637 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
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)
643 const _test_case& test_case = *test_cases_iterator;
645 /* What is the size of a single index value? */
646 unsigned int index_size = 0;
648 switch (test_case.index_type)
650 case GL_UNSIGNED_BYTE:
653 case GL_UNSIGNED_SHORT:
656 case GL_UNSIGNED_INT:
662 TCU_FAIL("Unrecognized index type");
664 } /* switch (test_case.index_type) */
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);
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");
674 gl.clear(GL_COLOR_BUFFER_BIT);
675 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
677 switch (test_case.function_type)
679 case FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX:
681 gl.drawElementsBaseVertex(test_case.primitive_mode, 3, /* count */
682 test_case.index_type, test_case.index_offset, test_case.basevertex);
687 case FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX:
689 gl.drawElementsInstancedBaseVertex(test_case.primitive_mode, 3, /* count */
690 test_case.index_type, test_case.index_offset, 3, /* instancecount */
691 test_case.basevertex);
696 case FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX:
698 gl.drawRangeElementsBaseVertex(test_case.primitive_mode, test_case.range_start, test_case.range_end,
700 test_case.index_type, test_case.index_offset, test_case.basevertex);
705 case FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX:
707 const glw::GLint basevertex_array[] = { test_case.basevertex, test_case.basevertex, test_case.basevertex };
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 */
719 TCU_FAIL("Unsupported function index");
721 } /* switch (n_function) */
723 if (gl.getError() != GL_NO_ERROR)
725 std::stringstream error_sstream;
727 error_sstream << getFunctionName(test_case.function_type) << " call failed";
728 TCU_FAIL(error_sstream.str().c_str());
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");
735 gl.clear(GL_COLOR_BUFFER_BIT);
736 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
738 glw::GLenum regular_draw_call_index_type = test_case.index_type;
739 if (test_case.regular_draw_call_index_type != 0)
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;
744 switch (test_case.regular_draw_call_index_type)
746 case GL_UNSIGNED_BYTE:
749 case GL_UNSIGNED_SHORT:
752 case GL_UNSIGNED_INT:
758 TCU_FAIL("Unrecognized index type");
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)
767 /* Special case for overflow test */
768 regular_draw_call_offset = (glw::GLubyte*)test_case.regular_draw_call_offset2;
771 switch (test_case.function_type)
773 case FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX: /* pass-through */
774 case FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX:
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");
783 case FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX:
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");
792 case FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX:
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.
798 for (unsigned int n_draw_call = 0; n_draw_call < 3; /* drawcount */
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]);
805 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements() call failed.");
813 TCU_FAIL("Unrecognized function index");
815 } /* switch (n_function) */
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
821 compareBaseAndReferenceTextures(test_case.should_base_texture_match_reference_texture);
823 /* ES Resources are allocated per test objects, we need to release them here */
824 deinitPerTestObjects();
825 } /* for (all test cases) */
828 /* Returns name of the function represented by _function_type.
830 * @param function_type Function type to use for the query.
832 * @return As per description, or "[?]" (without the quotation marks)
833 * if @param function_type was not recognized.
835 std::string DrawElementsBaseVertexTestBase::getFunctionName(_function_type function_type)
837 std::string result = "[?]";
839 switch (function_type)
841 case FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX:
843 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
845 result = "glDrawElementsBaseVertexEXT()";
851 result = "glDrawElementsBaseVertex()";
859 case FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX:
861 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
863 result = "glDrawElementsInstancedBaseVertexEXT()";
869 result = "glDrawElementsInstancedBaseVertex()";
877 case FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX:
879 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
881 result = "glDrawRangeElementsBaseVertexEXT()";
887 result = "glDrawRangeElementsBaseVertex()";
895 case FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX:
897 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
899 result = "glMultiDrawElementsBaseVertexEXT()";
905 result = "glMultiDrawElementsBaseVertex()";
915 TCU_FAIL("Unknown function type");
919 } /* switch (function_type) */
924 /** Initializes extension-specific function pointers and caches information about
925 * extension availability.
927 * Function pointers for the following extensions are retrieved & stored:
929 * - GL_EXT_draw_elements_base_vertex (ES) or GL_ARB_draw_elements_base_vertex (GL)
930 * - GL_EXT_multi_draw_arrays (ES & GL)
932 * Availability of the following extensions is checked & cached:
934 * - GL_EXT_draw_elements_base_vertex (ES) or GL_ARB_draw_elements_base_vertex (GL)
935 * - GL_EXT_geometry_shader (ES) or GL_ARB_geometry_shader4 (GL)
936 * - GL_EXT_multi_draw_arrays (ES & GL)
937 * - GL_EXT_tessellation_shader (ES) or GL_ARB_tessellation_shader (GL)
939 void DrawElementsBaseVertexTestBase::init()
941 TestCaseBase::init();
943 const glu::ContextInfo& context_info = m_context.getContextInfo();
945 if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
946 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
947 context_info.isExtensionSupported("GL_EXT_draw_elements_base_vertex"))) ||
948 context_info.isExtensionSupported("GL_ARB_draw_elements_base_vertex"))
950 #if defined(DE_DEBUG) && !defined(DE_COVERAGE_BUILD)
951 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
954 m_is_draw_elements_base_vertex_supported = true;
956 DE_ASSERT(gl.drawElementsBaseVertex != NULL);
957 DE_ASSERT(gl.drawElementsInstancedBaseVertex != NULL);
958 DE_ASSERT(gl.drawRangeElementsBaseVertex != NULL);
960 /* NOTE: glMultiDrawElementsBaseVertex() is a part of the draw_elements_base_vertex extension in GL,
961 * but requires a separate extension under ES.
963 if (!glu::isContextTypeES(m_context.getRenderContext().getType()) ||
964 context_info.isExtensionSupported("GL_EXT_multi_draw_arrays"))
966 m_is_ext_multi_draw_arrays_supported = true;
968 DE_ASSERT(gl.multiDrawElementsBaseVertex != NULL);
969 } /* if (GL_EXT_multi_draw_arrays is supported or GL context is being tested) */
971 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
973 /* This conformance test needs to be adjusted in order to run under < ES3.1 contexts */
974 DE_ASSERT(glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 1)));
978 m_is_vertex_attrib_binding_supported = context_info.isExtensionSupported("GL_ARB_vertex_attrib_binding");
980 } /* if (GL_{ARB, EXT}_draw_elements_base_vertex is supported) */
982 if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
983 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
984 context_info.isExtensionSupported("GL_EXT_geometry_shader"))) ||
985 context_info.isExtensionSupported("GL_ARB_geometry_shader4"))
987 m_is_geometry_shader_supported = true;
990 if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
991 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
992 context_info.isExtensionSupported("GL_EXT_tessellation_shader"))) ||
993 context_info.isExtensionSupported("GL_ARB_tessellation_shader"))
995 m_is_tessellation_shader_supported = true;
998 if (!m_is_draw_elements_base_vertex_supported)
1000 throw tcu::NotSupportedError("draw_elements_base_vertex functionality is not supported");
1004 /** Sets up all ES objects required to run a single functional test case iteration.
1006 * @param use_clientside_vertex_data true if the test case requires client-side buffers to
1007 * back the color/vertex vertex attribute arrays; false
1008 * to use buffer object storage.
1009 * @param use_clientside_index_data true if the test case requires client-side buffers to
1010 * be used as index data source; false to use buffer object
1012 * @param use_tessellation_shader_stage true if the program object used for the test should include
1013 * tessellation control & evaluation shader stages; false to
1014 * not to include these shader stages in the pipeline.
1015 * @param use_geometry_shader_stage true if the program object used for the test should include
1016 * geometry shader stage; false to not to include the shader
1017 * stage in the pipeline.
1018 * @param use_vertex_attrib_binding true if vertex attribute bindings should be used for
1019 * vertex array object configuration. This also modifies the
1020 * vertex shader, so that instead of calculating vertex color
1021 * on a per-vertex basis, contents of the "color" input
1022 * will be used as a data source for the color data.
1023 * false to use a vertex attribute array configured with
1024 * a casual glVertexAttribPointer() call.
1025 * @param use_overflow_test_vertices true if using an especially large vertex array to test
1026 * overflow behavior.
1028 * This method can throw an exception if any of the ES calls fail.
1030 void DrawElementsBaseVertexTestBase::setUpFunctionalTestObjects(
1031 bool use_clientside_vertex_data, bool use_clientside_index_data, bool use_tessellation_shader_stage,
1032 bool use_geometry_shader_stage, bool use_vertex_attrib_binding, bool use_overflow_test_vertices)
1034 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1036 /* Set up a texture object that we will use as a color attachment */
1037 gl.genTextures(1, &m_to_base_id);
1038 gl.genTextures(1, &m_to_ref_id);
1039 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed.");
1041 const glw::GLuint to_ids[] = { m_to_base_id, m_to_ref_id };
1042 const unsigned int n_to_ids = sizeof(to_ids) / sizeof(to_ids[0]);
1044 for (unsigned int n_to_id = 0; n_to_id < n_to_ids; ++n_to_id)
1046 gl.bindTexture(GL_TEXTURE_2D, to_ids[n_to_id]);
1047 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
1049 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
1050 GL_RGBA8, m_to_width, m_to_height);
1051 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
1054 /* Also set up some buffers we will use for data comparison */
1055 m_to_base_data = new unsigned char[m_to_width * m_to_height * 4 /* components */];
1056 m_to_ref_data = new unsigned char[m_to_width * m_to_height * 4 /* components */];
1058 /* Finally, for glReadPixels() operations, we need to make sure that pack alignment is set to 1 */
1059 gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
1060 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
1062 /* Proceed with framebuffer object initialization. Since we will be rendering to different
1063 * render-targets, there's not much point in attaching any of the textures at this point.
1065 gl.genFramebuffers(1, &m_fbo_id);
1066 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
1068 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
1069 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebufer() call failed");
1071 gl.viewport(0, /* x */
1073 m_to_width, m_to_height);
1074 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed");
1076 /* Set up buffer object we will use for the draw calls. Use the data
1077 * from the test specification.
1079 * NOTE: If you need to change the data layout here, make sure you also update
1080 * m_draw_call_color_offset, m_draw_call_index*_offset, and
1081 * m_draw_call_vertex*_offset setter calls elsewhere.
1085 unsigned int current_offset = 0;
1087 gl.genBuffers(1, &m_bo_id);
1088 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1090 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1091 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1093 gl.bufferData(GL_ARRAY_BUFFER,
1094 m_bo_functional_data_index_size + m_bo_functional_data_vertex_size +
1095 m_bo_functional2_data_vertex_size + m_bo_functional2_data_index_size +
1096 m_bo_functional3_data_index_size + m_bo_functional4_data_index_size +
1097 m_bo_functional5_data_index_size + m_bo_functional_data_color_size,
1100 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1102 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_vertex_size,
1103 m_bo_functional_data_vertex);
1104 current_offset += m_bo_functional_data_vertex_size;
1106 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional2_data_vertex_size,
1107 m_bo_functional2_data_vertex);
1108 current_offset += m_bo_functional2_data_vertex_size;
1110 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_index_size, m_bo_functional_data_index);
1111 current_offset += m_bo_functional_data_index_size;
1113 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional2_data_index_size,
1114 m_bo_functional2_data_index);
1115 current_offset += m_bo_functional2_data_index_size;
1117 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional3_data_index_size,
1118 m_bo_functional3_data_index);
1119 current_offset += m_bo_functional3_data_index_size;
1121 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional4_data_index_size,
1122 m_bo_functional4_data_index);
1123 current_offset += m_bo_functional4_data_index_size;
1125 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional5_data_index_size,
1126 m_bo_functional5_data_index);
1127 current_offset += m_bo_functional5_data_index_size;
1129 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_color_size, m_bo_functional_data_color);
1130 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
1133 if (use_overflow_test_vertices && m_bo_id_2 == 0)
1135 /* Create a special buffer that only has vertex data in a few slots */
1136 gl.genBuffers(1, &m_bo_id_2);
1137 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
1139 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_2);
1140 gl.bufferData(GL_ARRAY_BUFFER, 2 * 65550 * sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
1141 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
1144 * Upload to offset 0: regular draw call indices for making sure ubyte
1145 * and ushort indices don't wrap around too early
1146 * Upload to offset 256: base draw call indices of type ubyte
1147 * Upload to offset 65536: base draw call indices of type ushort
1149 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,
1150 -0.9f, -0.9f, 0.9f, -0.9f, 0.9f, 0.9f, -0.9f, 0.9f, -0.9f, -0.9f, 0.9f, -0.9f };
1151 gl.bufferSubData(GL_ARRAY_BUFFER, 0, sizeof(badVtx), badVtx);
1152 gl.bufferSubData(GL_ARRAY_BUFFER, 2 * 256 * sizeof(glw::GLfloat), 2 * 12 * sizeof(glw::GLfloat),
1153 m_bo_functional_data_vertex);
1154 gl.bufferSubData(GL_ARRAY_BUFFER, 2 * 65536 * sizeof(glw::GLfloat), 2 * 12 * sizeof(glw::GLfloat),
1155 m_bo_functional_data_vertex);
1156 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed");
1159 /* Set up the test program object */
1160 if (m_po_id == 0 || m_po_uses_gs_stage != use_geometry_shader_stage ||
1161 m_po_uses_tc_te_stages != use_tessellation_shader_stage ||
1162 m_po_uses_vertex_attrib_binding != use_vertex_attrib_binding)
1165 static const char* functional_fs_code = "${VERSION}\n"
1167 "precision highp float;\n"
1169 "in vec4 FS_COLOR_INPUT_NAME;\n"
1170 "out vec4 result;\n"
1174 " result = FS_COLOR_INPUT_NAME;\n"
1176 static const char* functional_gs_code = "${VERSION}\n"
1177 "${GEOMETRY_SHADER_REQUIRE}\n"
1179 "layout(triangles) in;\n"
1180 "layout(triangle_strip, max_vertices = 3) out;\n"
1182 "in vec4 GS_COLOR_INPUT_NAME[];\n"
1183 "out vec4 FS_COLOR_INPUT_NAME;\n"
1187 " for (int n = 0; n < 3; ++n)\n"
1189 " gl_Position = vec4(gl_in[n].gl_Position.x, "
1190 "-gl_in[n].gl_Position.y, gl_in[n].gl_Position.zw);\n"
1191 " FS_COLOR_INPUT_NAME = GS_COLOR_INPUT_NAME[n];\n"
1196 " EndPrimitive();\n"
1198 static const char* functional_tc_code =
1200 "${TESSELLATION_SHADER_REQUIRE}\n"
1202 "in vec4 TC_COLOR_INPUT_NAME[];\n"
1203 "out vec4 TE_COLOR_INPUT_NAME[];\n"
1205 "layout(vertices = 3) out;\n"
1209 " gl_out [gl_InvocationID].gl_Position = gl_in [gl_InvocationID].gl_Position;\n"
1210 " TE_COLOR_INPUT_NAME[gl_InvocationID] = TC_COLOR_INPUT_NAME[gl_InvocationID];\n"
1212 " gl_TessLevelInner[0] = 3.0;\n"
1213 " gl_TessLevelOuter[0] = 3.0;\n"
1214 " gl_TessLevelOuter[1] = 3.0;\n"
1215 " gl_TessLevelOuter[2] = 3.0;\n"
1217 static const char* functional_te_code =
1220 "${TESSELLATION_SHADER_REQUIRE}\n"
1222 "layout(triangles, equal_spacing, cw) in;\n"
1224 "in vec4 TE_COLOR_INPUT_NAME[];\n"
1225 "out vec4 TE_COLOR_OUTPUT_NAME;\n"
1229 " vec2 p1 = gl_in[0].gl_Position.xy;\n"
1230 " vec2 p2 = gl_in[1].gl_Position.xy;\n"
1231 " vec2 p3 = gl_in[2].gl_Position.xy;\n"
1233 " TE_COLOR_OUTPUT_NAME = TE_COLOR_INPUT_NAME[0] + TE_COLOR_INPUT_NAME[1] + TE_COLOR_INPUT_NAME[2];\n"
1234 " gl_Position = vec4(gl_TessCoord.x * p1.x + gl_TessCoord.y * p2.x + gl_TessCoord.z * p3.x,\n"
1235 " gl_TessCoord.x * p1.y + gl_TessCoord.y * p2.y + gl_TessCoord.z * p3.y,\n"
1239 static const char* functional_vs_code = "${VERSION}\n"
1241 "out vec4 VS_COLOR_OUTPUT_NAME;\n"
1244 "OPTIONAL_USE_VERTEX_ATTRIB_BINDING_DEFINITIONS\n"
1248 " float vertex_id_float = float(gl_VertexID);\n"
1250 "#ifdef USE_VERTEX_ATTRIB_BINDING\n"
1251 " vec4 color = in_color;\n"
1253 " vec4 color = vec4(vertex_id_float / 7.0,\n"
1254 " vertex_id_float / 3.0,\n"
1255 " vertex_id_float / 17.0,\n"
1258 " float scale = (gl_InstanceID == 0) ? 1.0 :\n"
1259 " (gl_InstanceID == 1) ? 0.8 :\n"
1262 " VS_COLOR_OUTPUT_NAME = color;\n"
1263 " gl_Position = vec4(vertex.xy * scale, vertex.zw);\n"
1266 /* Release a program object if one has already been set up for the running test */
1267 deinitProgramAndShaderObjects();
1269 /* Replace the tokens with actual variable names */
1270 std::string fs_body = specializeShader(1, &functional_fs_code);
1271 std::string fs_color_input_name_token = "FS_COLOR_INPUT_NAME";
1272 std::string fs_color_input_name_token_value;
1273 std::string gs_body = specializeShader(1, &functional_gs_code);
1274 std::string gs_color_input_name_token = "GS_COLOR_INPUT_NAME";
1275 std::string gs_color_input_name_token_value;
1276 std::string tc_body = specializeShader(1, &functional_tc_code);
1277 std::string tc_color_input_name_token = "TC_COLOR_INPUT_NAME";
1278 std::string tc_color_input_name_token_value;
1279 std::string te_body = specializeShader(1, &functional_te_code);
1280 std::string te_color_input_name_token = "TE_COLOR_INPUT_NAME";
1281 std::string te_color_input_name_token_value;
1282 std::string te_color_output_name_token = "TE_COLOR_OUTPUT_NAME";
1283 std::string te_color_output_name_token_value;
1284 std::string vs_body = specializeShader(1, &functional_vs_code);
1285 std::string vs_color_output_name_token = "VS_COLOR_OUTPUT_NAME";
1286 std::string vs_color_output_name_token_value;
1287 std::string vs_optional_use_vertex_attrib_binding_definitions_token =
1288 "OPTIONAL_USE_VERTEX_ATTRIB_BINDING_DEFINITIONS";
1289 std::string vs_optional_use_vertex_attrib_binding_definitions_token_value;
1291 std::string* bodies[] = { &fs_body, &gs_body, &tc_body, &te_body, &vs_body };
1292 const unsigned int n_bodies = sizeof(bodies) / sizeof(bodies[0]);
1294 std::string* token_value_pairs[] = { &fs_color_input_name_token,
1295 &fs_color_input_name_token_value,
1296 &gs_color_input_name_token,
1297 &gs_color_input_name_token_value,
1298 &tc_color_input_name_token,
1299 &tc_color_input_name_token_value,
1300 &te_color_input_name_token,
1301 &te_color_input_name_token_value,
1302 &te_color_output_name_token,
1303 &te_color_output_name_token_value,
1304 &vs_color_output_name_token,
1305 &vs_color_output_name_token_value,
1306 &vs_optional_use_vertex_attrib_binding_definitions_token,
1307 &vs_optional_use_vertex_attrib_binding_definitions_token_value };
1308 const unsigned int n_token_value_pairs =
1309 sizeof(token_value_pairs) / sizeof(token_value_pairs[0]) / 2 /* token+value */;
1311 if (!use_tessellation_shader_stage)
1313 if (!use_geometry_shader_stage)
1315 /* Geometry & tessellation shader stages are not required.
1317 * NOTE: This code-path is also used by Functional Test VII which verifies that
1318 * vertex attribute bindings work correctly with basevertex draw calls.
1319 * The test only uses FS & VS in its rendering pipeline and consumes a color
1320 * taken from an enabled vertex attribute array instead of a vector value
1321 * calculated in vertex shader stage,
1323 vs_color_output_name_token_value = "out_vs_color";
1324 fs_color_input_name_token_value = vs_color_output_name_token_value;
1326 if (use_vertex_attrib_binding)
1328 vs_optional_use_vertex_attrib_binding_definitions_token_value =
1329 "#define USE_VERTEX_ATTRIB_BINDING\n"
1330 "in vec4 in_color;\n";
1332 } /* if (!use_geometry_shader_stage) */
1335 /* Geometry shader stage is needed, but tessellation shader stage
1337 fs_color_input_name_token_value = "out_fs_color";
1338 gs_color_input_name_token_value = "out_vs_color";
1339 vs_color_output_name_token_value = "out_vs_color";
1341 DE_ASSERT(!use_vertex_attrib_binding);
1343 } /* if (!use_tessellation_shader_stage) */
1346 DE_ASSERT(!use_vertex_attrib_binding);
1348 if (!use_geometry_shader_stage)
1350 /* Tessellation shader stage is needed, but geometry shader stage
1352 fs_color_input_name_token_value = "out_fs_color";
1353 tc_color_input_name_token_value = "out_vs_color";
1354 te_color_input_name_token_value = "out_tc_color";
1355 te_color_output_name_token_value = "out_fs_color";
1356 vs_color_output_name_token_value = "out_vs_color";
1357 } /* if (!use_geometry_shader_stage) */
1360 /* Both tessellation and geometry shader stages are needed */
1361 fs_color_input_name_token_value = "out_fs_color";
1362 gs_color_input_name_token_value = "out_te_color";
1363 tc_color_input_name_token_value = "out_vs_color";
1364 te_color_input_name_token_value = "out_tc_color";
1365 te_color_output_name_token_value = "out_te_color";
1366 vs_color_output_name_token_value = "out_vs_color";
1370 for (unsigned int n_body = 0; n_body < n_bodies; ++n_body)
1372 std::string* body_ptr = bodies[n_body];
1374 for (unsigned int n_token_value_pair = 0; n_token_value_pair < n_token_value_pairs; ++n_token_value_pair)
1376 std::string token = *token_value_pairs[2 * n_token_value_pair + 0];
1377 std::size_t token_location = std::string::npos;
1378 std::string value = *token_value_pairs[2 * n_token_value_pair + 1];
1380 while ((token_location = body_ptr->find(token)) != std::string::npos)
1382 body_ptr->replace(token_location, token.length(), value);
1383 } /* while (tokens are found) */
1384 } /* for (all token+value pairs) */
1385 } /* for (all bodies) */
1387 /* Build the actual program */
1388 buildProgram(fs_body.c_str(), vs_body.c_str(), use_tessellation_shader_stage ? tc_body.c_str() : DE_NULL,
1389 use_tessellation_shader_stage ? te_body.c_str() : DE_NULL,
1390 use_geometry_shader_stage ? gs_body.c_str() : DE_NULL);
1392 m_po_uses_gs_stage = use_geometry_shader_stage;
1393 m_po_uses_tc_te_stages = use_tessellation_shader_stage;
1394 m_po_uses_vertex_attrib_binding = use_vertex_attrib_binding;
1397 /* Set up the vertex array object */
1400 gl.deleteVertexArrays(1, &m_vao_id);
1401 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
1406 if (!use_clientside_vertex_data)
1408 gl.genVertexArrays(1, &m_vao_id);
1409 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1411 gl.bindVertexArray(m_vao_id);
1412 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1414 if (m_po_color_attribute_location != -1)
1416 DE_ASSERT(use_vertex_attrib_binding);
1418 gl.enableVertexAttribArray(m_po_color_attribute_location);
1421 gl.enableVertexAttribArray(m_po_vertex_attribute_location);
1422 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call(s) failed.");
1424 /* Configure the VAO */
1425 if (use_clientside_index_data)
1427 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1428 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1432 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id);
1433 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1436 if (use_clientside_vertex_data)
1438 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1439 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1443 gl.bindBuffer(GL_ARRAY_BUFFER, use_overflow_test_vertices ? m_bo_id_2 : m_bo_id);
1444 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1447 if (!use_vertex_attrib_binding)
1449 DE_ASSERT(m_po_color_attribute_location == -1);
1451 gl.vertexAttribPointer(m_po_vertex_attribute_location, 2, /* size */
1452 GL_FLOAT, GL_FALSE, /* normalized */
1454 m_draw_call_vertex_offset);
1455 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
1456 } /* if (!use_vertex_attrib_binding) */
1459 DE_ASSERT(m_po_color_attribute_location != -1);
1460 DE_ASSERT(m_draw_call_vertex_offset < m_draw_call_color_offset);
1462 gl.vertexAttribFormat(m_po_color_attribute_location, 2, /* size */
1463 GL_FLOAT, /* type */
1464 GL_FALSE, /* normalized */
1465 (glw::GLuint)((const glw::GLubyte*)m_draw_call_color_offset -
1466 (const glw::GLubyte*)m_draw_call_vertex_offset));
1467 gl.vertexAttribFormat(m_po_vertex_attribute_location, 2, /* size */
1468 GL_FLOAT, /* type */
1469 GL_FALSE, /* normalized */
1470 0); /* relativeoffset */
1471 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribFormat() call(s) failed.");
1473 gl.vertexAttribBinding(m_po_color_attribute_location, 0); /* bindingindex */
1474 gl.vertexAttribBinding(m_po_vertex_attribute_location, 0); /* bindingindex */
1475 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribBinding() call(s) failed.");
1477 gl.bindVertexBuffer(0, /* bindingindex */
1478 (use_clientside_vertex_data) ? 0 : (use_overflow_test_vertices ? m_bo_id_2 : m_bo_id),
1479 (glw::GLintptr)m_draw_call_vertex_offset, sizeof(float) * 2);
1480 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexBuffer() call failed.");
1483 /* Bind the program object to the rendering context */
1484 gl.useProgram(m_po_id);
1485 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1488 /** Sets up all ES objects required to run a single negative test case iteration.
1490 * @param use_clientside_vertex_data true if the test case requires client-side buffers to
1491 * back the color/vertex vertex attribute arrays; false
1492 * to use buffer object storage.
1493 * @param use_clientside_index_data true if the test case requires client-side buffers to
1494 * be used as index data source; false to use buffer object
1497 void DrawElementsBaseVertexTestBase::setUpNegativeTestObjects(bool use_clientside_vertex_data,
1498 bool use_clientside_index_data)
1500 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1502 /* Set up buffer object we will use for the draw calls. Use the data
1503 * from the test specification */
1506 gl.genBuffers(1, &m_bo_id);
1507 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1509 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1510 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1512 gl.bufferData(GL_ARRAY_BUFFER, m_bo_negative_data_index_size + m_bo_negative_data_vertex_size,
1515 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1517 gl.bufferSubData(GL_ARRAY_BUFFER, 0, /* offset */
1518 m_bo_negative_data_vertex_size, m_bo_negative_data_vertex);
1519 gl.bufferSubData(GL_ARRAY_BUFFER, m_bo_negative_data_vertex_size, /* offset */
1520 m_bo_negative_data_index_size, m_bo_negative_data_index);
1521 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
1524 if (use_clientside_index_data)
1526 m_draw_call_index_offset = m_bo_negative_data_index;
1530 m_draw_call_index_offset = (const glw::GLuint*)(deUintptr)m_bo_negative_data_vertex_size;
1533 if (use_clientside_vertex_data)
1535 m_draw_call_vertex_offset = m_bo_negative_data_vertex;
1539 m_draw_call_vertex_offset = DE_NULL;
1542 /* Set up the test program object */
1545 static const char* negative_fs_code = "${VERSION}\n"
1546 "precision highp float;\n"
1548 "out vec4 result;\n"
1552 " result = vec4(1.0);\n"
1554 static const char* negative_vs_code = "${VERSION}\n"
1560 " gl_Position = vertex;\n"
1563 std::string fs_specialized_code = specializeShader(1, &negative_fs_code);
1564 const char* fs_specialized_code_raw = fs_specialized_code.c_str();
1565 std::string vs_specialized_code = specializeShader(1, &negative_vs_code);
1566 const char* vs_specialized_code_raw = vs_specialized_code.c_str();
1568 buildProgram(fs_specialized_code_raw, vs_specialized_code_raw, DE_NULL, /* tc_code */
1569 DE_NULL, /* te_code */
1570 DE_NULL); /* gs_code */
1573 /* Set up a vertex array object */
1576 gl.genVertexArrays(1, &m_vao_id);
1577 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1579 gl.bindVertexArray(m_vao_id);
1580 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1582 gl.enableVertexAttribArray(m_po_vertex_attribute_location);
1583 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
1586 /* Configure the VAO */
1587 if (use_clientside_index_data)
1589 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1590 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1594 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id);
1595 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1598 if (use_clientside_vertex_data)
1600 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1601 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1603 gl.bindVertexArray(0);
1604 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1608 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1609 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1612 gl.vertexAttribPointer(m_po_vertex_attribute_location, 2, /* size */
1613 GL_FLOAT, GL_FALSE, /* normalized */
1615 m_draw_call_vertex_offset);
1616 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
1618 /* Bind the program object to the rendering context */
1619 gl.useProgram(m_po_id);
1620 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1625 * @param context Rendering context handle.
1627 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior(
1628 Context& context, const ExtParameters& extParams)
1629 : DrawElementsBaseVertexTestBase(context, extParams, "basevertex_behavior1",
1630 "Verifies basevertex draw calls work correctly for a number of "
1631 "different rendering pipeline and VAO configurations")
1633 /* Left blank on purpose */
1636 /** Sets up test case descriptors for the test instance. These will later be used
1637 * as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1638 * the actual testing.
1640 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::setUpTestCases()
1642 /* Set up test case descriptors */
1643 const glw::GLint basevertex_values[] = { 10, 0 };
1644 const unsigned int n_basevertex_values = sizeof(basevertex_values) / sizeof(basevertex_values[0]);
1646 /* The test needs to be run in two iterations, using client-side memory and buffer object
1647 * for index data respectively
1649 for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1651 /* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1652 * See section 11.1.3.9 in OpenGL ES 3.1 spec
1654 bool use_clientside_vertex_data = 0;
1655 bool use_clientside_index_data = ((vao_iteration & (1 << 0)) != 0);
1657 /* OpenGL does not support client-side data. */
1658 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1660 if (use_clientside_index_data || use_clientside_vertex_data)
1666 /* Compute the offsets */
1667 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1669 /* There are two index data sets we need to iterate over */
1670 const glw::GLuint* index_offsets[] = { m_draw_call_index_offset, m_draw_call_index2_offset };
1671 const unsigned int n_index_offsets = sizeof(index_offsets) / sizeof(index_offsets[0]);
1673 for (unsigned int n_index_offset = 0; n_index_offset < n_index_offsets; ++n_index_offset)
1675 const glw::GLuint* current_index_offset = index_offsets[n_index_offset];
1677 /* We need to test four different functions:
1679 * a) glDrawElementsBaseVertex() (GL)
1680 * or glDrawElementsBaseVertexEXT() (ES)
1681 * b) glDrawRangeElementsBaseVertex() (GL)
1682 * or glDrawRangeElementsBaseVertexEXT() (ES)
1683 * c) glDrawElementsInstancedBaseVertex() (GL)
1684 * or glDrawElementsInstancedBaseVertexEXT() (ES)
1685 * d) glMultiDrawElementsBaseVertex() (GL)
1686 * or glMultiDrawElementsBaseVertexEXT() (ES) (if supported)
1688 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1690 /* Do not try to use the multi draw call if relevant extension is
1692 if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1697 /* We need to run the test for a number of different basevertex values. */
1698 for (unsigned int n_basevertex_value = 0; n_basevertex_value < n_basevertex_values;
1699 ++n_basevertex_value)
1701 /* Finally, we want to verify that basevertex draw calls work correctly both when vertex attribute
1702 * bindings are enabled and disabled */
1703 bool vertex_attrib_binding_statuses[] = { false, true };
1704 unsigned int n_vertex_attrib_binding_statuses =
1705 sizeof(vertex_attrib_binding_statuses) / sizeof(vertex_attrib_binding_statuses[0]);
1707 for (unsigned int n_vertex_attrib_binding_status = 0;
1708 n_vertex_attrib_binding_status < n_vertex_attrib_binding_statuses;
1709 ++n_vertex_attrib_binding_status)
1711 bool use_vertex_attrib_binding = vertex_attrib_binding_statuses[n_vertex_attrib_binding_status];
1713 /* Under GL, "vertex attrib binding" functionality is only available if GL_ARB_vertex_attrib_binding
1714 * extension is supported.
1716 if (!m_is_vertex_attrib_binding_supported && use_vertex_attrib_binding)
1721 /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1722 const glw::GLsizei multi_draw_call_count_array[3] = { 3, 6, 3 };
1723 const glw::GLuint* multi_draw_call_indices_array[3] = {
1724 (glw::GLuint*)(current_index_offset), (glw::GLuint*)(current_index_offset + 3),
1725 (glw::GLuint*)(current_index_offset + 9)
1728 /* Reference texture should always reflect basevertex=10 behavior. */
1729 const glw::GLuint regular_draw_call_offset = basevertex_values[0];
1730 const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1731 multi_draw_call_indices_array[0] + regular_draw_call_offset,
1732 multi_draw_call_indices_array[1] + regular_draw_call_offset,
1733 multi_draw_call_indices_array[2] + regular_draw_call_offset,
1736 /* Construct the test case descriptor */
1737 _test_case new_test_case;
1739 new_test_case.basevertex = basevertex_values[n_basevertex_value];
1740 new_test_case.function_type = (_function_type)n_function;
1741 new_test_case.index_offset = current_index_offset;
1742 new_test_case.range_start = n_index_offset == 0 ? 0 : 10;
1743 new_test_case.range_end = n_index_offset == 0 ? 22 : 32;
1744 new_test_case.index_type = GL_UNSIGNED_INT;
1745 new_test_case.primitive_mode = GL_TRIANGLES;
1746 new_test_case.regular_draw_call_offset = basevertex_values[0];
1747 new_test_case.should_base_texture_match_reference_texture =
1748 ((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
1749 new_test_case.use_clientside_index_data = use_clientside_index_data;
1750 new_test_case.use_clientside_vertex_data = use_clientside_vertex_data;
1751 new_test_case.use_geometry_shader_stage = false;
1752 new_test_case.use_tessellation_shader_stage = false;
1753 new_test_case.use_vertex_attrib_binding = use_vertex_attrib_binding;
1755 memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1756 sizeof(multi_draw_call_count_array));
1757 memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1758 sizeof(multi_draw_call_indices_array));
1759 memcpy(new_test_case.regular_multi_draw_call_offseted_array,
1760 regular_multi_draw_call_offseted_array, sizeof(regular_multi_draw_call_offseted_array));
1762 m_test_cases.push_back(new_test_case);
1763 } /* for (all vertex_attrib_binding statuses) */
1764 } /* for (all basevertex values) */
1765 } /* for (all four functions) */
1766 } /* for (all index data sets) */
1767 } /* for (all VAO iterations) */
1770 /** Executes test iteration.
1772 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1774 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::iterate()
1779 /* Test case passed */
1780 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1787 * @param context Rendering context handle.
1789 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2(
1790 Context& context, const ExtParameters& extParams)
1791 : DrawElementsBaseVertexTestBase(context, extParams, "basevertex_behavior2",
1792 "Verifies basevertex draw calls work correctly for a number of "
1793 "different rendering pipeline and VAO configurations. Uses slightly "
1794 "different data set than basevertex_behavior.")
1796 /* Left blank on purpose */
1799 /** Sets up test case descriptors for the test instance. These will later be used
1800 * as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1801 * the actual testing.
1803 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::setUpTestCases()
1805 /* Set up test case descriptors */
1806 const glw::GLint basevertex = 5;
1808 /* The test needs to be run in two iterations, using client-side memory and buffer object
1809 * for index data respectively
1811 for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1813 /* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1814 * See section 11.1.3.9 in OpenGL ES 3.1 spec
1816 bool use_clientside_vertex_data = 0;
1817 bool use_clientside_index_data = ((vao_iteration & (1 << 0)) != 0);
1819 /* OpenGL does not support client-side data. */
1820 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1822 if (use_clientside_index_data || use_clientside_vertex_data)
1828 /* Compute the offsets */
1829 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1831 /* We need to test four different functions:
1833 * a) glDrawElementsBaseVertex() (GL)
1834 * or glDrawElementsBaseVertexEXT() (ES)
1835 * b) glDrawRangeElementsBaseVertex() (GL)
1836 * or glDrawRangeElementsBaseVertexEXT() (ES)
1837 * c) glDrawElementsInstancedBaseVertex() (GL)
1838 * or glDrawElementsInstancedBaseVertexEXT() (ES)
1839 * d) glMultiDrawElementsBaseVertex() (GL)
1840 * or glMultiDrawElementsBaseVertexEXT() (ES) (if supported)
1842 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1844 /* Do not try to use the multi draw call if relevant extension is
1846 if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1851 /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1852 const glw::GLsizei multi_draw_call_count_array[3] = { 3, 6, 3 };
1853 const glw::GLuint* multi_draw_call_indices_array[3] = { (glw::GLuint*)(m_draw_call_index_offset),
1854 (glw::GLuint*)(m_draw_call_index_offset + 3),
1855 (glw::GLuint*)(m_draw_call_index_offset + 9) };
1857 /* Reference texture should always reflect basevertex=10 behavior. */
1858 const glw::GLuint regular_draw_call_offset = 0;
1859 const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1860 multi_draw_call_indices_array[0] + regular_draw_call_offset,
1861 multi_draw_call_indices_array[1] + regular_draw_call_offset,
1862 multi_draw_call_indices_array[2] + regular_draw_call_offset,
1865 /* Construct the test case descriptor */
1866 _test_case new_test_case;
1868 new_test_case.basevertex = basevertex;
1869 new_test_case.function_type = (_function_type)n_function;
1870 new_test_case.index_offset = m_draw_call_index_offset;
1871 new_test_case.range_start = 0;
1872 new_test_case.range_end = 22;
1873 new_test_case.index_type = GL_UNSIGNED_INT;
1874 new_test_case.primitive_mode = GL_TRIANGLES;
1875 new_test_case.regular_draw_call_offset = regular_draw_call_offset;
1876 new_test_case.should_base_texture_match_reference_texture =
1877 ((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
1878 new_test_case.use_clientside_index_data = use_clientside_index_data;
1879 new_test_case.use_clientside_vertex_data = use_clientside_vertex_data;
1880 new_test_case.use_geometry_shader_stage = false;
1881 new_test_case.use_tessellation_shader_stage = false;
1882 new_test_case.use_vertex_attrib_binding = false;
1884 memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1885 sizeof(multi_draw_call_count_array));
1886 memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1887 sizeof(multi_draw_call_indices_array));
1888 memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
1889 sizeof(regular_multi_draw_call_offseted_array));
1891 m_test_cases.push_back(new_test_case);
1892 } /* for (all four functions) */
1893 } /* for (all VAO iterations) */
1896 /** Executes test iteration.
1898 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1900 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::iterate()
1905 /* Test case passed */
1906 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1913 * @param context Rendering context handle.
1915 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::
1916 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow(Context& context, const ExtParameters& extParams)
1917 : DrawElementsBaseVertexTestBase(context, extParams, "underflow",
1918 "Verifies basevertex draw calls work correctly for negative "
1919 "basevertex values")
1921 /* Left blank on purpose */
1924 /** Sets up test case descriptors for the test instance. These will later be used
1925 * as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1926 * the actual testing.
1928 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::setUpTestCases()
1930 /* Set up test case descriptors */
1931 const glw::GLint basevertex = -10;
1933 /* The test needs to be run in two iterations, using client-side memory and buffer object
1934 * for index data respectively
1936 for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1938 /* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1939 * See section 11.1.3.9 in OpenGL ES 3.1 spec
1941 bool use_clientside_vertex_data = 0;
1942 bool use_clientside_index_data = ((vao_iteration & (1 << 0)) != 0);
1944 /* OpenGL does not support client-side data. */
1945 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1947 if (use_clientside_index_data || use_clientside_vertex_data)
1953 /* Compute the offsets */
1954 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1956 /* We need to test four different functions:
1958 * a) glDrawElementsBaseVertex() (GL)
1959 * or glDrawElementsBaseVertexEXT() (ES)
1960 * b) glDrawRangeElementsBaseVertex() (GL)
1961 * or glDrawRangeElementsBaseVertexEXT() (ES)
1962 * c) glDrawElementsInstancedBaseVertex() (GL)
1963 * or glDrawElementsInstancedBaseVertexEXT() (ES)
1964 * d) glMultiDrawElementsBaseVertex() (GL)
1965 * or glMultiDrawElementsBaseVertexEXT() (ES) (if supported)
1967 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1969 /* Do not try to use the multi draw call if relevant extension is
1971 if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1976 /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1977 unsigned int offset_from_10_to_0_index = 23; /* this offset moves us from the start index of 10 to a zero
1978 * index, given the second index data set we will be using.
1979 * Please see declaration of functional2_index_data if you
1980 * need to verify this by yourself. */
1982 const glw::GLsizei multi_draw_call_count_array[3] = { 3, 6, 3 };
1983 const glw::GLuint* multi_draw_call_indices_array[3] = { (glw::GLuint*)(m_draw_call_index2_offset),
1984 (glw::GLuint*)(m_draw_call_index2_offset + 3),
1985 (glw::GLuint*)(m_draw_call_index2_offset + 9) };
1986 const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1987 multi_draw_call_indices_array[0] + offset_from_10_to_0_index,
1988 multi_draw_call_indices_array[1] + offset_from_10_to_0_index,
1989 multi_draw_call_indices_array[2] + offset_from_10_to_0_index,
1992 /* Construct the test case descriptor */
1993 _test_case new_test_case;
1995 new_test_case.basevertex = basevertex;
1996 new_test_case.function_type = (_function_type)n_function;
1997 new_test_case.index_offset = m_draw_call_index2_offset;
1998 new_test_case.range_start = 10;
1999 new_test_case.range_end = 32;
2000 new_test_case.index_type = GL_UNSIGNED_INT;
2001 new_test_case.primitive_mode = GL_TRIANGLES;
2002 new_test_case.regular_draw_call_offset = offset_from_10_to_0_index;
2003 new_test_case.should_base_texture_match_reference_texture = true;
2004 new_test_case.use_clientside_index_data = use_clientside_index_data;
2005 new_test_case.use_clientside_vertex_data = use_clientside_vertex_data;
2006 new_test_case.use_geometry_shader_stage = false;
2007 new_test_case.use_tessellation_shader_stage = false;
2008 new_test_case.use_vertex_attrib_binding = false;
2010 memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
2011 sizeof(multi_draw_call_count_array));
2012 memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
2013 sizeof(multi_draw_call_indices_array));
2014 memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
2015 sizeof(regular_multi_draw_call_offseted_array));
2017 m_test_cases.push_back(new_test_case);
2018 } /* for (all four functions) */
2019 } /* for (all VAO iterations) */
2022 /** Executes test iteration.
2024 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2026 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::iterate()
2031 /* Test case passed */
2032 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2039 * @param context Rendering context handle.
2041 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::
2042 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow(Context& context, const ExtParameters& extParams)
2043 : DrawElementsBaseVertexTestBase(context, extParams, "overflow",
2044 "Verifies basevertex draw calls work correctly for overflowing "
2045 "basevertex values")
2047 /* Left blank on purpose */
2050 /** Sets up test case descriptors for the test instance. These will later be used
2051 * as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
2052 * the actual testing.
2054 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::setUpTestCases()
2056 /* The test needs to be run in two iterations, using client-side memory and buffer object
2057 * for index data respectively
2059 for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
2061 /* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
2062 * See section 11.1.3.9 in OpenGL ES 3.1 spec
2064 bool use_clientside_vertex_data = 0;
2065 bool use_clientside_index_data = ((vao_iteration & (1 << 0)) != 0);
2067 /* OpenGL does not support client-side data. */
2068 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2070 if (use_clientside_index_data || use_clientside_vertex_data)
2076 /* Compute the offsets */
2077 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
2079 /* We need to test four different functions:
2081 * a) glDrawElementsBaseVertex() (GL)
2082 * or glDrawElementsBaseVertexEXT() (ES)
2083 * b) glDrawRangeElementsBaseVertex() (GL)
2084 * or glDrawRangeElementsBaseVertexEXT() (ES)
2085 * c) glDrawElementsInstancedBaseVertex() (GL)
2086 * or glDrawElementsInstancedBaseVertexEXT() (ES)
2087 * d) glMultiDrawElementsBaseVertex() (GL)
2088 * or glMultiDrawElementsBaseVertexEXT() (ES) (if supported)
2090 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
2092 /* Do not try to use the multi draw call if relevant extension is
2094 if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
2099 const glw::GLenum index_types[] = { GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT };
2101 const unsigned int n_index_types = sizeof(index_types) / sizeof(index_types[0]);
2103 for (unsigned int n_index_type = 0; n_index_type < n_index_types; ++n_index_type)
2106 glw::GLint basevertex = -1;
2107 const glw::GLubyte* index_offset = NULL;
2109 glw::GLenum index_type = index_types[n_index_type];
2110 glw::GLenum regular_draw_call_index_type = 0;
2111 int regular_draw_call_index_size = 0;
2112 glw::GLboolean use_overflow_test_vertices = false;
2114 /* To meet requirements of tests IX.1-IX.2 and IX.3, we need to use two basevertex deltas. */
2115 const glw::GLint basevertex_deltas[] = {
2119 const unsigned int n_basevertex_deltas = sizeof(basevertex_deltas) / sizeof(basevertex_deltas[0]);
2121 for (unsigned int n_basevertex_delta = 0; n_basevertex_delta < n_basevertex_deltas;
2122 ++n_basevertex_delta)
2124 const glw::GLint basevertex_delta = basevertex_deltas[n_basevertex_delta];
2125 glw::GLuint regular_draw_call_offset = 0;
2126 glw::GLuint* regular_draw_call_offset2 = NULL;
2127 glw::GLuint range_start = 0;
2128 glw::GLuint range_end = 0;
2134 * UBYTE base draw indices: 0, 1, 2
2136 * regular draw indices: 0, 1, 2
2137 * expected result: ubyte indices should not wrap around at 8-bit width,
2138 * base draw result should not match regular draw result
2140 * UBYTE base draw indices: 0, 1, 2
2142 * regular draw indices: 257, 258, 259 (uint)
2143 * expected result: ubyte indices should be upconverted to 32-bit uint,
2144 * base draw result should match regular draw result
2146 case GL_UNSIGNED_BYTE:
2148 basevertex = 256 + basevertex_delta;
2149 index_offset = (const glw::GLubyte*)m_draw_call_index3_offset;
2153 regular_draw_call_index_type = (basevertex_delta == 0) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT;
2154 regular_draw_call_index_size = (regular_draw_call_index_type == GL_UNSIGNED_BYTE) ? 1 : 4;
2155 regular_draw_call_offset2 =
2156 (basevertex_delta == 0) ?
2157 (glw::GLuint*)(m_draw_call_index3_offset) :
2158 (glw::GLuint*)(m_draw_call_index5_offset + 12); // 12th in functional5_index_data
2159 shouldMatch = (basevertex_delta == 1) ? true : false;
2160 use_overflow_test_vertices = true;
2165 * USHORT base draw indices: 0, 1, 2
2166 * baseVertex: 65536+0
2167 * regular draw indices: 0, 1, 2
2168 * expected result: ubyte indices should not wrap around at 16-bit width,
2169 * base draw result should not match regular draw result
2171 * USHORT base draw indices: 0, 1, 2
2172 * baseVertex: 65536+1
2173 * regular draw indices: 65537, 65538, 65539 (uint)
2174 * expected result: ushort indices should be upconverted to 32-bit uint,
2175 * base draw result should match regular draw result
2177 case GL_UNSIGNED_SHORT:
2179 basevertex = 65536 + basevertex_delta;
2180 index_offset = (const glw::GLubyte*)m_draw_call_index4_offset;
2184 regular_draw_call_index_type = (basevertex_delta == 0) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
2185 regular_draw_call_index_size = (regular_draw_call_index_type == GL_UNSIGNED_SHORT) ? 2 : 4;
2186 regular_draw_call_offset2 =
2187 (basevertex_delta == 0) ?
2188 (glw::GLuint*)(m_draw_call_index4_offset) :
2189 (glw::GLuint*)(m_draw_call_index5_offset + 24); // 24th in functional5_index_data
2190 shouldMatch = (basevertex_delta == 1) ? true : false;
2191 use_overflow_test_vertices = true;
2196 * UINT base draw indices: 2^31+2, 2^31+3, 2^31+4
2197 * baseVertex: 2^31-2
2198 * regular draw indices: 0, 1, 2
2199 * expected result: uint indices should wrap to {0, 1, 2},
2200 * base draw result should match regular draw result
2202 * UINT base draw indices: 2^31+2, 2^31+3, 2^31+4
2203 * baseVertex: 2^31-1
2204 * regular draw indices: 0, 1, 2
2205 * expected result: uint indices should wrap to {1, 2, 3},
2206 * base draw result should not match regular draw result
2208 case GL_UNSIGNED_INT:
2210 basevertex = 2147483647 - 1 + basevertex_delta;
2211 index_offset = (const glw::GLubyte*)m_draw_call_index5_offset;
2213 range_start = 2147483647 + 3u; // 2^31+2
2214 range_end = 2147483647 + 5u; // 2^31+4
2215 regular_draw_call_index_type = GL_UNSIGNED_INT;
2216 regular_draw_call_index_size = 4;
2217 regular_draw_call_offset = 36; // 36th in functional5_index_data
2218 shouldMatch = (basevertex_delta == 0) ? true : false;
2219 use_overflow_test_vertices = false;
2225 TCU_FAIL("Unrecognized index type");
2227 } /* switch (index_type) */
2229 /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
2230 const glw::GLsizei multi_draw_call_count_array[3] = { 3, 6, 3 };
2231 const glw::GLubyte* multi_draw_call_indices_array[3] = { index_offset,
2232 index_offset + 3 * index_size,
2233 index_offset + 9 * index_size };
2234 const glw::GLubyte* regular_multi_draw_call_offseted_array[3];
2235 if (use_overflow_test_vertices)
2237 regular_multi_draw_call_offseted_array[0] = (glw::GLubyte*)regular_draw_call_offset2;
2238 regular_multi_draw_call_offseted_array[1] =
2239 (glw::GLubyte*)regular_draw_call_offset2 + 3 * regular_draw_call_index_size;
2240 regular_multi_draw_call_offseted_array[2] =
2241 (glw::GLubyte*)regular_draw_call_offset2 + 9 * regular_draw_call_index_size;
2245 regular_multi_draw_call_offseted_array[0] =
2246 multi_draw_call_indices_array[0] + index_size * regular_draw_call_offset;
2247 regular_multi_draw_call_offseted_array[1] =
2248 multi_draw_call_indices_array[1] + index_size * regular_draw_call_offset;
2249 regular_multi_draw_call_offseted_array[2] =
2250 multi_draw_call_indices_array[2] + index_size * regular_draw_call_offset;
2253 /* Construct the test case descriptor */
2254 _test_case new_test_case;
2256 new_test_case.basevertex = basevertex;
2257 new_test_case.function_type = (_function_type)n_function;
2258 new_test_case.index_offset = (const glw::GLuint*)index_offset;
2259 new_test_case.range_start = range_start;
2260 new_test_case.range_end = range_end;
2261 new_test_case.index_type = index_type;
2262 new_test_case.primitive_mode = GL_TRIANGLES;
2263 new_test_case.regular_draw_call_offset = regular_draw_call_offset;
2264 new_test_case.regular_draw_call_offset2 = regular_draw_call_offset2;
2265 new_test_case.regular_draw_call_index_type = regular_draw_call_index_type;
2266 new_test_case.should_base_texture_match_reference_texture = shouldMatch;
2267 new_test_case.use_clientside_index_data = use_clientside_index_data;
2268 new_test_case.use_clientside_vertex_data = use_clientside_vertex_data;
2269 new_test_case.use_geometry_shader_stage = false;
2270 new_test_case.use_tessellation_shader_stage = false;
2271 new_test_case.use_vertex_attrib_binding = false;
2272 new_test_case.use_overflow_test_vertices = use_overflow_test_vertices != GL_FALSE;
2274 memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
2275 sizeof(multi_draw_call_count_array));
2276 memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
2277 sizeof(multi_draw_call_indices_array));
2278 memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
2279 sizeof(regular_multi_draw_call_offseted_array));
2281 m_test_cases.push_back(new_test_case);
2282 } /* for (all basevertex deltas) */
2283 } /* for (all index types) */
2284 } /* for (all four functions) */
2285 } /* for (all VAO iterations) */
2288 /** Executes test iteration.
2290 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2292 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::iterate()
2297 /* Test case passed */
2298 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2305 * @param context Rendering context handle.
2307 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::
2308 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages(Context& context,
2309 const ExtParameters& extParams)
2310 : DrawElementsBaseVertexTestBase(context, extParams, "AEP_shader_stages",
2311 "Verifies basevertex draw calls work correctly when geometry & "
2312 "tessellation shader stages are used in the rendering pipeline.")
2314 /* Left blank intentionally */
2317 /** Sets up test case descriptors for the test instance. These will later be used
2318 * as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
2319 * the actual testing.
2321 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::setUpTestCases()
2323 /* Set up test case descriptors */
2324 const glw::GLuint basevertex_values[] = {
2328 const unsigned int n_basevertex_values = sizeof(basevertex_values) / sizeof(basevertex_values[0]);
2330 /* The test needs to be run in two iterations, using client-side memory and buffer object
2331 * for index data respectively
2333 for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
2335 /* Skip client-side vertex array as gl_VertexID is undefined when zero buffer is bound to ARRAY_BUFFER */
2336 bool use_clientside_vertex_data = 0;
2337 bool use_clientside_index_data = ((vao_iteration & (1 << 0)) != 0);
2339 /* OpenGL does not support client-side data. */
2340 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2342 if (use_clientside_index_data || use_clientside_vertex_data)
2348 /* Compute the offsets */
2349 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
2351 /* There are two index data sets we need to iterate over */
2352 const glw::GLuint* index_offsets[] = { m_draw_call_index_offset, m_draw_call_index2_offset };
2353 const unsigned int n_index_offsets = sizeof(index_offsets) / sizeof(index_offsets[0]);
2355 for (unsigned int n_index_offset = 0; n_index_offset < n_index_offsets; ++n_index_offset)
2357 const glw::GLuint* current_index_offset = index_offsets[n_index_offset];
2359 /* We need to test four different functions:
2361 * a) glDrawElementsBaseVertex() (GL)
2362 * or glDrawElementsBaseVertexEXT() (ES)
2363 * b) glDrawRangeElementsBaseVertex() (GL)
2364 * or glDrawRangeElementsBaseVertexEXT() (ES)
2365 * c) glDrawElementsInstancedBaseVertex() (GL)
2366 * or glDrawElementsInstancedBaseVertexEXT() (ES)
2367 * d) glMultiDrawElementsBaseVertex() (GL)
2368 * or glMultiDrawElementsBaseVertexEXT() (ES) (if supported)
2370 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
2372 /* Iterate over all basevertex values */
2373 for (unsigned int n_basevertex_value = 0; n_basevertex_value < n_basevertex_values;
2374 ++n_basevertex_value)
2377 /* Iterate over all GS+(TC & TE) stage combinations */
2378 for (unsigned int n_stage_combination = 0; n_stage_combination < 4; ++n_stage_combination)
2380 bool should_include_gs = (n_stage_combination & 1) != 0;
2381 bool should_include_tc_te = (n_stage_combination & 2) != 0;
2383 /* Skip iterations, for which we'd need to use extensions not supported
2384 * by the running implementation */
2385 if (should_include_gs && !m_is_geometry_shader_supported)
2390 if (should_include_tc_te && !m_is_tessellation_shader_supported)
2395 /* Do not try to use the multi draw call if relevant extension is
2397 if (!m_is_ext_multi_draw_arrays_supported &&
2398 n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
2403 /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
2404 const glw::GLsizei multi_draw_call_count_array[3] = { 3, 6, 3 };
2405 const glw::GLuint* multi_draw_call_indices_array[3] = {
2406 (glw::GLuint*)(current_index_offset), (glw::GLuint*)(current_index_offset + 3),
2407 (glw::GLuint*)(current_index_offset + 9)
2410 /* Reference texture should always reflect basevertex=10 behavior. */
2411 const glw::GLuint regular_draw_call_offset = basevertex_values[0];
2412 const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
2413 multi_draw_call_indices_array[0] + regular_draw_call_offset,
2414 multi_draw_call_indices_array[1] + regular_draw_call_offset,
2415 multi_draw_call_indices_array[2] + regular_draw_call_offset,
2418 /* Construct the test case descriptor */
2419 _test_case new_test_case;
2421 new_test_case.basevertex = basevertex_values[n_basevertex_value];
2422 new_test_case.function_type = (_function_type)n_function;
2423 new_test_case.index_offset = current_index_offset;
2424 new_test_case.range_start = n_index_offset == 0 ? 0 : 10;
2425 new_test_case.range_end = n_index_offset == 0 ? 22 : 32;
2426 new_test_case.index_type = GL_UNSIGNED_INT;
2427 new_test_case.primitive_mode = (should_include_tc_te) ? GL_PATCHES : GL_TRIANGLES;
2428 new_test_case.regular_draw_call_offset = regular_draw_call_offset;
2429 new_test_case.should_base_texture_match_reference_texture =
2430 ((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
2431 new_test_case.use_clientside_index_data = use_clientside_index_data;
2432 new_test_case.use_clientside_vertex_data = use_clientside_vertex_data;
2433 new_test_case.use_geometry_shader_stage = should_include_gs;
2434 new_test_case.use_tessellation_shader_stage = should_include_tc_te;
2435 new_test_case.use_vertex_attrib_binding = false;
2437 memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
2438 sizeof(multi_draw_call_count_array));
2439 memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
2440 sizeof(multi_draw_call_indices_array));
2441 memcpy(new_test_case.regular_multi_draw_call_offseted_array,
2442 regular_multi_draw_call_offseted_array, sizeof(regular_multi_draw_call_offseted_array));
2444 m_test_cases.push_back(new_test_case);
2445 } /* for (all shader stage combinations) */
2446 } /* for (all basevertex values) */
2447 } /* for (all four functions) */
2448 } /* for (all index data sets) */
2449 } /* for (all VAO iterations) */
2452 /** Executes test iteration.
2454 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2456 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::iterate()
2458 /* This test should not be run on implementations that don't support both tessellation and geometry
2461 if (!m_is_geometry_shader_supported && !m_is_tessellation_shader_supported)
2463 throw tcu::NotSupportedError("Geometry shader and tessellation shader functionality is not supported");
2469 /* Test case passed */
2470 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2477 * @param context Rendering context handle.
2479 DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::DrawElementsBaseVertexNegativeActiveTransformFeedbackTest(
2480 Context& context, const ExtParameters& extParams)
2481 : DrawElementsBaseVertexTestBase(context, extParams, "valid_active_tf",
2482 "Tries to do \"base vertex\" draw calls while Transform Feedback is active")
2483 , m_bo_tf_result_id(0)
2485 /* Left blank on purpose */
2488 /** Deinitializes all ES objects per test case if test fails and exit through exception path */
2489 void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::deinit()
2491 deinitPerTestObjects();
2494 /** Deinitializes all ES objects that may have been created by the test */
2495 void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::deinitPerTestObjects()
2497 /* Call the base class' deinitPerTestObjects() first. */
2498 DrawElementsBaseVertexTestBase::deinitPerTestObjects();
2500 /* Proceed with internal deinitialization */
2501 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2503 if (m_bo_tf_result_id != 0)
2505 gl.deleteBuffers(1, &m_bo_tf_result_id);
2507 m_bo_tf_result_id = 0;
2511 /** Initializes all ES objects used by the test. */
2512 void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::init()
2514 /* Call the base class' init() first. */
2515 DrawElementsBaseVertexTestBase::init();
2517 /* Proceed with internal initialization */
2518 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2520 gl.genBuffers(1, &m_bo_tf_result_id);
2521 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
2523 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_tf_result_id);
2524 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
2526 gl.bufferData(GL_ARRAY_BUFFER, 3 /* count */ * sizeof(float) * 4 /* components used by gl_Position */,
2529 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2531 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
2533 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
2536 /** Executes test iteration.
2538 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2540 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::iterate()
2542 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2544 /* this test doesn't apply to OpenGL contexts */
2545 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2547 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
2551 /* Set up the work environment */
2552 setUpNegativeTestObjects(false, /* use_clientside_vertex_data */
2553 false); /* use_clientside_index_data */
2555 /* Kick off transform feedback */
2556 gl.beginTransformFeedback(GL_TRIANGLES);
2557 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2559 /* Try to perform indiced draw calls which are invalid when TF is active.
2561 glw::GLenum error_code = GL_NONE;
2563 gl.drawElementsBaseVertex(GL_TRIANGLES, 3, /* count */
2564 GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
2566 error_code = gl.getError();
2568 /* The error for using DrawElements* commands while transform feedback is
2569 active is lifted in OES/EXT_geometry_shader. See issue 13 in the spec.
2571 glw::GLenum expected_error_code = m_is_geometry_shader_supported ? GL_NO_ERROR : GL_INVALID_OPERATION;
2573 if (error_code != expected_error_code)
2575 std::stringstream error_sstream;
2577 error_sstream << "Invalid error code generated by " << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX);
2579 m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX)
2580 << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2581 << tcu::TestLog::EndMessage;
2583 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2588 gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, 3, /* count */
2589 GL_UNSIGNED_INT, m_draw_call_index_offset, 1, /* instancecount */
2590 0); /* basevertex */
2592 error_code = gl.getError();
2593 if (error_code != expected_error_code)
2595 std::stringstream error_sstream;
2597 error_sstream << "Invalid error code generated by "
2598 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX);
2600 m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX)
2601 << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2602 << tcu::TestLog::EndMessage;
2604 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2609 gl.drawRangeElementsBaseVertex(GL_TRIANGLES, 0, 2, /* end */
2611 GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
2613 error_code = gl.getError();
2614 if (error_code != expected_error_code)
2616 std::stringstream error_sstream;
2618 error_sstream << "Invalid error code generated by "
2619 << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX);
2621 m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX)
2622 << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2623 << tcu::TestLog::EndMessage;
2625 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2630 /* Test case passed */
2631 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2634 gl.endTransformFeedback();
2640 * @param context Rendering context handle.
2642 DrawElementsBaseVertexNegativeInvalidCountArgumentTest::DrawElementsBaseVertexNegativeInvalidCountArgumentTest(
2643 Context& context, const ExtParameters& extParams)
2644 : DrawElementsBaseVertexTestBase(context, extParams, "invalid_count_argument",
2645 "Tries to use invalid 'count' argument values for the \"base vertex\" draw calls")
2647 /* Left blank on purpose */
2650 /** Executes test iteration.
2652 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2654 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidCountArgumentTest::iterate()
2656 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2658 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
2659 * in a slightly different manner.
2661 for (int iteration = 0; iteration < 4; ++iteration)
2663 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
2664 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2666 /* OpenGL does not support client-side data. */
2667 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2669 if (use_clientside_index_data || use_clientside_vertex_data)
2675 /* Set up the work environment */
2676 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2678 /* Try to execute the invalid draw calls */
2679 glw::GLenum error_code = GL_NONE;
2681 gl.drawElementsBaseVertex(GL_TRIANGLES, -1, /* count */
2682 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
2684 error_code = gl.getError();
2685 if (error_code != GL_INVALID_VALUE)
2687 std::stringstream error_sstream;
2689 error_sstream << "Invalid error code reported for an invalid "
2690 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2692 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2693 << ": expected GL_INVALID_VALUE, got:"
2695 << error_code << "]" << tcu::TestLog::EndMessage;
2697 TCU_FAIL(error_sstream.str().c_str());
2700 gl.drawRangeElementsBaseVertex(GL_TRIANGLES, /* mode */
2704 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2705 0); /* basevertex */
2707 error_code = gl.getError();
2708 if (error_code != GL_INVALID_VALUE)
2710 std::stringstream error_sstream;
2712 error_sstream << "Invalid error code reported for an invalid "
2713 << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
2715 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2716 << ": expected GL_INVALID_VALUE, got:"
2718 << error_code << "]" << tcu::TestLog::EndMessage;
2720 TCU_FAIL(error_sstream.str().c_str());
2723 gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, /* mode */
2725 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2726 1, /* instancecount */
2727 0); /* basevertex */
2729 error_code = gl.getError();
2730 if (error_code != GL_INVALID_VALUE)
2732 std::stringstream error_sstream;
2734 error_sstream << "Invalid error code reported for an invalid "
2735 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2737 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2738 << ": expected GL_INVALID_VALUE, got:"
2740 << error_code << "]" << tcu::TestLog::EndMessage;
2742 TCU_FAIL(error_sstream.str().c_str());
2745 if (m_is_ext_multi_draw_arrays_supported)
2747 const glw::GLsizei count = -1;
2748 const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
2750 gl.multiDrawElementsBaseVertex(GL_TRIANGLES, /* mode */
2751 &count, GL_UNSIGNED_INT, offsets, 1, /* primcount */
2752 0); /* basevertex */
2754 error_code = gl.getError();
2755 if (error_code != GL_INVALID_VALUE)
2757 std::stringstream error_sstream;
2759 error_sstream << "Invalid error code reported for an invalid "
2760 << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2762 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2763 << ": expected GL_INVALID_VALUE, got:"
2765 << error_code << "]" << tcu::TestLog::EndMessage;
2767 TCU_FAIL("Invalid error code reported for an invalid glMultiDrawElementsBaseVertexEXT() call.");
2769 } /* if (m_is_ext_multi_draw_arrays_supported) */
2770 } /* for (all iterations) */
2772 /* Test case passed */
2773 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2780 * @param context Rendering context handle.
2782 DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest::
2783 DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest(Context& context, const ExtParameters& extParams)
2784 : DrawElementsBaseVertexTestBase(context, extParams, "invalid_instancecount_argument",
2785 "Tries to use invalid 'instancecount' argument values for "
2786 "glDrawElementsInstancedBaseVertexEXT (ES) or "
2787 "glDrawElementsInstancedBaseVertex (GL) draw call")
2789 /* Left blank on purpose */
2792 /** Executes test iteration.
2794 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2796 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest::iterate()
2798 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2800 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
2801 * in a slightly different manner.
2803 for (int iteration = 0; iteration < 4; ++iteration)
2805 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
2806 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2808 /* OpenGL does not support client-side data. */
2809 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2811 if (use_clientside_index_data || use_clientside_vertex_data)
2817 /* Set up the work environment */
2818 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2820 /* Try to execute the invalid draw call */
2821 glw::GLenum error_code = GL_NONE;
2823 gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, /* mode */
2825 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2826 -1, /* instancecount */
2827 0); /* basevertex */
2829 error_code = gl.getError();
2830 if (error_code != GL_INVALID_VALUE)
2832 std::stringstream error_sstream;
2834 error_sstream << "Invalid error code reported for an invalid "
2835 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2837 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2838 << ": expected GL_INVALID_VALUE, got:"
2840 << error_code << "]" << tcu::TestLog::EndMessage;
2842 TCU_FAIL(error_sstream.str().c_str());
2844 } /* for (all test iterations) */
2846 /* Test case passed */
2847 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2854 * @param context Rendering context handle.
2856 DrawElementsBaseVertexNegativeInvalidModeArgumentTest::DrawElementsBaseVertexNegativeInvalidModeArgumentTest(
2857 Context& context, const ExtParameters& extParams)
2858 : DrawElementsBaseVertexTestBase(context, extParams, "invalid_mode_argument",
2859 "Tries to use invalid 'mode' argument values for the \"base vertex\" draw calls")
2861 /* Left blank on purpose */
2864 /** Executes test iteration.
2866 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2868 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidModeArgumentTest::iterate()
2870 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2872 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
2873 * in a slightly different manner.
2875 for (int iteration = 0; iteration < 4; ++iteration)
2877 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
2878 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2880 /* OpenGL does not support client-side data. */
2881 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2883 if (use_clientside_index_data || use_clientside_vertex_data)
2889 /* Set up the work environment */
2890 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2892 /* Try to execute the invalid draw calls */
2893 glw::GLenum error_code = GL_NONE;
2895 gl.drawElementsBaseVertex(GL_GREATER, /* mode */
2897 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
2899 error_code = gl.getError();
2900 if (error_code != GL_INVALID_ENUM)
2902 std::stringstream error_sstream;
2904 error_sstream << "Invalid error code reported for an invalid "
2905 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2907 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2908 << ": expected GL_INVALID_ENUM, got:"
2910 << error_code << "]" << tcu::TestLog::EndMessage;
2912 TCU_FAIL(error_sstream.str().c_str());
2915 gl.drawRangeElementsBaseVertex(GL_GREATER, /* mode */
2919 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2920 0); /* basevertex */
2922 error_code = gl.getError();
2923 if (error_code != GL_INVALID_ENUM)
2925 std::stringstream error_sstream;
2927 error_sstream << "Invalid error code reported for an invalid "
2928 << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
2930 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2931 << ": expected GL_INVALID_ENUM, got:"
2933 << error_code << "]" << tcu::TestLog::EndMessage;
2935 TCU_FAIL(error_sstream.str().c_str());
2938 gl.drawElementsInstancedBaseVertex(GL_GREATER, /* mode */
2940 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2941 1, /* instancecount */
2942 0); /* basevertex */
2944 error_code = gl.getError();
2945 if (error_code != GL_INVALID_ENUM)
2947 std::stringstream error_sstream;
2949 error_sstream << "Invalid error code reported for an invalid "
2950 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2952 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2953 << ": expected GL_INVALID_ENUM, got:"
2955 << error_code << "]" << tcu::TestLog::EndMessage;
2957 TCU_FAIL(error_sstream.str().c_str());
2960 if (m_is_ext_multi_draw_arrays_supported)
2962 const glw::GLsizei count = 3;
2963 const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
2965 gl.multiDrawElementsBaseVertex(GL_GREATER, /* mode */
2966 &count, GL_UNSIGNED_INT, offsets, 1, /* primcount */
2967 0); /* basevertex */
2969 error_code = gl.getError();
2970 if (error_code != GL_INVALID_ENUM)
2972 std::stringstream error_sstream;
2974 error_sstream << "Invalid error code reported for an invalid "
2975 << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2977 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2978 << ": expected GL_INVALID_ENUM, got:"
2980 << error_code << "]" << tcu::TestLog::EndMessage;
2982 TCU_FAIL(error_sstream.str().c_str());
2984 } /* if (m_is_ext_multi_draw_arrays_supported) */
2985 } /* for (all test iterations) */
2987 /* Test case passed */
2988 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2995 * @param context Rendering context handle.
2997 DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest::DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest(
2998 Context& context, const ExtParameters& extParams)
2999 : DrawElementsBaseVertexTestBase(
3000 context, extParams, "invalid_primcount_argument",
3001 "Tries to use invalid 'primcount' argument values for the \"base vertex\" draw calls")
3003 /* Left blank on purpose */
3006 /** Executes test iteration.
3008 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3010 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest::iterate()
3012 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3014 /* This test requires presence of GL_EXT_multi_draw_arrays under ES contexts */
3015 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
3017 if (!m_is_ext_multi_draw_arrays_supported)
3019 throw tcu::NotSupportedError("GL_EXT_multi_draw_arrays is not supported");
3023 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
3024 * in a slightly different manner.
3026 for (int iteration = 0; iteration < 4; ++iteration)
3028 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
3029 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3031 /* OpenGL does not support client-side data. */
3032 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3034 if (use_clientside_index_data || use_clientside_vertex_data)
3040 /* Set up the work environment */
3041 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3043 /* Perform the test */
3044 const glw::GLsizei count = 3;
3045 glw::GLenum error_code = GL_NO_ERROR;
3046 const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
3048 gl.multiDrawElementsBaseVertex(GL_TRIANGLES, /* mode */
3049 &count, GL_UNSIGNED_INT, offsets, -1, /* primcount */
3050 0); /* basevertex */
3052 error_code = gl.getError();
3053 if (error_code != GL_INVALID_VALUE)
3055 std::stringstream error_sstream;
3057 error_sstream << "Invalid error code reported for an invalid "
3058 << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3060 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3061 << ": expected GL_INVALID_VALUE, got:"
3063 << error_code << "]" << tcu::TestLog::EndMessage;
3065 TCU_FAIL(error_sstream.str().c_str());
3067 } /* for (all test iterations) */
3069 /* Test case passed */
3070 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3077 * @param context Rendering context handle.
3079 DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest::DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest(
3080 Context& context, const ExtParameters& extParams)
3081 : DrawElementsBaseVertexTestBase(context, extParams, "invalid_start_end_arguments",
3082 "Tries to use invalid 'start' and 'end' argument values for the "
3083 "glDrawRangeElementsBaseVertexEXT() (under ES) or "
3084 "glDrawRangeElementsBaseVertex() (under GL) draw call")
3086 /* Left blank on purpose */
3089 /** Executes test iteration.
3091 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3093 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest::iterate()
3095 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3097 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
3098 * in a slightly different manner.
3100 for (int iteration = 0; iteration < 4; ++iteration)
3102 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
3103 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3105 /* OpenGL does not support client-side data. */
3106 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3108 if (use_clientside_index_data || use_clientside_vertex_data)
3114 /* Set up the work environment */
3115 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3117 /* Try to execute the invalid draw call */
3118 glw::GLenum error_code = GL_NONE;
3120 gl.drawRangeElementsBaseVertex(GL_TRIANGLES, /* mode */
3124 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
3125 0); /* basevertex */
3127 error_code = gl.getError();
3128 if (error_code != GL_INVALID_VALUE)
3130 std::stringstream error_sstream;
3132 error_sstream << "Invalid error code reported for an invalid "
3133 << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
3135 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3136 << ": expected GL_INVALID_VALUE, got:"
3138 << error_code << "]" << tcu::TestLog::EndMessage;
3140 TCU_FAIL(error_sstream.str().c_str());
3142 } /* for (all test iterations) */
3144 /* Test case passed */
3145 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3152 * @param context Rendering context handle.
3154 DrawElementsBaseVertexNegativeInvalidTypeArgumentTest::DrawElementsBaseVertexNegativeInvalidTypeArgumentTest(
3155 Context& context, const ExtParameters& extParams)
3156 : DrawElementsBaseVertexTestBase(context, extParams, "invalid_type_argument",
3157 "Tries to use invalid 'type' argument values for the \"base vertex\" draw calls")
3159 /* Left blank on purpose */
3162 /** Executes test iteration.
3164 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3166 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidTypeArgumentTest::iterate()
3168 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3170 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
3171 * in a slightly different manner.
3173 for (int iteration = 0; iteration < 4; ++iteration)
3175 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
3176 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3178 /* OpenGL does not support client-side data. */
3179 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3181 if (use_clientside_index_data || use_clientside_vertex_data)
3187 /* Set up the work environment */
3188 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3190 /* Try to execute the invalid draw calls */
3191 glw::GLenum error_code = GL_NONE;
3193 gl.drawElementsBaseVertex(GL_TRIANGLES, /* mode */
3195 GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
3197 error_code = gl.getError();
3198 if (error_code != GL_INVALID_ENUM)
3200 std::stringstream error_sstream;
3202 error_sstream << "Invalid error code reported for an invalid "
3203 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3205 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3206 << ": expected GL_INVALID_ENUM, got:"
3208 << error_code << "]" << tcu::TestLog::EndMessage;
3210 TCU_FAIL(error_sstream.str().c_str());
3213 gl.drawRangeElementsBaseVertex(GL_TRIANGLES, /* mode */
3217 GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
3219 error_code = gl.getError();
3220 if (error_code != GL_INVALID_ENUM)
3222 std::stringstream error_sstream;
3224 error_sstream << "Invalid error code reported for an invalid "
3225 << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
3227 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3228 << ": expected GL_INVALID_ENUM, got:"
3230 << error_code << "]" << tcu::TestLog::EndMessage;
3232 TCU_FAIL(error_sstream.str().c_str());
3235 gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, /* mode */
3237 GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 1, /* instancecount */
3238 0); /* basevertex */
3240 error_code = gl.getError();
3241 if (error_code != GL_INVALID_ENUM)
3243 std::stringstream error_sstream;
3245 error_sstream << "Invalid error code reported for an invalid "
3246 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
3248 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3249 << ": expected GL_INVALID_ENUM, got:"
3251 << error_code << "]" << tcu::TestLog::EndMessage;
3253 TCU_FAIL(error_sstream.str().c_str());
3256 if (m_is_ext_multi_draw_arrays_supported)
3258 const glw::GLsizei count = 3;
3259 const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
3261 gl.multiDrawElementsBaseVertex(GL_TRIANGLES, /* mode */
3262 &count, GL_NONE, offsets, 1, /* primcount */
3263 0); /* basevertex */
3265 error_code = gl.getError();
3266 if (error_code != GL_INVALID_ENUM)
3268 std::stringstream error_sstream;
3270 error_sstream << "Invalid error code reported for an invalid "
3271 << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3273 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3274 << ": expected GL_INVALID_ENUM, got:"
3276 << error_code << "]" << tcu::TestLog::EndMessage;
3278 TCU_FAIL(error_sstream.str().c_str());
3280 } /* if (m_is_ext_multi_draw_arrays_supported) */
3281 } /* for (all test iterations) */
3283 /* Test case passed */
3284 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3291 * @param context Rendering context handle.
3293 DrawElementsBaseVertexNegativeMappedBufferObjectsTest::DrawElementsBaseVertexNegativeMappedBufferObjectsTest(
3294 Context& context, const ExtParameters& extParams)
3295 : DrawElementsBaseVertexTestBase(
3296 context, extParams, "invalid_mapped_bos",
3297 "Tries to use mapped VBO and Index Buffer Object for the \"base vertex\" draw calls")
3299 /* Left blank on purpose */
3302 /** Executes test iteration.
3304 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3306 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeMappedBufferObjectsTest::iterate()
3308 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3310 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
3311 * in a slightly different manner.
3313 for (int iteration = 0; iteration < 4; ++iteration)
3315 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
3316 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3318 /* OpenGL does not support client-side data. */
3319 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3321 if (use_clientside_index_data || use_clientside_vertex_data)
3327 /* Skip the iteration where no array buffer is used */
3328 if (use_clientside_vertex_data)
3333 /* Set up the work environment */
3334 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3336 /* Map the buffer object into process space */
3337 const glw::GLvoid* bo_ptr = gl.mapBufferRange(GL_ARRAY_BUFFER, 0, /* offset */
3338 m_bo_negative_data_vertex_size, GL_MAP_READ_BIT);
3340 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
3342 /* Perform draw calls that would otherwise have been valid, if it
3343 * were not for the mapped VBO
3345 glw::GLenum error_code = GL_NONE;
3347 gl.drawElementsBaseVertex(GL_TRIANGLES, 3, /* count */
3348 GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
3350 error_code = gl.getError();
3351 if (error_code != GL_INVALID_OPERATION)
3353 std::stringstream error_sstream;
3355 error_sstream << "Invalid error code generated by "
3356 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX);
3358 m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX)
3359 << " returned error code [" << error_code << "] instead of GL_INVALID_OPERATION."
3360 << tcu::TestLog::EndMessage;
3362 TCU_FAIL(error_sstream.str().c_str());
3363 } /* if (error_code != GL_INVALID_OPERATION) */
3365 gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, 3, /* count */
3366 GL_UNSIGNED_INT, m_draw_call_index_offset, 1, /* instancecount */
3367 0); /* basevertex */
3369 error_code = gl.getError();
3370 if (error_code != GL_INVALID_OPERATION)
3372 std::stringstream error_sstream;
3374 error_sstream << "Invalid error code generated by "
3375 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX);
3377 m_testCtx.getLog() << tcu::TestLog::Message
3378 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX)
3379 << " returned error code [" << error_code << "] instead of GL_INVALID_OPERATION."
3380 << tcu::TestLog::EndMessage;
3382 TCU_FAIL(error_sstream.str().c_str());
3385 gl.drawRangeElementsBaseVertex(GL_TRIANGLES, 0, 2, /* end */
3387 GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
3389 error_code = gl.getError();
3390 if (error_code != GL_INVALID_OPERATION)
3392 std::stringstream error_sstream;
3394 error_sstream << "Invalid error code generated by "
3395 << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX);
3397 m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX)
3398 << " returned error code [" << error_code << "] instead of GL_INVALID_OPERATION."
3399 << tcu::TestLog::EndMessage;
3401 TCU_FAIL(error_sstream.str().c_str());
3404 /* Unmap the BO before we proceed */
3405 gl.unmapBuffer(GL_ARRAY_BUFFER);
3406 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
3408 } /* for (all test iterations) */
3410 /* Test case passed */
3411 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3418 * @param context Rendering context.
3420 DrawElementsBaseVertexTests::DrawElementsBaseVertexTests(glcts::Context& context, const ExtParameters& extParams)
3421 : TestCaseGroupBase(context, extParams, "draw_elements_base_vertex_tests",
3422 "Contains conformance tests that verify ES and GL implementation's support "
3423 "for GL_EXT_draw_elements_base_vertex (ES) and "
3424 "GL_ARB_draw_elements_base_vertex (GL) extensions.")
3428 /** Initializes the test group contents. */
3429 void DrawElementsBaseVertexTests::init()
3431 addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior(m_context, m_extParams));
3432 addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2(m_context, m_extParams));
3433 addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages(m_context, m_extParams));
3434 addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow(m_context, m_extParams));
3435 addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow(m_context, m_extParams));
3436 addChild(new DrawElementsBaseVertexNegativeActiveTransformFeedbackTest(m_context, m_extParams));
3437 addChild(new DrawElementsBaseVertexNegativeInvalidCountArgumentTest(m_context, m_extParams));
3438 addChild(new DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest(m_context, m_extParams));
3439 addChild(new DrawElementsBaseVertexNegativeInvalidModeArgumentTest(m_context, m_extParams));
3440 addChild(new DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest(m_context, m_extParams));
3441 addChild(new DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest(m_context, m_extParams));
3442 addChild(new DrawElementsBaseVertexNegativeInvalidTypeArgumentTest(m_context, m_extParams));
3443 addChild(new DrawElementsBaseVertexNegativeMappedBufferObjectsTest(m_context, m_extParams));
3446 } /* glcts namespace */