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