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()";
849 result = "glDrawElementsBaseVertex()";
855 case FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX:
857 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
859 result = "glDrawElementsInstancedBaseVertexEXT()";
863 result = "glDrawElementsInstancedBaseVertex()";
869 case FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX:
871 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
873 result = "glDrawRangeElementsBaseVertexEXT()";
877 result = "glDrawRangeElementsBaseVertex()";
883 case FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX:
885 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
887 result = "glMultiDrawElementsBaseVertexEXT()";
891 result = "glMultiDrawElementsBaseVertex()";
899 TCU_FAIL("Unknown function type");
901 } /* switch (function_type) */
906 /** Initializes extension-specific function pointers and caches information about
907 * extension availability.
909 * Function pointers for the following extensions are retrieved & stored:
911 * - GL_EXT_draw_elements_base_vertex (ES) or GL_ARB_draw_elements_base_vertex (GL)
912 * - GL_EXT_multi_draw_arrays (ES & GL)
914 * Availability of the following extensions is checked & cached:
916 * - GL_EXT_draw_elements_base_vertex (ES) or GL_ARB_draw_elements_base_vertex (GL)
917 * - GL_EXT_geometry_shader (ES) or GL_ARB_geometry_shader4 (GL)
918 * - GL_EXT_multi_draw_arrays (ES & GL)
919 * - GL_EXT_tessellation_shader (ES) or GL_ARB_tessellation_shader (GL)
921 void DrawElementsBaseVertexTestBase::init()
923 TestCaseBase::init();
925 const glu::ContextInfo& context_info = m_context.getContextInfo();
927 if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
928 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
929 context_info.isExtensionSupported("GL_EXT_draw_elements_base_vertex"))) ||
930 context_info.isExtensionSupported("GL_ARB_draw_elements_base_vertex"))
932 #if defined(DE_DEBUG) && !defined(DE_COVERAGE_BUILD)
933 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
936 m_is_draw_elements_base_vertex_supported = true;
938 DE_ASSERT(gl.drawElementsBaseVertex != NULL);
939 DE_ASSERT(gl.drawElementsInstancedBaseVertex != NULL);
940 DE_ASSERT(gl.drawRangeElementsBaseVertex != NULL);
942 /* NOTE: glMultiDrawElementsBaseVertex() is a part of the draw_elements_base_vertex extension in GL,
943 * but requires a separate extension under ES.
945 if (!glu::isContextTypeES(m_context.getRenderContext().getType()) ||
946 context_info.isExtensionSupported("GL_EXT_multi_draw_arrays"))
948 m_is_ext_multi_draw_arrays_supported = true;
950 DE_ASSERT(gl.multiDrawElementsBaseVertex != NULL);
951 } /* if (GL_EXT_multi_draw_arrays is supported or GL context is being tested) */
953 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
955 /* This conformance test needs to be adjusted in order to run under < ES3.1 contexts */
956 DE_ASSERT(glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 1)));
960 m_is_vertex_attrib_binding_supported = context_info.isExtensionSupported("GL_ARB_vertex_attrib_binding");
962 } /* if (GL_{ARB, EXT}_draw_elements_base_vertex is supported) */
964 if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
965 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
966 context_info.isExtensionSupported("GL_EXT_geometry_shader"))) ||
967 context_info.isExtensionSupported("GL_ARB_geometry_shader4"))
969 m_is_geometry_shader_supported = true;
972 if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
973 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
974 context_info.isExtensionSupported("GL_EXT_tessellation_shader"))) ||
975 context_info.isExtensionSupported("GL_ARB_tessellation_shader"))
977 m_is_tessellation_shader_supported = true;
980 if (!m_is_draw_elements_base_vertex_supported)
982 throw tcu::NotSupportedError("draw_elements_base_vertex functionality is not supported");
986 /** Sets up all ES objects required to run a single functional test case iteration.
988 * @param use_clientside_vertex_data true if the test case requires client-side buffers to
989 * back the color/vertex vertex attribute arrays; false
990 * to use buffer object storage.
991 * @param use_clientside_index_data true if the test case requires client-side buffers to
992 * be used as index data source; false to use buffer object
994 * @param use_tessellation_shader_stage true if the program object used for the test should include
995 * tessellation control & evaluation shader stages; false to
996 * not to include these shader stages in the pipeline.
997 * @param use_geometry_shader_stage true if the program object used for the test should include
998 * geometry shader stage; false to not to include the shader
999 * stage in the pipeline.
1000 * @param use_vertex_attrib_binding true if vertex attribute bindings should be used for
1001 * vertex array object configuration. This also modifies the
1002 * vertex shader, so that instead of calculating vertex color
1003 * on a per-vertex basis, contents of the "color" input
1004 * will be used as a data source for the color data.
1005 * false to use a vertex attribute array configured with
1006 * a casual glVertexAttribPointer() call.
1007 * @param use_overflow_test_vertices true if using an especially large vertex array to test
1008 * overflow behavior.
1010 * This method can throw an exception if any of the ES calls fail.
1012 void DrawElementsBaseVertexTestBase::setUpFunctionalTestObjects(
1013 bool use_clientside_vertex_data, bool use_clientside_index_data, bool use_tessellation_shader_stage,
1014 bool use_geometry_shader_stage, bool use_vertex_attrib_binding, bool use_overflow_test_vertices)
1016 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1018 /* Set up a texture object that we will use as a color attachment */
1019 gl.genTextures(1, &m_to_base_id);
1020 gl.genTextures(1, &m_to_ref_id);
1021 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed.");
1023 const glw::GLuint to_ids[] = { m_to_base_id, m_to_ref_id };
1024 const unsigned int n_to_ids = sizeof(to_ids) / sizeof(to_ids[0]);
1026 for (unsigned int n_to_id = 0; n_to_id < n_to_ids; ++n_to_id)
1028 gl.bindTexture(GL_TEXTURE_2D, to_ids[n_to_id]);
1029 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
1031 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
1032 GL_RGBA8, m_to_width, m_to_height);
1033 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
1036 /* Also set up some buffers we will use for data comparison */
1037 m_to_base_data = new unsigned char[m_to_width * m_to_height * 4 /* components */];
1038 m_to_ref_data = new unsigned char[m_to_width * m_to_height * 4 /* components */];
1040 /* Finally, for glReadPixels() operations, we need to make sure that pack alignment is set to 1 */
1041 gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
1042 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
1044 /* Proceed with framebuffer object initialization. Since we will be rendering to different
1045 * render-targets, there's not much point in attaching any of the textures at this point.
1047 gl.genFramebuffers(1, &m_fbo_id);
1048 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
1050 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
1051 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebufer() call failed");
1053 gl.viewport(0, /* x */
1055 m_to_width, m_to_height);
1056 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed");
1058 /* Set up buffer object we will use for the draw calls. Use the data
1059 * from the test specification.
1061 * NOTE: If you need to change the data layout here, make sure you also update
1062 * m_draw_call_color_offset, m_draw_call_index*_offset, and
1063 * m_draw_call_vertex*_offset setter calls elsewhere.
1067 unsigned int current_offset = 0;
1069 gl.genBuffers(1, &m_bo_id);
1070 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1072 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1073 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1075 gl.bufferData(GL_ARRAY_BUFFER,
1076 m_bo_functional_data_index_size + m_bo_functional_data_vertex_size +
1077 m_bo_functional2_data_vertex_size + m_bo_functional2_data_index_size +
1078 m_bo_functional3_data_index_size + m_bo_functional4_data_index_size +
1079 m_bo_functional5_data_index_size + m_bo_functional_data_color_size,
1082 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1084 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_vertex_size,
1085 m_bo_functional_data_vertex);
1086 current_offset += m_bo_functional_data_vertex_size;
1088 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional2_data_vertex_size,
1089 m_bo_functional2_data_vertex);
1090 current_offset += m_bo_functional2_data_vertex_size;
1092 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_index_size, m_bo_functional_data_index);
1093 current_offset += m_bo_functional_data_index_size;
1095 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional2_data_index_size,
1096 m_bo_functional2_data_index);
1097 current_offset += m_bo_functional2_data_index_size;
1099 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional3_data_index_size,
1100 m_bo_functional3_data_index);
1101 current_offset += m_bo_functional3_data_index_size;
1103 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional4_data_index_size,
1104 m_bo_functional4_data_index);
1105 current_offset += m_bo_functional4_data_index_size;
1107 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional5_data_index_size,
1108 m_bo_functional5_data_index);
1109 current_offset += m_bo_functional5_data_index_size;
1111 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_color_size, m_bo_functional_data_color);
1112 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
1115 if (use_overflow_test_vertices && m_bo_id_2 == 0)
1117 /* Create a special buffer that only has vertex data in a few slots */
1118 gl.genBuffers(1, &m_bo_id_2);
1119 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
1121 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_2);
1122 gl.bufferData(GL_ARRAY_BUFFER, 2 * 65550 * sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
1123 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
1126 * Upload to offset 0: regular draw call indices for making sure ubyte
1127 * and ushort indices don't wrap around too early
1128 * Upload to offset 256: base draw call indices of type ubyte
1129 * Upload to offset 65536: base draw call indices of type ushort
1131 glw::GLfloat badVtx[] = { 0.9f, 0.9f, -0.9f, 0.9f, -0.9f, -0.9f, 0.9f, -0.9f, 0.9f, 0.9f, -0.9f, 0.9f,
1132 -0.9f, -0.9f, 0.9f, -0.9f, 0.9f, 0.9f, -0.9f, 0.9f, -0.9f, -0.9f, 0.9f, -0.9f };
1133 gl.bufferSubData(GL_ARRAY_BUFFER, 0, sizeof(badVtx), badVtx);
1134 gl.bufferSubData(GL_ARRAY_BUFFER, 2 * 256 * sizeof(glw::GLfloat), 2 * 12 * sizeof(glw::GLfloat),
1135 m_bo_functional_data_vertex);
1136 gl.bufferSubData(GL_ARRAY_BUFFER, 2 * 65536 * sizeof(glw::GLfloat), 2 * 12 * sizeof(glw::GLfloat),
1137 m_bo_functional_data_vertex);
1138 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed");
1141 /* Set up the test program object */
1142 if (m_po_id == 0 || m_po_uses_gs_stage != use_geometry_shader_stage ||
1143 m_po_uses_tc_te_stages != use_tessellation_shader_stage ||
1144 m_po_uses_vertex_attrib_binding != use_vertex_attrib_binding)
1147 static const char* functional_fs_code = "${VERSION}\n"
1149 "precision highp float;\n"
1151 "in vec4 FS_COLOR_INPUT_NAME;\n"
1152 "out vec4 result;\n"
1156 " result = FS_COLOR_INPUT_NAME;\n"
1158 static const char* functional_gs_code = "${VERSION}\n"
1159 "${GEOMETRY_SHADER_REQUIRE}\n"
1161 "layout(triangles) in;\n"
1162 "layout(triangle_strip, max_vertices = 3) out;\n"
1164 "in vec4 GS_COLOR_INPUT_NAME[];\n"
1165 "out vec4 FS_COLOR_INPUT_NAME;\n"
1169 " for (int n = 0; n < 3; ++n)\n"
1171 " gl_Position = vec4(gl_in[n].gl_Position.x, "
1172 "-gl_in[n].gl_Position.y, gl_in[n].gl_Position.zw);\n"
1173 " FS_COLOR_INPUT_NAME = GS_COLOR_INPUT_NAME[n];\n"
1178 " EndPrimitive();\n"
1180 static const char* functional_tc_code =
1182 "${TESSELLATION_SHADER_REQUIRE}\n"
1184 "in vec4 TC_COLOR_INPUT_NAME[];\n"
1185 "out vec4 TE_COLOR_INPUT_NAME[];\n"
1187 "layout(vertices = 3) out;\n"
1191 " gl_out [gl_InvocationID].gl_Position = gl_in [gl_InvocationID].gl_Position;\n"
1192 " TE_COLOR_INPUT_NAME[gl_InvocationID] = TC_COLOR_INPUT_NAME[gl_InvocationID];\n"
1194 " gl_TessLevelInner[0] = 3.0;\n"
1195 " gl_TessLevelOuter[0] = 3.0;\n"
1196 " gl_TessLevelOuter[1] = 3.0;\n"
1197 " gl_TessLevelOuter[2] = 3.0;\n"
1199 static const char* functional_te_code =
1202 "${TESSELLATION_SHADER_REQUIRE}\n"
1204 "layout(triangles, equal_spacing, cw) in;\n"
1206 "in vec4 TE_COLOR_INPUT_NAME[];\n"
1207 "out vec4 TE_COLOR_OUTPUT_NAME;\n"
1211 " vec2 p1 = gl_in[0].gl_Position.xy;\n"
1212 " vec2 p2 = gl_in[1].gl_Position.xy;\n"
1213 " vec2 p3 = gl_in[2].gl_Position.xy;\n"
1215 " TE_COLOR_OUTPUT_NAME = TE_COLOR_INPUT_NAME[0] + TE_COLOR_INPUT_NAME[1] + TE_COLOR_INPUT_NAME[2];\n"
1216 " gl_Position = vec4(gl_TessCoord.x * p1.x + gl_TessCoord.y * p2.x + gl_TessCoord.z * p3.x,\n"
1217 " gl_TessCoord.x * p1.y + gl_TessCoord.y * p2.y + gl_TessCoord.z * p3.y,\n"
1221 static const char* functional_vs_code = "${VERSION}\n"
1223 "out vec4 VS_COLOR_OUTPUT_NAME;\n"
1226 "OPTIONAL_USE_VERTEX_ATTRIB_BINDING_DEFINITIONS\n"
1230 " float vertex_id_float = float(gl_VertexID);\n"
1232 "#ifdef USE_VERTEX_ATTRIB_BINDING\n"
1233 " vec4 color = in_color;\n"
1235 " vec4 color = vec4(vertex_id_float / 7.0,\n"
1236 " vertex_id_float / 3.0,\n"
1237 " vertex_id_float / 17.0,\n"
1240 " float scale = (gl_InstanceID == 0) ? 1.0 :\n"
1241 " (gl_InstanceID == 1) ? 0.8 :\n"
1244 " VS_COLOR_OUTPUT_NAME = color;\n"
1245 " gl_Position = vec4(vertex.xy * scale, vertex.zw);\n"
1248 /* Release a program object if one has already been set up for the running test */
1249 deinitProgramAndShaderObjects();
1251 /* Replace the tokens with actual variable names */
1252 std::string fs_body = specializeShader(1, &functional_fs_code);
1253 std::string fs_color_input_name_token = "FS_COLOR_INPUT_NAME";
1254 std::string fs_color_input_name_token_value;
1255 std::string gs_body = specializeShader(1, &functional_gs_code);
1256 std::string gs_color_input_name_token = "GS_COLOR_INPUT_NAME";
1257 std::string gs_color_input_name_token_value;
1258 std::string tc_body = specializeShader(1, &functional_tc_code);
1259 std::string tc_color_input_name_token = "TC_COLOR_INPUT_NAME";
1260 std::string tc_color_input_name_token_value;
1261 std::string te_body = specializeShader(1, &functional_te_code);
1262 std::string te_color_input_name_token = "TE_COLOR_INPUT_NAME";
1263 std::string te_color_input_name_token_value;
1264 std::string te_color_output_name_token = "TE_COLOR_OUTPUT_NAME";
1265 std::string te_color_output_name_token_value;
1266 std::string vs_body = specializeShader(1, &functional_vs_code);
1267 std::string vs_color_output_name_token = "VS_COLOR_OUTPUT_NAME";
1268 std::string vs_color_output_name_token_value;
1269 std::string vs_optional_use_vertex_attrib_binding_definitions_token =
1270 "OPTIONAL_USE_VERTEX_ATTRIB_BINDING_DEFINITIONS";
1271 std::string vs_optional_use_vertex_attrib_binding_definitions_token_value;
1273 std::string* bodies[] = { &fs_body, &gs_body, &tc_body, &te_body, &vs_body };
1274 const unsigned int n_bodies = sizeof(bodies) / sizeof(bodies[0]);
1276 std::string* token_value_pairs[] = { &fs_color_input_name_token,
1277 &fs_color_input_name_token_value,
1278 &gs_color_input_name_token,
1279 &gs_color_input_name_token_value,
1280 &tc_color_input_name_token,
1281 &tc_color_input_name_token_value,
1282 &te_color_input_name_token,
1283 &te_color_input_name_token_value,
1284 &te_color_output_name_token,
1285 &te_color_output_name_token_value,
1286 &vs_color_output_name_token,
1287 &vs_color_output_name_token_value,
1288 &vs_optional_use_vertex_attrib_binding_definitions_token,
1289 &vs_optional_use_vertex_attrib_binding_definitions_token_value };
1290 const unsigned int n_token_value_pairs =
1291 sizeof(token_value_pairs) / sizeof(token_value_pairs[0]) / 2 /* token+value */;
1293 if (!use_tessellation_shader_stage)
1295 if (!use_geometry_shader_stage)
1297 /* Geometry & tessellation shader stages are not required.
1299 * NOTE: This code-path is also used by Functional Test VII which verifies that
1300 * vertex attribute bindings work correctly with basevertex draw calls.
1301 * The test only uses FS & VS in its rendering pipeline and consumes a color
1302 * taken from an enabled vertex attribute array instead of a vector value
1303 * calculated in vertex shader stage,
1305 vs_color_output_name_token_value = "out_vs_color";
1306 fs_color_input_name_token_value = vs_color_output_name_token_value;
1308 if (use_vertex_attrib_binding)
1310 vs_optional_use_vertex_attrib_binding_definitions_token_value =
1311 "#define USE_VERTEX_ATTRIB_BINDING\n"
1312 "in vec4 in_color;\n";
1314 } /* if (!use_geometry_shader_stage) */
1317 /* Geometry shader stage is needed, but tessellation shader stage
1319 fs_color_input_name_token_value = "out_fs_color";
1320 gs_color_input_name_token_value = "out_vs_color";
1321 vs_color_output_name_token_value = "out_vs_color";
1323 DE_ASSERT(!use_vertex_attrib_binding);
1325 } /* if (!use_tessellation_shader_stage) */
1328 DE_ASSERT(!use_vertex_attrib_binding);
1330 if (!use_geometry_shader_stage)
1332 /* Tessellation shader stage is needed, but geometry shader stage
1334 fs_color_input_name_token_value = "out_fs_color";
1335 tc_color_input_name_token_value = "out_vs_color";
1336 te_color_input_name_token_value = "out_tc_color";
1337 te_color_output_name_token_value = "out_fs_color";
1338 vs_color_output_name_token_value = "out_vs_color";
1339 } /* if (!use_geometry_shader_stage) */
1342 /* Both tessellation and geometry shader stages are needed */
1343 fs_color_input_name_token_value = "out_fs_color";
1344 gs_color_input_name_token_value = "out_te_color";
1345 tc_color_input_name_token_value = "out_vs_color";
1346 te_color_input_name_token_value = "out_tc_color";
1347 te_color_output_name_token_value = "out_te_color";
1348 vs_color_output_name_token_value = "out_vs_color";
1352 for (unsigned int n_body = 0; n_body < n_bodies; ++n_body)
1354 std::string* body_ptr = bodies[n_body];
1356 for (unsigned int n_token_value_pair = 0; n_token_value_pair < n_token_value_pairs; ++n_token_value_pair)
1358 std::string token = *token_value_pairs[2 * n_token_value_pair + 0];
1359 std::size_t token_location = std::string::npos;
1360 std::string value = *token_value_pairs[2 * n_token_value_pair + 1];
1362 while ((token_location = body_ptr->find(token)) != std::string::npos)
1364 body_ptr->replace(token_location, token.length(), value);
1365 } /* while (tokens are found) */
1366 } /* for (all token+value pairs) */
1367 } /* for (all bodies) */
1369 /* Build the actual program */
1370 buildProgram(fs_body.c_str(), vs_body.c_str(), use_tessellation_shader_stage ? tc_body.c_str() : DE_NULL,
1371 use_tessellation_shader_stage ? te_body.c_str() : DE_NULL,
1372 use_geometry_shader_stage ? gs_body.c_str() : DE_NULL);
1374 m_po_uses_gs_stage = use_geometry_shader_stage;
1375 m_po_uses_tc_te_stages = use_tessellation_shader_stage;
1376 m_po_uses_vertex_attrib_binding = use_vertex_attrib_binding;
1379 /* Set up the vertex array object */
1382 gl.deleteVertexArrays(1, &m_vao_id);
1383 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
1388 if (!use_clientside_vertex_data)
1390 gl.genVertexArrays(1, &m_vao_id);
1391 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1393 gl.bindVertexArray(m_vao_id);
1394 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1396 if (m_po_color_attribute_location != -1)
1398 DE_ASSERT(use_vertex_attrib_binding);
1400 gl.enableVertexAttribArray(m_po_color_attribute_location);
1403 gl.enableVertexAttribArray(m_po_vertex_attribute_location);
1404 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call(s) failed.");
1406 /* Configure the VAO */
1407 if (use_clientside_index_data)
1409 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1410 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1414 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id);
1415 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1418 if (use_clientside_vertex_data)
1420 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1421 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1425 gl.bindBuffer(GL_ARRAY_BUFFER, use_overflow_test_vertices ? m_bo_id_2 : m_bo_id);
1426 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1429 if (!use_vertex_attrib_binding)
1431 DE_ASSERT(m_po_color_attribute_location == -1);
1433 gl.vertexAttribPointer(m_po_vertex_attribute_location, 2, /* size */
1434 GL_FLOAT, GL_FALSE, /* normalized */
1436 m_draw_call_vertex_offset);
1437 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
1438 } /* if (!use_vertex_attrib_binding) */
1441 DE_ASSERT(m_po_color_attribute_location != -1);
1442 DE_ASSERT(m_draw_call_vertex_offset < m_draw_call_color_offset);
1444 gl.vertexAttribFormat(m_po_color_attribute_location, 2, /* size */
1445 GL_FLOAT, /* type */
1446 GL_FALSE, /* normalized */
1447 (glw::GLuint)((const glw::GLubyte*)m_draw_call_color_offset -
1448 (const glw::GLubyte*)m_draw_call_vertex_offset));
1449 gl.vertexAttribFormat(m_po_vertex_attribute_location, 2, /* size */
1450 GL_FLOAT, /* type */
1451 GL_FALSE, /* normalized */
1452 0); /* relativeoffset */
1453 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribFormat() call(s) failed.");
1455 gl.vertexAttribBinding(m_po_color_attribute_location, 0); /* bindingindex */
1456 gl.vertexAttribBinding(m_po_vertex_attribute_location, 0); /* bindingindex */
1457 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribBinding() call(s) failed.");
1459 gl.bindVertexBuffer(0, /* bindingindex */
1460 (use_clientside_vertex_data) ? 0 : (use_overflow_test_vertices ? m_bo_id_2 : m_bo_id),
1461 (glw::GLintptr)m_draw_call_vertex_offset, sizeof(float) * 2);
1462 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexBuffer() call failed.");
1465 /* Bind the program object to the rendering context */
1466 gl.useProgram(m_po_id);
1467 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1470 /** Sets up all ES objects required to run a single negative test case iteration.
1472 * @param use_clientside_vertex_data true if the test case requires client-side buffers to
1473 * back the color/vertex vertex attribute arrays; false
1474 * to use buffer object storage.
1475 * @param use_clientside_index_data true if the test case requires client-side buffers to
1476 * be used as index data source; false to use buffer object
1479 void DrawElementsBaseVertexTestBase::setUpNegativeTestObjects(bool use_clientside_vertex_data,
1480 bool use_clientside_index_data)
1482 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1484 /* Set up buffer object we will use for the draw calls. Use the data
1485 * from the test specification */
1488 gl.genBuffers(1, &m_bo_id);
1489 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1491 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1492 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1494 gl.bufferData(GL_ARRAY_BUFFER, m_bo_negative_data_index_size + m_bo_negative_data_vertex_size,
1497 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1499 gl.bufferSubData(GL_ARRAY_BUFFER, 0, /* offset */
1500 m_bo_negative_data_vertex_size, m_bo_negative_data_vertex);
1501 gl.bufferSubData(GL_ARRAY_BUFFER, m_bo_negative_data_vertex_size, /* offset */
1502 m_bo_negative_data_index_size, m_bo_negative_data_index);
1503 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
1506 if (use_clientside_index_data)
1508 m_draw_call_index_offset = m_bo_negative_data_index;
1512 m_draw_call_index_offset = (const glw::GLuint*)(deUintptr)m_bo_negative_data_vertex_size;
1515 if (use_clientside_vertex_data)
1517 m_draw_call_vertex_offset = m_bo_negative_data_vertex;
1521 m_draw_call_vertex_offset = DE_NULL;
1524 /* Set up the test program object */
1527 static const char* negative_fs_code = "${VERSION}\n"
1528 "precision highp float;\n"
1530 "out vec4 result;\n"
1534 " result = vec4(1.0);\n"
1536 static const char* negative_vs_code = "${VERSION}\n"
1542 " gl_Position = vertex;\n"
1545 std::string fs_specialized_code = specializeShader(1, &negative_fs_code);
1546 const char* fs_specialized_code_raw = fs_specialized_code.c_str();
1547 std::string vs_specialized_code = specializeShader(1, &negative_vs_code);
1548 const char* vs_specialized_code_raw = vs_specialized_code.c_str();
1550 buildProgram(fs_specialized_code_raw, vs_specialized_code_raw, DE_NULL, /* tc_code */
1551 DE_NULL, /* te_code */
1552 DE_NULL); /* gs_code */
1555 /* Set up a vertex array object */
1558 gl.genVertexArrays(1, &m_vao_id);
1559 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1561 gl.bindVertexArray(m_vao_id);
1562 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1564 gl.enableVertexAttribArray(m_po_vertex_attribute_location);
1565 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
1568 /* Configure the VAO */
1569 if (use_clientside_index_data)
1571 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1572 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1576 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id);
1577 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1580 if (use_clientside_vertex_data)
1582 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1583 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1585 gl.bindVertexArray(0);
1586 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1590 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1591 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1594 gl.vertexAttribPointer(m_po_vertex_attribute_location, 2, /* size */
1595 GL_FLOAT, GL_FALSE, /* normalized */
1597 m_draw_call_vertex_offset);
1598 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
1600 /* Bind the program object to the rendering context */
1601 gl.useProgram(m_po_id);
1602 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1607 * @param context Rendering context handle.
1609 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior(
1610 Context& context, const ExtParameters& extParams)
1611 : DrawElementsBaseVertexTestBase(context, extParams, "basevertex_behavior1",
1612 "Verifies basevertex draw calls work correctly for a number of "
1613 "different rendering pipeline and VAO configurations")
1615 /* Left blank on purpose */
1618 /** Sets up test case descriptors for the test instance. These will later be used
1619 * as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1620 * the actual testing.
1622 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::setUpTestCases()
1624 /* Set up test case descriptors */
1625 const glw::GLint basevertex_values[] = { 10, 0 };
1626 const unsigned int n_basevertex_values = sizeof(basevertex_values) / sizeof(basevertex_values[0]);
1628 /* The test needs to be run in two iterations, using client-side memory and buffer object
1629 * for index data respectively
1631 for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1633 /* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1634 * See section 11.1.3.9 in OpenGL ES 3.1 spec
1636 bool use_clientside_vertex_data = 0;
1637 bool use_clientside_index_data = ((vao_iteration & (1 << 0)) != 0);
1639 /* OpenGL does not support client-side data. */
1640 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1642 if (use_clientside_index_data || use_clientside_vertex_data)
1648 /* Compute the offsets */
1649 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1651 /* There are two index data sets we need to iterate over */
1652 const glw::GLuint* index_offsets[] = { m_draw_call_index_offset, m_draw_call_index2_offset };
1653 const unsigned int n_index_offsets = sizeof(index_offsets) / sizeof(index_offsets[0]);
1655 for (unsigned int n_index_offset = 0; n_index_offset < n_index_offsets; ++n_index_offset)
1657 const glw::GLuint* current_index_offset = index_offsets[n_index_offset];
1659 /* We need to test four different functions:
1661 * a) glDrawElementsBaseVertex() (GL)
1662 * or glDrawElementsBaseVertexEXT() (ES)
1663 * b) glDrawRangeElementsBaseVertex() (GL)
1664 * or glDrawRangeElementsBaseVertexEXT() (ES)
1665 * c) glDrawElementsInstancedBaseVertex() (GL)
1666 * or glDrawElementsInstancedBaseVertexEXT() (ES)
1667 * d) glMultiDrawElementsBaseVertex() (GL)
1668 * or glMultiDrawElementsBaseVertexEXT() (ES) (if supported)
1670 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1672 /* Do not try to use the multi draw call if relevant extension is
1674 if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1679 /* We need to run the test for a number of different basevertex values. */
1680 for (unsigned int n_basevertex_value = 0; n_basevertex_value < n_basevertex_values;
1681 ++n_basevertex_value)
1683 /* Finally, we want to verify that basevertex draw calls work correctly both when vertex attribute
1684 * bindings are enabled and disabled */
1685 bool vertex_attrib_binding_statuses[] = { false, true };
1686 unsigned int n_vertex_attrib_binding_statuses =
1687 sizeof(vertex_attrib_binding_statuses) / sizeof(vertex_attrib_binding_statuses[0]);
1689 for (unsigned int n_vertex_attrib_binding_status = 0;
1690 n_vertex_attrib_binding_status < n_vertex_attrib_binding_statuses;
1691 ++n_vertex_attrib_binding_status)
1693 bool use_vertex_attrib_binding = vertex_attrib_binding_statuses[n_vertex_attrib_binding_status];
1695 /* Under GL, "vertex attrib binding" functionality is only available if GL_ARB_vertex_attrib_binding
1696 * extension is supported.
1698 if (!m_is_vertex_attrib_binding_supported && use_vertex_attrib_binding)
1703 /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1704 const glw::GLsizei multi_draw_call_count_array[3] = { 3, 6, 3 };
1705 const glw::GLuint* multi_draw_call_indices_array[3] = {
1706 (glw::GLuint*)(current_index_offset), (glw::GLuint*)(current_index_offset + 3),
1707 (glw::GLuint*)(current_index_offset + 9)
1710 /* Reference texture should always reflect basevertex=10 behavior. */
1711 const glw::GLuint regular_draw_call_offset = basevertex_values[0];
1712 const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1713 multi_draw_call_indices_array[0] + regular_draw_call_offset,
1714 multi_draw_call_indices_array[1] + regular_draw_call_offset,
1715 multi_draw_call_indices_array[2] + regular_draw_call_offset,
1718 /* Construct the test case descriptor */
1719 _test_case new_test_case;
1721 new_test_case.basevertex = basevertex_values[n_basevertex_value];
1722 new_test_case.function_type = (_function_type)n_function;
1723 new_test_case.index_offset = current_index_offset;
1724 new_test_case.range_start = n_index_offset == 0 ? 0 : 10;
1725 new_test_case.range_end = n_index_offset == 0 ? 22 : 32;
1726 new_test_case.index_type = GL_UNSIGNED_INT;
1727 new_test_case.primitive_mode = GL_TRIANGLES;
1728 new_test_case.regular_draw_call_offset = basevertex_values[0];
1729 new_test_case.should_base_texture_match_reference_texture =
1730 ((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
1731 new_test_case.use_clientside_index_data = use_clientside_index_data;
1732 new_test_case.use_clientside_vertex_data = use_clientside_vertex_data;
1733 new_test_case.use_geometry_shader_stage = false;
1734 new_test_case.use_tessellation_shader_stage = false;
1735 new_test_case.use_vertex_attrib_binding = use_vertex_attrib_binding;
1737 memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1738 sizeof(multi_draw_call_count_array));
1739 memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1740 sizeof(multi_draw_call_indices_array));
1741 memcpy(new_test_case.regular_multi_draw_call_offseted_array,
1742 regular_multi_draw_call_offseted_array, sizeof(regular_multi_draw_call_offseted_array));
1744 m_test_cases.push_back(new_test_case);
1745 } /* for (all vertex_attrib_binding statuses) */
1746 } /* for (all basevertex values) */
1747 } /* for (all four functions) */
1748 } /* for (all index data sets) */
1749 } /* for (all VAO iterations) */
1752 /** Executes test iteration.
1754 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1756 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::iterate()
1761 /* Test case passed */
1762 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1769 * @param context Rendering context handle.
1771 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2(
1772 Context& context, const ExtParameters& extParams)
1773 : DrawElementsBaseVertexTestBase(context, extParams, "basevertex_behavior2",
1774 "Verifies basevertex draw calls work correctly for a number of "
1775 "different rendering pipeline and VAO configurations. Uses slightly "
1776 "different data set than basevertex_behavior.")
1778 /* Left blank on purpose */
1781 /** Sets up test case descriptors for the test instance. These will later be used
1782 * as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1783 * the actual testing.
1785 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::setUpTestCases()
1787 /* Set up test case descriptors */
1788 const glw::GLint basevertex = 5;
1790 /* The test needs to be run in two iterations, using client-side memory and buffer object
1791 * for index data respectively
1793 for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1795 /* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1796 * See section 11.1.3.9 in OpenGL ES 3.1 spec
1798 bool use_clientside_vertex_data = 0;
1799 bool use_clientside_index_data = ((vao_iteration & (1 << 0)) != 0);
1801 /* OpenGL does not support client-side data. */
1802 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1804 if (use_clientside_index_data || use_clientside_vertex_data)
1810 /* Compute the offsets */
1811 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1813 /* We need to test four different functions:
1815 * a) glDrawElementsBaseVertex() (GL)
1816 * or glDrawElementsBaseVertexEXT() (ES)
1817 * b) glDrawRangeElementsBaseVertex() (GL)
1818 * or glDrawRangeElementsBaseVertexEXT() (ES)
1819 * c) glDrawElementsInstancedBaseVertex() (GL)
1820 * or glDrawElementsInstancedBaseVertexEXT() (ES)
1821 * d) glMultiDrawElementsBaseVertex() (GL)
1822 * or glMultiDrawElementsBaseVertexEXT() (ES) (if supported)
1824 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1826 /* Do not try to use the multi draw call if relevant extension is
1828 if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1833 /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1834 const glw::GLsizei multi_draw_call_count_array[3] = { 3, 6, 3 };
1835 const glw::GLuint* multi_draw_call_indices_array[3] = { (glw::GLuint*)(m_draw_call_index_offset),
1836 (glw::GLuint*)(m_draw_call_index_offset + 3),
1837 (glw::GLuint*)(m_draw_call_index_offset + 9) };
1839 /* Reference texture should always reflect basevertex=10 behavior. */
1840 const glw::GLuint regular_draw_call_offset = 0;
1841 const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1842 multi_draw_call_indices_array[0] + regular_draw_call_offset,
1843 multi_draw_call_indices_array[1] + regular_draw_call_offset,
1844 multi_draw_call_indices_array[2] + regular_draw_call_offset,
1847 /* Construct the test case descriptor */
1848 _test_case new_test_case;
1850 new_test_case.basevertex = basevertex;
1851 new_test_case.function_type = (_function_type)n_function;
1852 new_test_case.index_offset = m_draw_call_index_offset;
1853 new_test_case.range_start = 0;
1854 new_test_case.range_end = 22;
1855 new_test_case.index_type = GL_UNSIGNED_INT;
1856 new_test_case.primitive_mode = GL_TRIANGLES;
1857 new_test_case.regular_draw_call_offset = regular_draw_call_offset;
1858 new_test_case.should_base_texture_match_reference_texture =
1859 ((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
1860 new_test_case.use_clientside_index_data = use_clientside_index_data;
1861 new_test_case.use_clientside_vertex_data = use_clientside_vertex_data;
1862 new_test_case.use_geometry_shader_stage = false;
1863 new_test_case.use_tessellation_shader_stage = false;
1864 new_test_case.use_vertex_attrib_binding = false;
1866 memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1867 sizeof(multi_draw_call_count_array));
1868 memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1869 sizeof(multi_draw_call_indices_array));
1870 memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
1871 sizeof(regular_multi_draw_call_offseted_array));
1873 m_test_cases.push_back(new_test_case);
1874 } /* for (all four functions) */
1875 } /* for (all VAO iterations) */
1878 /** Executes test iteration.
1880 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1882 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::iterate()
1887 /* Test case passed */
1888 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1895 * @param context Rendering context handle.
1897 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::
1898 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow(Context& context, const ExtParameters& extParams)
1899 : DrawElementsBaseVertexTestBase(context, extParams, "underflow",
1900 "Verifies basevertex draw calls work correctly for negative "
1901 "basevertex values")
1903 /* Left blank on purpose */
1906 /** Sets up test case descriptors for the test instance. These will later be used
1907 * as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1908 * the actual testing.
1910 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::setUpTestCases()
1912 /* Set up test case descriptors */
1913 const glw::GLint basevertex = -10;
1915 /* The test needs to be run in two iterations, using client-side memory and buffer object
1916 * for index data respectively
1918 for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1920 /* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1921 * See section 11.1.3.9 in OpenGL ES 3.1 spec
1923 bool use_clientside_vertex_data = 0;
1924 bool use_clientside_index_data = ((vao_iteration & (1 << 0)) != 0);
1926 /* OpenGL does not support client-side data. */
1927 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1929 if (use_clientside_index_data || use_clientside_vertex_data)
1935 /* Compute the offsets */
1936 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1938 /* We need to test four different functions:
1940 * a) glDrawElementsBaseVertex() (GL)
1941 * or glDrawElementsBaseVertexEXT() (ES)
1942 * b) glDrawRangeElementsBaseVertex() (GL)
1943 * or glDrawRangeElementsBaseVertexEXT() (ES)
1944 * c) glDrawElementsInstancedBaseVertex() (GL)
1945 * or glDrawElementsInstancedBaseVertexEXT() (ES)
1946 * d) glMultiDrawElementsBaseVertex() (GL)
1947 * or glMultiDrawElementsBaseVertexEXT() (ES) (if supported)
1949 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1951 /* Do not try to use the multi draw call if relevant extension is
1953 if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1958 /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1959 unsigned int offset_from_10_to_0_index = 23; /* this offset moves us from the start index of 10 to a zero
1960 * index, given the second index data set we will be using.
1961 * Please see declaration of functional2_index_data if you
1962 * need to verify this by yourself. */
1964 const glw::GLsizei multi_draw_call_count_array[3] = { 3, 6, 3 };
1965 const glw::GLuint* multi_draw_call_indices_array[3] = { (glw::GLuint*)(m_draw_call_index2_offset),
1966 (glw::GLuint*)(m_draw_call_index2_offset + 3),
1967 (glw::GLuint*)(m_draw_call_index2_offset + 9) };
1968 const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1969 multi_draw_call_indices_array[0] + offset_from_10_to_0_index,
1970 multi_draw_call_indices_array[1] + offset_from_10_to_0_index,
1971 multi_draw_call_indices_array[2] + offset_from_10_to_0_index,
1974 /* Construct the test case descriptor */
1975 _test_case new_test_case;
1977 new_test_case.basevertex = basevertex;
1978 new_test_case.function_type = (_function_type)n_function;
1979 new_test_case.index_offset = m_draw_call_index2_offset;
1980 new_test_case.range_start = 10;
1981 new_test_case.range_end = 32;
1982 new_test_case.index_type = GL_UNSIGNED_INT;
1983 new_test_case.primitive_mode = GL_TRIANGLES;
1984 new_test_case.regular_draw_call_offset = offset_from_10_to_0_index;
1985 new_test_case.should_base_texture_match_reference_texture = true;
1986 new_test_case.use_clientside_index_data = use_clientside_index_data;
1987 new_test_case.use_clientside_vertex_data = use_clientside_vertex_data;
1988 new_test_case.use_geometry_shader_stage = false;
1989 new_test_case.use_tessellation_shader_stage = false;
1990 new_test_case.use_vertex_attrib_binding = false;
1992 memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1993 sizeof(multi_draw_call_count_array));
1994 memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1995 sizeof(multi_draw_call_indices_array));
1996 memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
1997 sizeof(regular_multi_draw_call_offseted_array));
1999 m_test_cases.push_back(new_test_case);
2000 } /* for (all four functions) */
2001 } /* for (all VAO iterations) */
2004 /** Executes test iteration.
2006 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2008 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::iterate()
2013 /* Test case passed */
2014 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2021 * @param context Rendering context handle.
2023 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::
2024 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow(Context& context, const ExtParameters& extParams)
2025 : DrawElementsBaseVertexTestBase(context, extParams, "overflow",
2026 "Verifies basevertex draw calls work correctly for overflowing "
2027 "basevertex values")
2029 /* Left blank on purpose */
2032 /** Sets up test case descriptors for the test instance. These will later be used
2033 * as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
2034 * the actual testing.
2036 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::setUpTestCases()
2038 /* The test needs to be run in two iterations, using client-side memory and buffer object
2039 * for index data respectively
2041 for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
2043 /* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
2044 * See section 11.1.3.9 in OpenGL ES 3.1 spec
2046 bool use_clientside_vertex_data = 0;
2047 bool use_clientside_index_data = ((vao_iteration & (1 << 0)) != 0);
2049 /* OpenGL does not support client-side data. */
2050 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2052 if (use_clientside_index_data || use_clientside_vertex_data)
2058 /* Compute the offsets */
2059 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
2061 /* We need to test four different functions:
2063 * a) glDrawElementsBaseVertex() (GL)
2064 * or glDrawElementsBaseVertexEXT() (ES)
2065 * b) glDrawRangeElementsBaseVertex() (GL)
2066 * or glDrawRangeElementsBaseVertexEXT() (ES)
2067 * c) glDrawElementsInstancedBaseVertex() (GL)
2068 * or glDrawElementsInstancedBaseVertexEXT() (ES)
2069 * d) glMultiDrawElementsBaseVertex() (GL)
2070 * or glMultiDrawElementsBaseVertexEXT() (ES) (if supported)
2072 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
2074 /* Do not try to use the multi draw call if relevant extension is
2076 if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
2081 const glw::GLenum index_types[] = { GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT };
2083 const unsigned int n_index_types = sizeof(index_types) / sizeof(index_types[0]);
2085 for (unsigned int n_index_type = 0; n_index_type < n_index_types; ++n_index_type)
2088 glw::GLint basevertex = -1;
2089 const glw::GLubyte* index_offset = NULL;
2091 glw::GLenum index_type = index_types[n_index_type];
2092 glw::GLenum regular_draw_call_index_type = 0;
2093 int regular_draw_call_index_size = 0;
2094 glw::GLboolean use_overflow_test_vertices = false;
2096 /* To meet requirements of tests IX.1-IX.2 and IX.3, we need to use two basevertex deltas. */
2097 const glw::GLint basevertex_deltas[] = {
2101 const unsigned int n_basevertex_deltas = sizeof(basevertex_deltas) / sizeof(basevertex_deltas[0]);
2103 for (unsigned int n_basevertex_delta = 0; n_basevertex_delta < n_basevertex_deltas;
2104 ++n_basevertex_delta)
2106 const glw::GLint basevertex_delta = basevertex_deltas[n_basevertex_delta];
2107 glw::GLuint regular_draw_call_offset = 0;
2108 glw::GLuint* regular_draw_call_offset2 = NULL;
2109 glw::GLuint range_start = 0;
2110 glw::GLuint range_end = 0;
2116 * UBYTE base draw indices: 0, 1, 2
2118 * regular draw indices: 0, 1, 2
2119 * expected result: ubyte indices should not wrap around at 8-bit width,
2120 * base draw result should not match regular draw result
2122 * UBYTE base draw indices: 0, 1, 2
2124 * regular draw indices: 257, 258, 259 (uint)
2125 * expected result: ubyte indices should be upconverted to 32-bit uint,
2126 * base draw result should match regular draw result
2128 case GL_UNSIGNED_BYTE:
2130 basevertex = 256 + basevertex_delta;
2131 index_offset = (const glw::GLubyte*)m_draw_call_index3_offset;
2135 regular_draw_call_index_type = (basevertex_delta == 0) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT;
2136 regular_draw_call_index_size = (regular_draw_call_index_type == GL_UNSIGNED_BYTE) ? 1 : 4;
2137 regular_draw_call_offset2 =
2138 (basevertex_delta == 0) ?
2139 (glw::GLuint*)(m_draw_call_index3_offset) :
2140 (glw::GLuint*)(m_draw_call_index5_offset + 12); // 12th in functional5_index_data
2141 shouldMatch = (basevertex_delta == 1) ? true : false;
2142 use_overflow_test_vertices = true;
2147 * USHORT base draw indices: 0, 1, 2
2148 * baseVertex: 65536+0
2149 * regular draw indices: 0, 1, 2
2150 * expected result: ubyte indices should not wrap around at 16-bit width,
2151 * base draw result should not match regular draw result
2153 * USHORT base draw indices: 0, 1, 2
2154 * baseVertex: 65536+1
2155 * regular draw indices: 65537, 65538, 65539 (uint)
2156 * expected result: ushort indices should be upconverted to 32-bit uint,
2157 * base draw result should match regular draw result
2159 case GL_UNSIGNED_SHORT:
2161 basevertex = 65536 + basevertex_delta;
2162 index_offset = (const glw::GLubyte*)m_draw_call_index4_offset;
2166 regular_draw_call_index_type = (basevertex_delta == 0) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
2167 regular_draw_call_index_size = (regular_draw_call_index_type == GL_UNSIGNED_SHORT) ? 2 : 4;
2168 regular_draw_call_offset2 =
2169 (basevertex_delta == 0) ?
2170 (glw::GLuint*)(m_draw_call_index4_offset) :
2171 (glw::GLuint*)(m_draw_call_index5_offset + 24); // 24th in functional5_index_data
2172 shouldMatch = (basevertex_delta == 1) ? true : false;
2173 use_overflow_test_vertices = true;
2178 * UINT base draw indices: 2^31+2, 2^31+3, 2^31+4
2179 * baseVertex: 2^31-2
2180 * regular draw indices: 0, 1, 2
2181 * expected result: uint indices should wrap to {0, 1, 2},
2182 * base draw result should match regular draw result
2184 * UINT base draw indices: 2^31+2, 2^31+3, 2^31+4
2185 * baseVertex: 2^31-1
2186 * regular draw indices: 0, 1, 2
2187 * expected result: uint indices should wrap to {1, 2, 3},
2188 * base draw result should not match regular draw result
2190 case GL_UNSIGNED_INT:
2192 basevertex = 2147483647 - 1 + basevertex_delta;
2193 index_offset = (const glw::GLubyte*)m_draw_call_index5_offset;
2195 range_start = 2147483647 + 3u; // 2^31+2
2196 range_end = 2147483647 + 5u; // 2^31+4
2197 regular_draw_call_index_type = GL_UNSIGNED_INT;
2198 regular_draw_call_index_size = 4;
2199 regular_draw_call_offset = 36; // 36th in functional5_index_data
2200 shouldMatch = (basevertex_delta == 0) ? true : false;
2201 use_overflow_test_vertices = false;
2207 TCU_FAIL("Unrecognized index type");
2209 } /* switch (index_type) */
2211 /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
2212 const glw::GLsizei multi_draw_call_count_array[3] = { 3, 6, 3 };
2213 const glw::GLubyte* multi_draw_call_indices_array[3] = { index_offset,
2214 index_offset + 3 * index_size,
2215 index_offset + 9 * index_size };
2216 const glw::GLubyte* regular_multi_draw_call_offseted_array[3];
2217 if (use_overflow_test_vertices)
2219 regular_multi_draw_call_offseted_array[0] = (glw::GLubyte*)regular_draw_call_offset2;
2220 regular_multi_draw_call_offseted_array[1] =
2221 (glw::GLubyte*)regular_draw_call_offset2 + 3 * regular_draw_call_index_size;
2222 regular_multi_draw_call_offseted_array[2] =
2223 (glw::GLubyte*)regular_draw_call_offset2 + 9 * regular_draw_call_index_size;
2227 regular_multi_draw_call_offseted_array[0] =
2228 multi_draw_call_indices_array[0] + index_size * regular_draw_call_offset;
2229 regular_multi_draw_call_offseted_array[1] =
2230 multi_draw_call_indices_array[1] + index_size * regular_draw_call_offset;
2231 regular_multi_draw_call_offseted_array[2] =
2232 multi_draw_call_indices_array[2] + index_size * regular_draw_call_offset;
2235 /* Construct the test case descriptor */
2236 _test_case new_test_case;
2238 new_test_case.basevertex = basevertex;
2239 new_test_case.function_type = (_function_type)n_function;
2240 new_test_case.index_offset = (const glw::GLuint*)index_offset;
2241 new_test_case.range_start = range_start;
2242 new_test_case.range_end = range_end;
2243 new_test_case.index_type = index_type;
2244 new_test_case.primitive_mode = GL_TRIANGLES;
2245 new_test_case.regular_draw_call_offset = regular_draw_call_offset;
2246 new_test_case.regular_draw_call_offset2 = regular_draw_call_offset2;
2247 new_test_case.regular_draw_call_index_type = regular_draw_call_index_type;
2248 new_test_case.should_base_texture_match_reference_texture = shouldMatch;
2249 new_test_case.use_clientside_index_data = use_clientside_index_data;
2250 new_test_case.use_clientside_vertex_data = use_clientside_vertex_data;
2251 new_test_case.use_geometry_shader_stage = false;
2252 new_test_case.use_tessellation_shader_stage = false;
2253 new_test_case.use_vertex_attrib_binding = false;
2254 new_test_case.use_overflow_test_vertices = use_overflow_test_vertices != GL_FALSE;
2256 memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
2257 sizeof(multi_draw_call_count_array));
2258 memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
2259 sizeof(multi_draw_call_indices_array));
2260 memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
2261 sizeof(regular_multi_draw_call_offseted_array));
2263 m_test_cases.push_back(new_test_case);
2264 } /* for (all basevertex deltas) */
2265 } /* for (all index types) */
2266 } /* for (all four functions) */
2267 } /* for (all VAO iterations) */
2270 /** Executes test iteration.
2272 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2274 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::iterate()
2279 /* Test case passed */
2280 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2287 * @param context Rendering context handle.
2289 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::
2290 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages(Context& context,
2291 const ExtParameters& extParams)
2292 : DrawElementsBaseVertexTestBase(context, extParams, "AEP_shader_stages",
2293 "Verifies basevertex draw calls work correctly when geometry & "
2294 "tessellation shader stages are used in the rendering pipeline.")
2296 /* Left blank intentionally */
2299 /** Sets up test case descriptors for the test instance. These will later be used
2300 * as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
2301 * the actual testing.
2303 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::setUpTestCases()
2305 /* Set up test case descriptors */
2306 const glw::GLuint basevertex_values[] = {
2310 const unsigned int n_basevertex_values = sizeof(basevertex_values) / sizeof(basevertex_values[0]);
2312 /* The test needs to be run in two iterations, using client-side memory and buffer object
2313 * for index data respectively
2315 for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
2317 /* Skip client-side vertex array as gl_VertexID is undefined when zero buffer is bound to ARRAY_BUFFER */
2318 bool use_clientside_vertex_data = 0;
2319 bool use_clientside_index_data = ((vao_iteration & (1 << 0)) != 0);
2321 /* OpenGL does not support client-side data. */
2322 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2324 if (use_clientside_index_data || use_clientside_vertex_data)
2330 /* Compute the offsets */
2331 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
2333 /* There are two index data sets we need to iterate over */
2334 const glw::GLuint* index_offsets[] = { m_draw_call_index_offset, m_draw_call_index2_offset };
2335 const unsigned int n_index_offsets = sizeof(index_offsets) / sizeof(index_offsets[0]);
2337 for (unsigned int n_index_offset = 0; n_index_offset < n_index_offsets; ++n_index_offset)
2339 const glw::GLuint* current_index_offset = index_offsets[n_index_offset];
2341 /* We need to test four different functions:
2343 * a) glDrawElementsBaseVertex() (GL)
2344 * or glDrawElementsBaseVertexEXT() (ES)
2345 * b) glDrawRangeElementsBaseVertex() (GL)
2346 * or glDrawRangeElementsBaseVertexEXT() (ES)
2347 * c) glDrawElementsInstancedBaseVertex() (GL)
2348 * or glDrawElementsInstancedBaseVertexEXT() (ES)
2349 * d) glMultiDrawElementsBaseVertex() (GL)
2350 * or glMultiDrawElementsBaseVertexEXT() (ES) (if supported)
2352 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
2354 /* Iterate over all basevertex values */
2355 for (unsigned int n_basevertex_value = 0; n_basevertex_value < n_basevertex_values;
2356 ++n_basevertex_value)
2359 /* Iterate over all GS+(TC & TE) stage combinations */
2360 for (unsigned int n_stage_combination = 0; n_stage_combination < 4; ++n_stage_combination)
2362 bool should_include_gs = (n_stage_combination & 1) != 0;
2363 bool should_include_tc_te = (n_stage_combination & 2) != 0;
2365 /* Skip iterations, for which we'd need to use extensions not supported
2366 * by the running implementation */
2367 if (should_include_gs && !m_is_geometry_shader_supported)
2372 if (should_include_tc_te && !m_is_tessellation_shader_supported)
2377 /* Do not try to use the multi draw call if relevant extension is
2379 if (!m_is_ext_multi_draw_arrays_supported &&
2380 n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
2385 /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
2386 const glw::GLsizei multi_draw_call_count_array[3] = { 3, 6, 3 };
2387 const glw::GLuint* multi_draw_call_indices_array[3] = {
2388 (glw::GLuint*)(current_index_offset), (glw::GLuint*)(current_index_offset + 3),
2389 (glw::GLuint*)(current_index_offset + 9)
2392 /* Reference texture should always reflect basevertex=10 behavior. */
2393 const glw::GLuint regular_draw_call_offset = basevertex_values[0];
2394 const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
2395 multi_draw_call_indices_array[0] + regular_draw_call_offset,
2396 multi_draw_call_indices_array[1] + regular_draw_call_offset,
2397 multi_draw_call_indices_array[2] + regular_draw_call_offset,
2400 /* Construct the test case descriptor */
2401 _test_case new_test_case;
2403 new_test_case.basevertex = basevertex_values[n_basevertex_value];
2404 new_test_case.function_type = (_function_type)n_function;
2405 new_test_case.index_offset = current_index_offset;
2406 new_test_case.range_start = n_index_offset == 0 ? 0 : 10;
2407 new_test_case.range_end = n_index_offset == 0 ? 22 : 32;
2408 new_test_case.index_type = GL_UNSIGNED_INT;
2409 new_test_case.primitive_mode = (should_include_tc_te) ? GL_PATCHES : GL_TRIANGLES;
2410 new_test_case.regular_draw_call_offset = regular_draw_call_offset;
2411 new_test_case.should_base_texture_match_reference_texture =
2412 ((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
2413 new_test_case.use_clientside_index_data = use_clientside_index_data;
2414 new_test_case.use_clientside_vertex_data = use_clientside_vertex_data;
2415 new_test_case.use_geometry_shader_stage = should_include_gs;
2416 new_test_case.use_tessellation_shader_stage = should_include_tc_te;
2417 new_test_case.use_vertex_attrib_binding = false;
2419 memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
2420 sizeof(multi_draw_call_count_array));
2421 memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
2422 sizeof(multi_draw_call_indices_array));
2423 memcpy(new_test_case.regular_multi_draw_call_offseted_array,
2424 regular_multi_draw_call_offseted_array, sizeof(regular_multi_draw_call_offseted_array));
2426 m_test_cases.push_back(new_test_case);
2427 } /* for (all shader stage combinations) */
2428 } /* for (all basevertex values) */
2429 } /* for (all four functions) */
2430 } /* for (all index data sets) */
2431 } /* for (all VAO iterations) */
2434 /** Executes test iteration.
2436 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2438 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::iterate()
2440 /* This test should not be run on implementations that don't support both tessellation and geometry
2443 if (!m_is_geometry_shader_supported && !m_is_tessellation_shader_supported)
2445 throw tcu::NotSupportedError("Geometry shader and tessellation shader functionality is not supported");
2451 /* Test case passed */
2452 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2459 * @param context Rendering context handle.
2461 DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::DrawElementsBaseVertexNegativeActiveTransformFeedbackTest(
2462 Context& context, const ExtParameters& extParams)
2463 : DrawElementsBaseVertexTestBase(context, extParams, "valid_active_tf",
2464 "Tries to do \"base vertex\" draw calls while Transform Feedback is active")
2465 , m_bo_tf_result_id(0)
2467 /* Left blank on purpose */
2470 /** Deinitializes all ES objects per test case if test fails and exit through exception path */
2471 void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::deinit()
2473 deinitPerTestObjects();
2476 /** Deinitializes all ES objects that may have been created by the test */
2477 void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::deinitPerTestObjects()
2479 /* Call the base class' deinitPerTestObjects() first. */
2480 DrawElementsBaseVertexTestBase::deinitPerTestObjects();
2482 /* Proceed with internal deinitialization */
2483 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2485 if (m_bo_tf_result_id != 0)
2487 gl.deleteBuffers(1, &m_bo_tf_result_id);
2489 m_bo_tf_result_id = 0;
2493 /** Initializes all ES objects used by the test. */
2494 void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::init()
2496 /* Call the base class' init() first. */
2497 DrawElementsBaseVertexTestBase::init();
2499 /* Proceed with internal initialization */
2500 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2502 gl.genBuffers(1, &m_bo_tf_result_id);
2503 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
2505 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_tf_result_id);
2506 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
2508 gl.bufferData(GL_ARRAY_BUFFER, 3 /* count */ * sizeof(float) * 4 /* components used by gl_Position */,
2511 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2513 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
2515 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
2518 /** Executes test iteration.
2520 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2522 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::iterate()
2524 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2526 /* this test doesn't apply to OpenGL contexts */
2527 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2529 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
2533 /* Set up the work environment */
2534 setUpNegativeTestObjects(false, /* use_clientside_vertex_data */
2535 false); /* use_clientside_index_data */
2537 /* Kick off transform feedback */
2538 gl.beginTransformFeedback(GL_TRIANGLES);
2539 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2541 /* Try to perform indiced draw calls which are invalid when TF is active.
2543 glw::GLenum error_code = GL_NONE;
2545 gl.drawElementsBaseVertex(GL_TRIANGLES, 3, /* count */
2546 GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
2548 error_code = gl.getError();
2550 /* The error for using DrawElements* commands while transform feedback is
2551 active is lifted in OES/EXT_geometry_shader. See issue 13 in the spec.
2553 glw::GLenum expected_error_code = m_is_geometry_shader_supported ? GL_NO_ERROR : GL_INVALID_OPERATION;
2555 if (error_code != expected_error_code)
2557 std::stringstream error_sstream;
2559 error_sstream << "Invalid error code generated by " << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX);
2561 m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX)
2562 << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2563 << tcu::TestLog::EndMessage;
2565 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2570 gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, 3, /* count */
2571 GL_UNSIGNED_INT, m_draw_call_index_offset, 1, /* instancecount */
2572 0); /* basevertex */
2574 error_code = gl.getError();
2575 if (error_code != expected_error_code)
2577 std::stringstream error_sstream;
2579 error_sstream << "Invalid error code generated by "
2580 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX);
2582 m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX)
2583 << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2584 << tcu::TestLog::EndMessage;
2586 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2591 gl.drawRangeElementsBaseVertex(GL_TRIANGLES, 0, 2, /* end */
2593 GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
2595 error_code = gl.getError();
2596 if (error_code != expected_error_code)
2598 std::stringstream error_sstream;
2600 error_sstream << "Invalid error code generated by "
2601 << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX);
2603 m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX)
2604 << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2605 << tcu::TestLog::EndMessage;
2607 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2612 /* Test case passed */
2613 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2616 gl.endTransformFeedback();
2622 * @param context Rendering context handle.
2624 DrawElementsBaseVertexNegativeInvalidCountArgumentTest::DrawElementsBaseVertexNegativeInvalidCountArgumentTest(
2625 Context& context, const ExtParameters& extParams)
2626 : DrawElementsBaseVertexTestBase(context, extParams, "invalid_count_argument",
2627 "Tries to use invalid 'count' argument values for the \"base vertex\" draw calls")
2629 /* Left blank on purpose */
2632 /** Executes test iteration.
2634 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2636 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidCountArgumentTest::iterate()
2638 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2640 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
2641 * in a slightly different manner.
2643 for (int iteration = 0; iteration < 4; ++iteration)
2645 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
2646 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2648 /* OpenGL does not support client-side data. */
2649 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2651 if (use_clientside_index_data || use_clientside_vertex_data)
2657 /* Set up the work environment */
2658 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2660 /* Try to execute the invalid draw calls */
2661 glw::GLenum error_code = GL_NONE;
2663 gl.drawElementsBaseVertex(GL_TRIANGLES, -1, /* count */
2664 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
2666 error_code = gl.getError();
2667 if (error_code != GL_INVALID_VALUE)
2669 std::stringstream error_sstream;
2671 error_sstream << "Invalid error code reported for an invalid "
2672 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2674 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2675 << ": expected GL_INVALID_VALUE, got:"
2677 << error_code << "]" << tcu::TestLog::EndMessage;
2679 TCU_FAIL(error_sstream.str().c_str());
2682 gl.drawRangeElementsBaseVertex(GL_TRIANGLES, /* mode */
2686 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2687 0); /* basevertex */
2689 error_code = gl.getError();
2690 if (error_code != GL_INVALID_VALUE)
2692 std::stringstream error_sstream;
2694 error_sstream << "Invalid error code reported for an invalid "
2695 << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
2697 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2698 << ": expected GL_INVALID_VALUE, got:"
2700 << error_code << "]" << tcu::TestLog::EndMessage;
2702 TCU_FAIL(error_sstream.str().c_str());
2705 gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, /* mode */
2707 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2708 1, /* instancecount */
2709 0); /* basevertex */
2711 error_code = gl.getError();
2712 if (error_code != GL_INVALID_VALUE)
2714 std::stringstream error_sstream;
2716 error_sstream << "Invalid error code reported for an invalid "
2717 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2719 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2720 << ": expected GL_INVALID_VALUE, got:"
2722 << error_code << "]" << tcu::TestLog::EndMessage;
2724 TCU_FAIL(error_sstream.str().c_str());
2727 if (m_is_ext_multi_draw_arrays_supported)
2729 const glw::GLsizei count = -1;
2730 const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
2732 gl.multiDrawElementsBaseVertex(GL_TRIANGLES, /* mode */
2733 &count, GL_UNSIGNED_INT, offsets, 1, /* primcount */
2734 0); /* basevertex */
2736 error_code = gl.getError();
2737 if (error_code != GL_INVALID_VALUE)
2739 std::stringstream error_sstream;
2741 error_sstream << "Invalid error code reported for an invalid "
2742 << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2744 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2745 << ": expected GL_INVALID_VALUE, got:"
2747 << error_code << "]" << tcu::TestLog::EndMessage;
2749 TCU_FAIL("Invalid error code reported for an invalid glMultiDrawElementsBaseVertexEXT() call.");
2751 } /* if (m_is_ext_multi_draw_arrays_supported) */
2752 } /* for (all iterations) */
2754 /* Test case passed */
2755 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2762 * @param context Rendering context handle.
2764 DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest::
2765 DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest(Context& context, const ExtParameters& extParams)
2766 : DrawElementsBaseVertexTestBase(context, extParams, "invalid_instancecount_argument",
2767 "Tries to use invalid 'instancecount' argument values for "
2768 "glDrawElementsInstancedBaseVertexEXT (ES) or "
2769 "glDrawElementsInstancedBaseVertex (GL) draw call")
2771 /* Left blank on purpose */
2774 /** Executes test iteration.
2776 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2778 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest::iterate()
2780 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2782 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
2783 * in a slightly different manner.
2785 for (int iteration = 0; iteration < 4; ++iteration)
2787 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
2788 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2790 /* OpenGL does not support client-side data. */
2791 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2793 if (use_clientside_index_data || use_clientside_vertex_data)
2799 /* Set up the work environment */
2800 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2802 /* Try to execute the invalid draw call */
2803 glw::GLenum error_code = GL_NONE;
2805 gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, /* mode */
2807 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2808 -1, /* instancecount */
2809 0); /* basevertex */
2811 error_code = gl.getError();
2812 if (error_code != GL_INVALID_VALUE)
2814 std::stringstream error_sstream;
2816 error_sstream << "Invalid error code reported for an invalid "
2817 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2819 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2820 << ": expected GL_INVALID_VALUE, got:"
2822 << error_code << "]" << tcu::TestLog::EndMessage;
2824 TCU_FAIL(error_sstream.str().c_str());
2826 } /* for (all test iterations) */
2828 /* Test case passed */
2829 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2836 * @param context Rendering context handle.
2838 DrawElementsBaseVertexNegativeInvalidModeArgumentTest::DrawElementsBaseVertexNegativeInvalidModeArgumentTest(
2839 Context& context, const ExtParameters& extParams)
2840 : DrawElementsBaseVertexTestBase(context, extParams, "invalid_mode_argument",
2841 "Tries to use invalid 'mode' argument values for the \"base vertex\" draw calls")
2843 /* Left blank on purpose */
2846 /** Executes test iteration.
2848 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2850 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidModeArgumentTest::iterate()
2852 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2854 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
2855 * in a slightly different manner.
2857 for (int iteration = 0; iteration < 4; ++iteration)
2859 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
2860 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2862 /* OpenGL does not support client-side data. */
2863 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2865 if (use_clientside_index_data || use_clientside_vertex_data)
2871 /* Set up the work environment */
2872 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2874 /* Try to execute the invalid draw calls */
2875 glw::GLenum error_code = GL_NONE;
2877 gl.drawElementsBaseVertex(GL_GREATER, /* mode */
2879 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
2881 error_code = gl.getError();
2882 if (error_code != GL_INVALID_ENUM)
2884 std::stringstream error_sstream;
2886 error_sstream << "Invalid error code reported for an invalid "
2887 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2889 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2890 << ": expected GL_INVALID_ENUM, got:"
2892 << error_code << "]" << tcu::TestLog::EndMessage;
2894 TCU_FAIL(error_sstream.str().c_str());
2897 gl.drawRangeElementsBaseVertex(GL_GREATER, /* mode */
2901 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2902 0); /* basevertex */
2904 error_code = gl.getError();
2905 if (error_code != GL_INVALID_ENUM)
2907 std::stringstream error_sstream;
2909 error_sstream << "Invalid error code reported for an invalid "
2910 << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
2912 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2913 << ": expected GL_INVALID_ENUM, got:"
2915 << error_code << "]" << tcu::TestLog::EndMessage;
2917 TCU_FAIL(error_sstream.str().c_str());
2920 gl.drawElementsInstancedBaseVertex(GL_GREATER, /* mode */
2922 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2923 1, /* instancecount */
2924 0); /* basevertex */
2926 error_code = gl.getError();
2927 if (error_code != GL_INVALID_ENUM)
2929 std::stringstream error_sstream;
2931 error_sstream << "Invalid error code reported for an invalid "
2932 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2934 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2935 << ": expected GL_INVALID_ENUM, got:"
2937 << error_code << "]" << tcu::TestLog::EndMessage;
2939 TCU_FAIL(error_sstream.str().c_str());
2942 if (m_is_ext_multi_draw_arrays_supported)
2944 const glw::GLsizei count = 3;
2945 const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
2947 gl.multiDrawElementsBaseVertex(GL_GREATER, /* mode */
2948 &count, GL_UNSIGNED_INT, offsets, 1, /* primcount */
2949 0); /* basevertex */
2951 error_code = gl.getError();
2952 if (error_code != GL_INVALID_ENUM)
2954 std::stringstream error_sstream;
2956 error_sstream << "Invalid error code reported for an invalid "
2957 << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2959 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2960 << ": expected GL_INVALID_ENUM, got:"
2962 << error_code << "]" << tcu::TestLog::EndMessage;
2964 TCU_FAIL(error_sstream.str().c_str());
2966 } /* if (m_is_ext_multi_draw_arrays_supported) */
2967 } /* for (all test iterations) */
2969 /* Test case passed */
2970 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2977 * @param context Rendering context handle.
2979 DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest::DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest(
2980 Context& context, const ExtParameters& extParams)
2981 : DrawElementsBaseVertexTestBase(
2982 context, extParams, "invalid_primcount_argument",
2983 "Tries to use invalid 'primcount' argument values for the \"base vertex\" draw calls")
2985 /* Left blank on purpose */
2988 /** Executes test iteration.
2990 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2992 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest::iterate()
2994 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2996 /* This test requires presence of GL_EXT_multi_draw_arrays under ES contexts */
2997 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
2999 if (!m_is_ext_multi_draw_arrays_supported)
3001 throw tcu::NotSupportedError("GL_EXT_multi_draw_arrays is not supported");
3005 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
3006 * in a slightly different manner.
3008 for (int iteration = 0; iteration < 4; ++iteration)
3010 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
3011 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3013 /* OpenGL does not support client-side data. */
3014 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3016 if (use_clientside_index_data || use_clientside_vertex_data)
3022 /* Set up the work environment */
3023 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3025 /* Perform the test */
3026 const glw::GLsizei count = 3;
3027 glw::GLenum error_code = GL_NO_ERROR;
3028 const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
3030 gl.multiDrawElementsBaseVertex(GL_TRIANGLES, /* mode */
3031 &count, GL_UNSIGNED_INT, offsets, -1, /* primcount */
3032 0); /* basevertex */
3034 error_code = gl.getError();
3035 if (error_code != GL_INVALID_VALUE)
3037 std::stringstream error_sstream;
3039 error_sstream << "Invalid error code reported for an invalid "
3040 << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3042 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3043 << ": expected GL_INVALID_VALUE, got:"
3045 << error_code << "]" << tcu::TestLog::EndMessage;
3047 TCU_FAIL(error_sstream.str().c_str());
3049 } /* for (all test iterations) */
3051 /* Test case passed */
3052 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3059 * @param context Rendering context handle.
3061 DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest::DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest(
3062 Context& context, const ExtParameters& extParams)
3063 : DrawElementsBaseVertexTestBase(context, extParams, "invalid_start_end_arguments",
3064 "Tries to use invalid 'start' and 'end' argument values for the "
3065 "glDrawRangeElementsBaseVertexEXT() (under ES) or "
3066 "glDrawRangeElementsBaseVertex() (under GL) draw call")
3068 /* Left blank on purpose */
3071 /** Executes test iteration.
3073 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3075 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest::iterate()
3077 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3079 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
3080 * in a slightly different manner.
3082 for (int iteration = 0; iteration < 4; ++iteration)
3084 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
3085 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3087 /* OpenGL does not support client-side data. */
3088 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3090 if (use_clientside_index_data || use_clientside_vertex_data)
3096 /* Set up the work environment */
3097 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3099 /* Try to execute the invalid draw call */
3100 glw::GLenum error_code = GL_NONE;
3102 gl.drawRangeElementsBaseVertex(GL_TRIANGLES, /* mode */
3106 GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
3107 0); /* basevertex */
3109 error_code = gl.getError();
3110 if (error_code != GL_INVALID_VALUE)
3112 std::stringstream error_sstream;
3114 error_sstream << "Invalid error code reported for an invalid "
3115 << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
3117 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3118 << ": expected GL_INVALID_VALUE, got:"
3120 << error_code << "]" << tcu::TestLog::EndMessage;
3122 TCU_FAIL(error_sstream.str().c_str());
3124 } /* for (all test iterations) */
3126 /* Test case passed */
3127 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3134 * @param context Rendering context handle.
3136 DrawElementsBaseVertexNegativeInvalidTypeArgumentTest::DrawElementsBaseVertexNegativeInvalidTypeArgumentTest(
3137 Context& context, const ExtParameters& extParams)
3138 : DrawElementsBaseVertexTestBase(context, extParams, "invalid_type_argument",
3139 "Tries to use invalid 'type' argument values for the \"base vertex\" draw calls")
3141 /* Left blank on purpose */
3144 /** Executes test iteration.
3146 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3148 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidTypeArgumentTest::iterate()
3150 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3152 /* The test needs to be run in four iterations, where for each iteration we configure the VAO
3153 * in a slightly different manner.
3155 for (int iteration = 0; iteration < 4; ++iteration)
3157 bool use_clientside_index_data = ((iteration & (1 << 0)) != 0);
3158 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3160 /* OpenGL does not support client-side data. */
3161 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3163 if (use_clientside_index_data || use_clientside_vertex_data)
3169 /* Set up the work environment */
3170 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3172 /* Try to execute the invalid draw calls */
3173 glw::GLenum error_code = GL_NONE;
3175 gl.drawElementsBaseVertex(GL_TRIANGLES, /* mode */
3177 GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
3179 error_code = gl.getError();
3180 if (error_code != GL_INVALID_ENUM)
3182 std::stringstream error_sstream;
3184 error_sstream << "Invalid error code reported for an invalid "
3185 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3187 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3188 << ": expected GL_INVALID_ENUM, got:"
3190 << error_code << "]" << tcu::TestLog::EndMessage;
3192 TCU_FAIL(error_sstream.str().c_str());
3195 gl.drawRangeElementsBaseVertex(GL_TRIANGLES, /* mode */
3199 GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
3201 error_code = gl.getError();
3202 if (error_code != GL_INVALID_ENUM)
3204 std::stringstream error_sstream;
3206 error_sstream << "Invalid error code reported for an invalid "
3207 << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
3209 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3210 << ": expected GL_INVALID_ENUM, got:"
3212 << error_code << "]" << tcu::TestLog::EndMessage;
3214 TCU_FAIL(error_sstream.str().c_str());
3217 gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, /* mode */
3219 GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 1, /* instancecount */
3220 0); /* basevertex */
3222 error_code = gl.getError();
3223 if (error_code != GL_INVALID_ENUM)
3225 std::stringstream error_sstream;
3227 error_sstream << "Invalid error code reported for an invalid "
3228 << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
3230 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3231 << ": expected GL_INVALID_ENUM, got:"
3233 << error_code << "]" << tcu::TestLog::EndMessage;
3235 TCU_FAIL(error_sstream.str().c_str());
3238 if (m_is_ext_multi_draw_arrays_supported)
3240 const glw::GLsizei count = 3;
3241 const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
3243 gl.multiDrawElementsBaseVertex(GL_TRIANGLES, /* mode */
3244 &count, GL_NONE, offsets, 1, /* primcount */
3245 0); /* basevertex */
3247 error_code = gl.getError();
3248 if (error_code != GL_INVALID_ENUM)
3250 std::stringstream error_sstream;
3252 error_sstream << "Invalid error code reported for an invalid "
3253 << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3255 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3256 << ": expected GL_INVALID_ENUM, got:"
3258 << error_code << "]" << tcu::TestLog::EndMessage;
3260 TCU_FAIL(error_sstream.str().c_str());
3262 } /* if (m_is_ext_multi_draw_arrays_supported) */
3263 } /* for (all test iterations) */
3265 /* Test case passed */
3266 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3273 * @param context Rendering context.
3275 DrawElementsBaseVertexTests::DrawElementsBaseVertexTests(glcts::Context& context, const ExtParameters& extParams)
3276 : TestCaseGroupBase(context, extParams, "draw_elements_base_vertex_tests",
3277 "Contains conformance tests that verify ES and GL implementation's support "
3278 "for GL_EXT_draw_elements_base_vertex (ES) and "
3279 "GL_ARB_draw_elements_base_vertex (GL) extensions.")
3283 /** Initializes the test group contents. */
3284 void DrawElementsBaseVertexTests::init()
3286 addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior(m_context, m_extParams));
3287 addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2(m_context, m_extParams));
3288 addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages(m_context, m_extParams));
3289 addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow(m_context, m_extParams));
3290 addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow(m_context, m_extParams));
3291 addChild(new DrawElementsBaseVertexNegativeActiveTransformFeedbackTest(m_context, m_extParams));
3292 addChild(new DrawElementsBaseVertexNegativeInvalidCountArgumentTest(m_context, m_extParams));
3293 addChild(new DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest(m_context, m_extParams));
3294 addChild(new DrawElementsBaseVertexNegativeInvalidModeArgumentTest(m_context, m_extParams));
3295 addChild(new DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest(m_context, m_extParams));
3296 addChild(new DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest(m_context, m_extParams));
3297 addChild(new DrawElementsBaseVertexNegativeInvalidTypeArgumentTest(m_context, m_extParams));
3300 } /* glcts namespace */