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