172e0af3c90c46e98926a57bb90086cb13b8e247
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / gl / gl4cPipelineStatisticsQueryTests.cpp
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  gl4cPipelineStatisticsQueryTests.cpp
27  * \brief Implements conformance tests for GL_ARB_pipeline_statistics_query functionality
28  */ /*-------------------------------------------------------------------*/
29
30 #include "gl4cPipelineStatisticsQueryTests.hpp"
31 #include "gluContextInfo.hpp"
32 #include "gluDefs.hpp"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 #include "tcuRenderTarget.hpp"
36 #include "tcuTestLog.hpp"
37
38 #include <string>
39 #include <vector>
40
41 #ifndef GL_VERTICES_SUBMITTED_ARB
42 #define GL_VERTICES_SUBMITTED_ARB (0x82EE)
43 #endif
44 #ifndef GL_PRIMITIVES_SUBMITTED_ARB
45 #define GL_PRIMITIVES_SUBMITTED_ARB (0x82EF)
46 #endif
47 #ifndef GL_VERTEX_SHADER_INVOCATIONS_ARB
48 #define GL_VERTEX_SHADER_INVOCATIONS_ARB (0x82F0)
49 #endif
50 #ifndef GL_TESS_CONTROL_SHADER_PATCHES_ARB
51 #define GL_TESS_CONTROL_SHADER_PATCHES_ARB (0x82F1)
52 #endif
53 #ifndef GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB
54 #define GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB (0x82F2)
55 #endif
56 #ifndef GL_GEOMETRY_SHADER_INVOCATIONS
57 #define GL_GEOMETRY_SHADER_INVOCATIONS (0x887F)
58 #endif
59 #ifndef GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB
60 #define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB (0x82F3)
61 #endif
62 #ifndef GL_FRAGMENT_SHADER_INVOCATIONS_ARB
63 #define GL_FRAGMENT_SHADER_INVOCATIONS_ARB (0x82F4)
64 #endif
65 #ifndef GL_COMPUTE_SHADER_INVOCATIONS_ARB
66 #define GL_COMPUTE_SHADER_INVOCATIONS_ARB (0x82F5)
67 #endif
68 #ifndef GL_CLIPPING_INPUT_PRIMITIVES_ARB
69 #define GL_CLIPPING_INPUT_PRIMITIVES_ARB (0x82F6)
70 #endif
71 #ifndef GL_CLIPPING_OUTPUT_PRIMITIVES_ARB
72 #define GL_CLIPPING_OUTPUT_PRIMITIVES_ARB (0x82F7)
73 #endif
74
75 namespace glcts
76 {
77 const char* PipelineStatisticsQueryUtilities::dummy_cs_code =
78         "#version 430\n"
79         "\n"
80         "layout(local_size_x=1, local_size_y = 1, local_size_z = 1) in;\n"
81         "\n"
82         "layout(binding = 0) uniform atomic_uint test_counter;\n"
83         "\n"
84         "void main()\n"
85         "{\n"
86         "    atomicCounterIncrement(test_counter);\n"
87         "}\n";
88 const char* PipelineStatisticsQueryUtilities::dummy_fs_code = "#version 130\n"
89                                                                                                                           "\n"
90                                                                                                                           "out vec4 result;\n"
91                                                                                                                           "\n"
92                                                                                                                           "void main()\n"
93                                                                                                                           "{\n"
94                                                                                                                           "    result = gl_FragCoord;\n"
95                                                                                                                           "}\n";
96 const char* PipelineStatisticsQueryUtilities::dummy_tc_code =
97         "#version 400\n"
98         "\n"
99         "layout(vertices = 3) out;\n"
100         "\n"
101         "void main()\n"
102         "{\n"
103         "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
104         "    gl_TessLevelInner[0]                = 1.0;\n"
105         "    gl_TessLevelInner[1]                = 2.0;\n"
106         "    gl_TessLevelOuter[0]                = 3.0;\n"
107         "    gl_TessLevelOuter[1]                = 4.0;\n"
108         "    gl_TessLevelOuter[2]                = 5.0;\n"
109         "    gl_TessLevelOuter[3]                = 6.0;\n"
110         "}\n";
111 const char* PipelineStatisticsQueryUtilities::dummy_te_code =
112         "#version 400\n"
113         "\n"
114         "layout(triangles) in;\n"
115         "\n"
116         "void main()\n"
117         "{\n"
118         "    gl_Position = gl_TessCoord.xyxy * gl_in[gl_PrimitiveID].gl_Position;\n"
119         "}\n";
120 const char* PipelineStatisticsQueryUtilities::dummy_vs_code = "#version 130\n"
121                                                                                                                           "\n"
122                                                                                                                           "in vec4 position;\n"
123                                                                                                                           "\n"
124                                                                                                                           "void main()\n"
125                                                                                                                           "{\n"
126                                                                                                                           "    gl_Position = position;\n"
127                                                                                                                           "}\n";
128
129 /** An array holding all query targets that are introduced by GL_ARB_pipeline_statistics_query */
130 const glw::GLenum PipelineStatisticsQueryUtilities::query_targets[] = {
131         GL_VERTICES_SUBMITTED_ARB,
132         GL_PRIMITIVES_SUBMITTED_ARB,
133         GL_VERTEX_SHADER_INVOCATIONS_ARB,
134         GL_TESS_CONTROL_SHADER_PATCHES_ARB,
135         GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB,
136         GL_GEOMETRY_SHADER_INVOCATIONS,
137         GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB,
138         GL_FRAGMENT_SHADER_INVOCATIONS_ARB,
139         GL_COMPUTE_SHADER_INVOCATIONS_ARB,
140         GL_CLIPPING_INPUT_PRIMITIVES_ARB,
141         GL_CLIPPING_OUTPUT_PRIMITIVES_ARB,
142 };
143 const unsigned int PipelineStatisticsQueryUtilities::n_query_targets = sizeof(query_targets) / sizeof(query_targets[0]);
144
145 /* Offsets that point to locations in a buffer object storage that will hold
146  * query object result values for a specific value type. */
147 const unsigned int PipelineStatisticsQueryUtilities::qo_bo_int_offset   = (0);
148 const unsigned int PipelineStatisticsQueryUtilities::qo_bo_int64_offset = (0 + 4 /* int */ + 4 /* alignment */);
149 const unsigned int PipelineStatisticsQueryUtilities::qo_bo_uint_offset  = (0 + 8 /* int + alignment */ + 8 /* int64 */);
150 const unsigned int PipelineStatisticsQueryUtilities::qo_bo_uint64_offset =
151         (0 + 8 /* int + alignment */ + 8 /* int64 */ + 8 /* uint + alignment */);
152 const unsigned int PipelineStatisticsQueryUtilities::qo_bo_size = 32;
153
154 /** Buffer object size required to run the second functional test. */
155 const unsigned int PipelineStatisticsQueryTestFunctional2::bo_size = 32;
156
157 /** Builds body of a geometry shader, given user-specified properties.
158  *
159  *  This function works in two different ways:
160  *
161  *  1) If the caller only needs the geometry shader to use a single stream, the body
162  *     will be constructed in a way that ignores stream existence completely.
163  *  2) Otherwise, the shader will only be compilable by platforms that support vertex
164  *     streams.
165  *
166  *  The shader will emit @param n_primitives_to_emit_in_stream0 primitives on the zeroth
167  *  stream, (@param n_primitives_to_emit_in_stream0 + 1) primitives on the first stream,
168  *  and so on.
169  *
170  *  @param gs_input                         Input primitive type that should be used by the geometry shader body.
171  *  @param gs_output                        Output primitive type that should be used by the geometry shader body.
172  *  @param n_primitives_to_emit_in_stream0  Number of primitives to be emitted on the zeroth vertex stream.
173  *  @param n_streams                        Number of streams the geometry shader should emit primitives on.
174  *
175  *  @return Geometry shader body.
176  **/
177 std::string PipelineStatisticsQueryUtilities::buildGeometryShaderBody(_geometry_shader_input  gs_input,
178                                                                                                                                           _geometry_shader_output gs_output,
179                                                                                                                                           unsigned int n_primitives_to_emit_in_stream0,
180                                                                                                                                           unsigned int n_streams)
181 {
182         DE_ASSERT(n_primitives_to_emit_in_stream0 >= 1);
183         DE_ASSERT(n_streams >= 1);
184
185         /* Each stream will output (n+1) primitives, where n corresponds to the number of primitives emitted
186          * by the previous stream. Stream 0 emits user-defined number of primitievs.
187          */
188         std::stringstream gs_body_sstream;
189         const std::string gs_input_string  = getGLSLStringForGSInput(gs_input);
190         const std::string gs_output_string = getGLSLStringForGSOutput(gs_output);
191         unsigned int      n_max_vertices   = 0;
192         unsigned int      n_vertices_required_for_gs_output =
193                 PipelineStatisticsQueryUtilities::getNumberOfVerticesForGSOutput(gs_output);
194
195         for (unsigned int n_stream = 0; n_stream < n_streams; ++n_stream)
196         {
197                 n_max_vertices += n_vertices_required_for_gs_output * (n_primitives_to_emit_in_stream0 + n_stream);
198         } /* for (all streams) */
199
200         /* Form the preamble. Note that we need to use the right ES SL version,
201          * since vertex streams are not a core GL3.2 feature.
202          **/
203         gs_body_sstream << ((n_streams > 1) ? "#version 400" : "#version 150\n") << "\n"
204                                                                                                                                                                 "layout("
205                                         << gs_input_string << ")                 in;\n"
206                                                                                   "layout("
207                                         << gs_output_string << ", max_vertices=" << n_max_vertices << ") out;\n";
208
209         /* If we need to define multiple streams, do it now */
210         if (n_streams > 1)
211         {
212                 gs_body_sstream << "\n";
213
214                 for (unsigned int n_stream = 0; n_stream < n_streams; ++n_stream)
215                 {
216                         gs_body_sstream << "layout(stream = " << n_stream << ") out vec4 out_stream" << n_stream << ";\n";
217                 } /* for (all streams) */
218         }        /* if (n_streams > 1) */
219
220         /* Contine forming actual body */
221         gs_body_sstream << "\n"
222                                            "void main()\n"
223                                            "{\n";
224
225         /* Emit primitives */
226         const unsigned int n_output_primitive_vertices =
227                 PipelineStatisticsQueryUtilities::getNumberOfVerticesForGSOutput(gs_output);
228
229         for (unsigned int n_stream = 0; n_stream < n_streams; ++n_stream)
230         {
231                 const unsigned int n_primitives_to_emit = n_primitives_to_emit_in_stream0 + n_stream;
232
233                 for (unsigned int n_primitive = 0; n_primitive < n_primitives_to_emit; ++n_primitive)
234                 {
235                         for (unsigned int n_vertex = 0; n_vertex < n_output_primitive_vertices; ++n_vertex)
236                         {
237                                 gs_body_sstream << "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n";
238
239                                 if (n_streams == 1)
240                                 {
241                                         gs_body_sstream << "    EmitVertex();\n";
242                                 }
243                                 else
244                                 {
245                                         gs_body_sstream << "    EmitStreamVertex(" << n_stream << ");\n";
246                                 }
247                         }
248
249                         if (n_streams == 1)
250                         {
251                                 gs_body_sstream << "    EndPrimitive();\n";
252                         }
253                         else
254                         {
255                                 gs_body_sstream << "    EndStreamPrimitive(" << n_stream << ");\n";
256                         }
257                 } /* for (all primitives the caller wants the shader to emit) */
258         }        /* for (all streams) */
259
260         gs_body_sstream << "}\n";
261
262         return gs_body_sstream.str();
263 }
264
265 /** Executes the query and collects the result data from both query object buffer object
266  *  (if these are supported by the running OpenGL implementation) and the query counters.
267  *  The result data is then exposed via @param out_result.
268  *
269  *  @param query_type     Type of the query to be executed for the iteration.
270  *  @param qo_id          ID of the query object to be used for the execution.
271  *                        The query object must not have been assigned a type
272  *                        prior to the call, or the type must be a match with
273  *                        @param query_type .
274  *  @param qo_bo_id       ID of the query buffer object to use for the call.
275  *                        Pass 0, if the running OpenGL implementation does not
276  *                        support QBOs.
277  *  @param pfn_draw       Function pointer to caller-specific routine that is
278  *                        going to execute the draw call. Must not be NULL.
279  *  @param draw_user_arg  Caller-specific user argument to be passed with the
280  *                        @param pfn_draw callback.
281  *  @param render_context glu::RenderContext& to be used by the method.
282  *  @param test_context   tcu::TestContext& to be used by the method.
283  *  @param context_info   glu::ContextInfo& to be used by the method.
284  *  @param out_result     Deref will be used to store the test execution result.
285  *                        Must not be NULL. Will only be modified if the method
286  *                        returns true.
287  *
288  *  @return true if the test executed successfully, and @param out_result 's fields
289  *          were modified.
290  *
291  */
292 bool PipelineStatisticsQueryUtilities::executeQuery(glw::GLenum query_type, glw::GLuint qo_id, glw::GLuint qo_bo_id,
293                                                                                                         PFNQUERYDRAWHANDLERPROC pfn_draw, void* draw_user_arg,
294                                                                                                         const glu::RenderContext& render_context,
295                                                                                                         tcu::TestContext&                 test_context,
296                                                                                                         const glu::ContextInfo&   context_info,
297                                                                                                         _test_execution_result*   out_result)
298 {
299         glw::GLenum                       error_code = GL_NO_ERROR;
300         const glw::Functions& gl                 = render_context.getFunctions();
301         bool                              result         = true;
302
303         /* Check if the implementation provides non-zero number of bits for the query.
304          * Queries, for which GL implementations provide zero bits of space return
305          * indeterminate values, so we should skip them */
306         glw::GLint n_query_bits = 0;
307
308         gl.getQueryiv(query_type, GL_QUERY_COUNTER_BITS, &n_query_bits);
309
310         error_code = gl.getError();
311         if (error_code != GL_NO_ERROR)
312         {
313                 test_context.getLog() << tcu::TestLog::Message
314                                                           << "glGetQueryiv() call failed for GL_QUERY_COUNTER_BITS pname and "
315                                                           << PipelineStatisticsQueryUtilities::getStringForEnum(query_type) << "query target."
316                                                           << tcu::TestLog::EndMessage;
317
318                 return false;
319         }
320
321         if (n_query_bits == 0)
322         {
323                 test_context.getLog() << tcu::TestLog::Message << "Skipping "
324                                                                                                                   "["
325                                                           << PipelineStatisticsQueryUtilities::getStringForEnum(query_type)
326                                                           << "]"
327                                                                  ": zero bits available for counter storage"
328                                                           << tcu::TestLog::EndMessage;
329
330                 return result;
331         }
332
333         /* Start the query */
334         gl.beginQuery(query_type, qo_id);
335
336         error_code = gl.getError();
337         if (error_code != GL_NO_ERROR)
338         {
339                 test_context.getLog() << tcu::TestLog::Message
340                                                           << "A valid glBeginQuery() call generated the following error code:"
341                                                                  "["
342                                                           << error_code << "]" << tcu::TestLog::EndMessage;
343
344                 return false;
345         }
346
347         /* If GL_ARB_query_buffer_object is supported and the caller supplied a BO id, use
348          * it before we fire any draw calls */
349         if (context_info.isExtensionSupported("GL_ARB_query_buffer_object") && qo_bo_id != 0)
350         {
351                 gl.bindBuffer(GL_QUERY_BUFFER, qo_bo_id);
352
353                 error_code = gl.getError();
354                 if (error_code != GL_NO_ERROR)
355                 {
356                         test_context.getLog() << tcu::TestLog::Message
357                                                                   << "Could not bind a buffer object to GL_QUERY_BUFFER buffer object "
358                                                                          "binding point. Error reported:"
359                                                                          "["
360                                                                   << error_code << "]" << tcu::TestLog::EndMessage;
361
362                         /* Stop the query before we leave */
363                         gl.endQuery(query_type);
364
365                         return false;
366                 } /* if (buffer binding operation failed) */
367         }        /* if (GL_ARB_query_buffer_object extension is supported and the supplied QO BO id
368          *     is not 0) */
369         else
370         {
371                 /* Reset the QO BO id, so that we can skip the checks later */
372                 qo_bo_id = 0;
373         }
374
375         /* Perform the draw calls, if any supplied call-back function pointer was supplied
376          * by the caller. */
377         if (pfn_draw != DE_NULL)
378         {
379                 pfn_draw(draw_user_arg);
380         }
381
382         /* End the query */
383         gl.endQuery(query_type);
384
385         error_code = gl.getError();
386         if (error_code != GL_NO_ERROR)
387         {
388                 test_context.getLog() << tcu::TestLog::Message << "glEndQuery() call failed with error code"
389                                                                                                                   "["
390                                                           << error_code << "]" << tcu::TestLog::EndMessage;
391
392                 return false;
393         } /* if (glEndQuery() call failed) */
394
395         /* We now need to retrieve the result data using all query getter functions
396          * GL has to offer. This will be handled in two iterations:
397          *
398          * 1. The data will be retrieved using the getters without a QO BO being bound.
399          * 2. If QO was provided, we will need to issue all getter calls executed against
400          *    the QO BO. We will then need to retrieve that data directly from the BO
401          *    storage.
402          */
403         const unsigned int iteration_index_wo_qo_bo   = 0;
404         const unsigned int iteration_index_with_qo_bo = 1;
405
406         for (unsigned int n_iteration = 0; n_iteration < 2; /* as per description */
407                  ++n_iteration)
408         {
409                 glw::GLint*     offset_int                       = DE_NULL;
410                 glw::GLint64*  offset_int64                      = DE_NULL;
411                 glw::GLuint*   offset_uint                       = DE_NULL;
412                 glw::GLuint64* offset_uint64             = DE_NULL;
413                 glw::GLint       result_int                      = INT_MAX;
414                 glw::GLint64   result_int64                      = LLONG_MAX;
415                 bool               result_int64_written  = false;
416                 glw::GLuint     result_uint                      = UINT_MAX;
417                 glw::GLuint64  result_uint64             = ULLONG_MAX;
418                 bool               result_uint64_written = false;
419
420                 /* Skip the QO BO iteration if QO BO id has not been provided */
421                 if (n_iteration == iteration_index_with_qo_bo && qo_bo_id == 0)
422                 {
423                         continue;
424                 }
425
426                 /* Determine the offsets we should use for the getter calls */
427                 if (n_iteration == iteration_index_wo_qo_bo)
428                 {
429                         offset_int      = &result_int;
430                         offset_int64  = &result_int64;
431                         offset_uint   = &result_uint;
432                         offset_uint64 = &result_uint64;
433                 }
434                 else
435                 {
436                         offset_int      = (glw::GLint*)(deUintptr)PipelineStatisticsQueryUtilities::qo_bo_int_offset;
437                         offset_int64  = (glw::GLint64*)(deUintptr)PipelineStatisticsQueryUtilities::qo_bo_int64_offset;
438                         offset_uint   = (glw::GLuint*)(deUintptr)PipelineStatisticsQueryUtilities::qo_bo_uint_offset;
439                         offset_uint64 = (glw::GLuint64*)(deUintptr)PipelineStatisticsQueryUtilities::qo_bo_uint64_offset;
440                 }
441
442                 /* Bind the QO BO if we need to use it for the getter calls */
443                 if (n_iteration == iteration_index_with_qo_bo)
444                 {
445                         gl.bindBuffer(GL_QUERY_BUFFER, qo_bo_id);
446                 }
447                 else
448                 {
449                         gl.bindBuffer(GL_QUERY_BUFFER, 0 /* buffer */);
450                 }
451
452                 error_code = gl.getError();
453                 if (error_code != GL_NO_ERROR)
454                 {
455                         test_context.getLog() << tcu::TestLog::Message
456                                                                   << "glBindBuffer() call failed for GL_QUERY_BUFFER target with error "
457                                                                          "["
458                                                                   << error_code << "]" << tcu::TestLog::EndMessage;
459
460                         return false;
461                 }
462
463                 /* Issue the getter calls.
464                  *
465                  * NOTE: 64-bit getter calls are supported only if >= GL 3.3*/
466                 if (glu::contextSupports(render_context.getType(), glu::ApiType::core(3, 3)))
467                 {
468                         gl.getQueryObjecti64v(qo_id, GL_QUERY_RESULT, offset_int64);
469
470                         error_code = gl.getError();
471                         if (error_code != GL_NO_ERROR)
472                         {
473                                 test_context.getLog() << tcu::TestLog::Message << "glGetQueryObjecti64v() call failed with error "
474                                                                                                                                   "["
475                                                                           << error_code << "]" << tcu::TestLog::EndMessage;
476
477                                 return false;
478                         }
479
480                         result_int64_written = true;
481                 }
482                 else
483                 {
484                         result_int64_written = false;
485                 }
486
487                 gl.getQueryObjectiv(qo_id, GL_QUERY_RESULT, offset_int);
488
489                 error_code = gl.getError();
490                 if (error_code != GL_NO_ERROR)
491                 {
492                         test_context.getLog() << tcu::TestLog::Message << "glGetQueryObjectiv() call failed with error "
493                                                                                                                           "["
494                                                                   << error_code << "]" << tcu::TestLog::EndMessage;
495
496                         return false;
497                 }
498
499                 if (glu::contextSupports(render_context.getType(), glu::ApiType::core(3, 3)))
500                 {
501                         gl.getQueryObjectui64v(qo_id, GL_QUERY_RESULT, offset_uint64);
502
503                         error_code = gl.getError();
504                         if (error_code != GL_NO_ERROR)
505                         {
506                                 test_context.getLog() << tcu::TestLog::Message << "glGetQueryObjectui64v() call failed with error "
507                                                                                                                                   "["
508                                                                           << error_code << "]" << tcu::TestLog::EndMessage;
509
510                                 return false;
511                         }
512
513                         result_uint64_written = true;
514                 }
515                 else
516                 {
517                         result_uint64_written = false;
518                 }
519
520                 gl.getQueryObjectuiv(qo_id, GL_QUERY_RESULT, offset_uint);
521
522                 error_code = gl.getError();
523                 if (error_code != GL_NO_ERROR)
524                 {
525                         test_context.getLog() << tcu::TestLog::Message << "glGetQueryObjectuiv() call failed with error "
526                                                                                                                           "["
527                                                                   << error_code << "]" << tcu::TestLog::EndMessage;
528
529                         return false;
530                 }
531
532                 /* If the getters wrote the result values to the BO, we need to retrieve the data
533                  * from the BO storage */
534                 if (n_iteration == iteration_index_with_qo_bo)
535                 {
536                         /* Map the BO to process space */
537                         const unsigned char* bo_data_ptr = (const unsigned char*)gl.mapBuffer(GL_QUERY_BUFFER, GL_READ_ONLY);
538
539                         error_code = gl.getError();
540
541                         if (error_code != GL_NO_ERROR || bo_data_ptr == NULL)
542                         {
543                                 test_context.getLog() << tcu::TestLog::Message << "QO BO mapping failed with error "
544                                                                                                                                   "["
545                                                                           << error_code << "] and data ptr returned:"
546                                                                                                            "["
547                                                                           << bo_data_ptr << "]" << tcu::TestLog::EndMessage;
548
549                                 return false;
550                         }
551
552                         /* Retrieve the query result data */
553                         result_int      = *(glw::GLint*)(bo_data_ptr + (int)(deIntptr)offset_int);
554                         result_int64  = *(glw::GLint64*)(bo_data_ptr + (int)(deIntptr)offset_int64);
555                         result_uint   = *(glw::GLuint*)(bo_data_ptr + (int)(deIntptr)offset_uint);
556                         result_uint64 = *(glw::GLuint64*)(bo_data_ptr + (int)(deIntptr)offset_uint64);
557
558                         /* Unmap the BO */
559                         gl.unmapBuffer(GL_QUERY_BUFFER);
560
561                         error_code = gl.getError();
562                         if (error_code != GL_NO_ERROR)
563                         {
564                                 test_context.getLog() << tcu::TestLog::Message << "QO BO unmapping failed with error "
565                                                                                                                                   "["
566                                                                           << error_code << "]" << tcu::TestLog::EndMessage;
567
568                                 return false;
569                         }
570                 } /* if (QO BO iteration) */
571
572                 /* Store the retrieved data in user-provided location */
573                 if (n_iteration == iteration_index_with_qo_bo)
574                 {
575                         out_result->result_qo_int       = result_int;
576                         out_result->result_qo_int64  = result_int64;
577                         out_result->result_qo_uint   = result_uint;
578                         out_result->result_qo_uint64 = result_uint64;
579                 }
580                 else
581                 {
582                         out_result->result_int  = result_int;
583                         out_result->result_int64  = result_int64;
584                         out_result->result_uint   = result_uint;
585                         out_result->result_uint64 = result_uint64;
586                 }
587
588                 out_result->int64_written  = result_int64_written;
589                 out_result->uint64_written = result_uint64_written;
590         } /* for (both iterations) */
591         return result;
592 }
593
594 /** Retrieves a GLenum value corresponding to internal _primitive_type
595  *  enum value.
596  *
597  *  @param primitive_type Internal primitive type to use for the getter call.
598  *
599  *  @return Corresponding GL value that can be used for the draw calls, or
600  *          GL_NONE if the conversion failed.
601  *
602  **/
603 glw::GLenum PipelineStatisticsQueryUtilities::getEnumForPrimitiveType(_primitive_type primitive_type)
604 {
605         glw::GLenum result = GL_NONE;
606
607         switch (primitive_type)
608         {
609         case PRIMITIVE_TYPE_POINTS:
610                 result = GL_POINTS;
611                 break;
612         case PRIMITIVE_TYPE_LINE_LOOP:
613                 result = GL_LINE_LOOP;
614                 break;
615         case PRIMITIVE_TYPE_LINE_STRIP:
616                 result = GL_LINE_STRIP;
617                 break;
618         case PRIMITIVE_TYPE_LINES:
619                 result = GL_LINES;
620                 break;
621         case PRIMITIVE_TYPE_LINES_ADJACENCY:
622                 result = GL_LINES_ADJACENCY;
623                 break;
624         case PRIMITIVE_TYPE_PATCHES:
625                 result = GL_PATCHES;
626                 break;
627         case PRIMITIVE_TYPE_TRIANGLE_FAN:
628                 result = GL_TRIANGLE_FAN;
629                 break;
630         case PRIMITIVE_TYPE_TRIANGLE_STRIP:
631                 result = GL_TRIANGLE_STRIP;
632                 break;
633         case PRIMITIVE_TYPE_TRIANGLES:
634                 result = GL_TRIANGLES;
635                 break;
636         case PRIMITIVE_TYPE_TRIANGLES_ADJACENCY:
637                 result = GL_TRIANGLES_ADJACENCY;
638                 break;
639
640         default:
641         {
642                 TCU_FAIL("Unrecognized primitive type");
643         }
644         } /* switch (primitive_type) */
645
646         return result;
647 }
648
649 /** Retrieves a human-readable name for a _geometry_shader_input value.
650  *
651  *  @param gs_input Internal _geometry_shader_input value to use for
652  *                  the conversion.
653  *
654  *  @return Human-readable string or empty string, if the conversion failed.
655  *
656  **/
657 std::string PipelineStatisticsQueryUtilities::getGLSLStringForGSInput(_geometry_shader_input gs_input)
658 {
659         std::string result;
660
661         switch (gs_input)
662         {
663         case GEOMETRY_SHADER_INPUT_POINTS:
664                 result = "points";
665                 break;
666         case GEOMETRY_SHADER_INPUT_LINES:
667                 result = "lines";
668                 break;
669         case GEOMETRY_SHADER_INPUT_LINES_ADJACENCY:
670                 result = "lines_adjacency";
671                 break;
672         case GEOMETRY_SHADER_INPUT_TRIANGLES:
673                 result = "triangles";
674                 break;
675         case GEOMETRY_SHADER_INPUT_TRIANGLES_ADJACENCY:
676                 result = "triangles_adjacency";
677                 break;
678
679         default:
680         {
681                 TCU_FAIL("Unrecognized geometry shader input enum");
682         }
683         } /* switch (gs_input) */
684
685         return result;
686 }
687
688 /** Retrieves a human-readable string for a _geometry_shader_output value.
689  *
690  *  @param  gs_output _geometry_shader_output value to use for the conversion.
691  *
692  *  @return Requested value or empty string, if the value was not recognized.
693  *
694  **/
695 std::string PipelineStatisticsQueryUtilities::getGLSLStringForGSOutput(_geometry_shader_output gs_output)
696 {
697         std::string result;
698
699         switch (gs_output)
700         {
701         case GEOMETRY_SHADER_OUTPUT_POINTS:
702                 result = "points";
703                 break;
704         case GEOMETRY_SHADER_OUTPUT_LINE_STRIP:
705                 result = "line_strip";
706                 break;
707         case GEOMETRY_SHADER_OUTPUT_TRIANGLE_STRIP:
708                 result = "triangle_strip";
709                 break;
710
711         default:
712         {
713                 TCU_FAIL("Unrecognized geometry shader output enum");
714         }
715         } /* switch (gs_output) */
716
717         return result;
718 }
719
720 /** Number of vertices the geometry shader can access on the input, if the shader
721  *  uses @param gs_input input primitive type.
722  *
723  *  @param gs_input Geometry shader input to use for the query.
724  *
725  *  @return Requested value or 0 if @param gs_input was not recognized.
726  **/
727 unsigned int PipelineStatisticsQueryUtilities::getNumberOfVerticesForGSInput(_geometry_shader_input gs_input)
728 {
729         unsigned int result = 0;
730
731         switch (gs_input)
732         {
733         case GEOMETRY_SHADER_INPUT_POINTS:
734                 result = 1;
735                 break;
736         case GEOMETRY_SHADER_INPUT_LINES:
737                 result = 2;
738                 break;
739         case GEOMETRY_SHADER_INPUT_LINES_ADJACENCY:
740                 result = 4;
741                 break;
742         case GEOMETRY_SHADER_INPUT_TRIANGLES:
743                 result = 3;
744                 break;
745         case GEOMETRY_SHADER_INPUT_TRIANGLES_ADJACENCY:
746                 result = 6;
747                 break;
748
749         default:
750         {
751                 TCU_FAIL("Unrecognized geometry shader input type");
752         }
753         } /* switch (gs_input) */
754
755         return result;
756 }
757
758 /** Retrieves a number of vertices that need to be emitted before the shader
759  *  can end the primitive, with the primitive being complete, assuming the
760  *  geometry shader outputs a primitive of type described by @param gs_output.
761  *
762  *  @param gs_output Primitive type to be outputted by the geometry shader.
763  *
764  *  @return As per description, or 0 if @param gs_output was not recognized.
765  **/
766 unsigned int PipelineStatisticsQueryUtilities::getNumberOfVerticesForGSOutput(_geometry_shader_output gs_output)
767 {
768         unsigned int n_result_vertices = 0;
769
770         switch (gs_output)
771         {
772         case GEOMETRY_SHADER_OUTPUT_LINE_STRIP:
773                 n_result_vertices = 2;
774                 break;
775         case GEOMETRY_SHADER_OUTPUT_POINTS:
776                 n_result_vertices = 1;
777                 break;
778         case GEOMETRY_SHADER_OUTPUT_TRIANGLE_STRIP:
779                 n_result_vertices = 3;
780                 break;
781
782         default:
783                 TCU_FAIL("Unrecognized geometry shader output type");
784         }
785
786         /* All done */
787         return n_result_vertices;
788 }
789
790 /** Returns the number of vertices a single primitive of type described by @param primitive_type
791  *  consists of.
792  *
793  *  @param primitive_type Primitive type to use for the query.
794  *
795  *  @return Result value, or 0 if @param primive_type was not recognized.
796  **/
797 unsigned int PipelineStatisticsQueryUtilities::getNumberOfVerticesForPrimitiveType(_primitive_type primitive_type)
798 {
799         unsigned int result = 0;
800
801         switch (primitive_type)
802         {
803         case PRIMITIVE_TYPE_POINTS:
804                 result = 1;
805                 break;
806         case PRIMITIVE_TYPE_LINE_LOOP:  /* fall-through */
807         case PRIMITIVE_TYPE_LINE_STRIP: /* fall-through */
808         case PRIMITIVE_TYPE_LINES:
809                 result = 2;
810                 break;
811         case PRIMITIVE_TYPE_TRIANGLE_FAN:   /* fall-through */
812         case PRIMITIVE_TYPE_TRIANGLE_STRIP: /* fall-through */
813         case PRIMITIVE_TYPE_TRIANGLES:
814                 result = 3;
815                 break;
816         case PRIMITIVE_TYPE_LINES_ADJACENCY:
817                 result = 4;
818                 break;
819         case PRIMITIVE_TYPE_TRIANGLES_ADJACENCY:
820                 result = 6;
821                 break;
822
823         default:
824                 TCU_FAIL("Unrecognized primitive type");
825         } /* switch (primitive_type) */
826
827         return result;
828 }
829
830 /** Converts user-specified _geometry_shader_input value to a _primitive_type value.
831  *
832  *  @param gs_input Input value for the conversion.
833  *
834  *  @return Requested value, or PRIMITIVE_TYPE_COUNT if the user-specified value
835  *          was unrecognized.
836  **/
837 PipelineStatisticsQueryUtilities::_primitive_type PipelineStatisticsQueryUtilities::getPrimitiveTypeFromGSInput(
838         _geometry_shader_input gs_input)
839 {
840         _primitive_type result = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_COUNT;
841
842         switch (gs_input)
843         {
844         case GEOMETRY_SHADER_INPUT_POINTS:
845                 result = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_POINTS;
846                 break;
847         case GEOMETRY_SHADER_INPUT_LINES:
848                 result = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES;
849                 break;
850         case GEOMETRY_SHADER_INPUT_LINES_ADJACENCY:
851                 result = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES_ADJACENCY;
852                 break;
853         case GEOMETRY_SHADER_INPUT_TRIANGLES:
854                 result = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES;
855                 break;
856         case GEOMETRY_SHADER_INPUT_TRIANGLES_ADJACENCY:
857                 result = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES_ADJACENCY;
858                 break;
859
860         default:
861         {
862                 TCU_FAIL("Unrecognized geometry shader input enum");
863         }
864         } /* switch (gs_input) */
865
866         return result;
867 }
868
869 /** Converts user-specified _draw_call_type value to a human-readable string.
870  *
871  *  @param draw_call_type Input value to use for the conversion.
872  *
873  *  @return Human-readable string, or "[?]" (without the quotation marks) if
874  *          the input value was not recognized.
875  **/
876 std::string PipelineStatisticsQueryUtilities::getStringForDrawCallType(_draw_call_type draw_call_type)
877 {
878         std::string result = "[?]";
879
880         switch (draw_call_type)
881         {
882         case DRAW_CALL_TYPE_GLDRAWARRAYS:
883                 result = "glDrawArrays()";
884                 break;
885         case DRAW_CALL_TYPE_GLDRAWARRAYSINDIRECT:
886                 result = "glDrawArraysIndirect()";
887                 break;
888         case DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCED:
889                 result = "glDrawArraysInstanced()";
890                 break;
891         case DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCEDBASEINSTANCE:
892                 result = "glDrawArraysInstancedBaseInstance()";
893                 break;
894         case DRAW_CALL_TYPE_GLDRAWELEMENTS:
895                 result = "glDrawElements()";
896                 break;
897         case DRAW_CALL_TYPE_GLDRAWELEMENTSBASEVERTEX:
898                 result = "glDrawElementsBaseVertex()";
899                 break;
900         case DRAW_CALL_TYPE_GLDRAWELEMENTSINDIRECT:
901                 result = "glDrawElementsIndirect()";
902                 break;
903         case DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCED:
904                 result = "glDrawElementsInstanced()";
905                 break;
906         case DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEINSTANCE:
907                 result = "glDrawElementsInstancedBaseInstance()";
908                 break;
909         case DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE:
910                 result = "glDrawElementsInstancedBaseVertexBaseInstance()";
911                 break;
912         case DRAW_CALL_TYPE_GLDRAWRANGEELEMENTS:
913                 result = "glDrawRangeElements()";
914                 break;
915         case DRAW_CALL_TYPE_GLDRAWRANGEELEMENTSBASEVERTEX:
916                 result = "glDrawRangeElementsBaseVertex()";
917                 break;
918         default:
919                 DE_ASSERT(0);
920                 break;
921         }
922
923         return result;
924 }
925
926 /** Converts a GL enum value expressing a pipeline statistics query type
927  *  into a human-readable string.
928  *
929  *  @param value Input value to use for the conversion.
930  *
931  *  @return Human-readable string or "[?]" (without the quotation marks)
932  *          if the input value was not recognized.
933  **/
934 std::string PipelineStatisticsQueryUtilities::getStringForEnum(glw::GLenum value)
935 {
936         std::string result = "[?]";
937
938         switch (value)
939         {
940         case GL_CLIPPING_INPUT_PRIMITIVES_ARB:
941                 result = "GL_CLIPPING_INPUT_PRIMITIVES_ARB";
942                 break;
943         case GL_CLIPPING_OUTPUT_PRIMITIVES_ARB:
944                 result = "GL_CLIPPING_OUTPUT_PRIMITIVES_ARB";
945                 break;
946         case GL_COMPUTE_SHADER_INVOCATIONS_ARB:
947                 result = "GL_COMPUTE_SHADER_INVOCATIONS_ARB";
948                 break;
949         case GL_FRAGMENT_SHADER_INVOCATIONS_ARB:
950                 result = "GL_FRAGMENT_SHADER_INVOCATIONS_ARB";
951                 break;
952         case GL_GEOMETRY_SHADER_INVOCATIONS:
953                 result = "GL_GEOMETRY_SHADER_INVOCATIONS";
954                 break;
955         case GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB:
956                 result = "GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB";
957                 break;
958         case GL_PRIMITIVES_SUBMITTED_ARB:
959                 result = "GL_PRIMITIVES_SUBMITTED_ARB";
960                 break;
961         case GL_TESS_CONTROL_SHADER_PATCHES_ARB:
962                 result = "GL_TESS_CONTROL_SHADER_PATCHES_ARB";
963                 break;
964         case GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB:
965                 result = "GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB";
966                 break;
967         case GL_VERTEX_SHADER_INVOCATIONS_ARB:
968                 result = "GL_VERTEX_SHADER_INVOCATIONS_ARB";
969                 break;
970         case GL_VERTICES_SUBMITTED_ARB:
971                 result = "GL_VERTICES_SUBMITTED_ARB";
972                 break;
973         } /* switch (value) */
974
975         return result;
976 }
977
978 /** Converts a _primitive_type value into a human-readable string.
979  *
980  *  @param primitive_type Input value to use for the conversion.
981  *
982  *  @return Requested string or "[?]" (without the quotation marks)
983  *          if the input value was not recognized.
984  **/
985 std::string PipelineStatisticsQueryUtilities::getStringForPrimitiveType(_primitive_type primitive_type)
986 {
987         std::string result = "[?]";
988
989         switch (primitive_type)
990         {
991         case PRIMITIVE_TYPE_POINTS:
992                 result = "GL_POINTS";
993                 break;
994         case PRIMITIVE_TYPE_LINE_LOOP:
995                 result = "GL_LINE_LOOP";
996                 break;
997         case PRIMITIVE_TYPE_LINE_STRIP:
998                 result = "GL_LINE_STRIP";
999                 break;
1000         case PRIMITIVE_TYPE_LINES:
1001                 result = "GL_LINES";
1002                 break;
1003         case PRIMITIVE_TYPE_LINES_ADJACENCY:
1004                 result = "GL_LINES_ADJACENCY";
1005                 break;
1006         case PRIMITIVE_TYPE_PATCHES:
1007                 result = "GL_PATCHES";
1008                 break;
1009         case PRIMITIVE_TYPE_TRIANGLE_FAN:
1010                 result = "GL_TRIANGLE_FAN";
1011                 break;
1012         case PRIMITIVE_TYPE_TRIANGLE_STRIP:
1013                 result = "GL_TRIANGLE_STRIP";
1014                 break;
1015         case PRIMITIVE_TYPE_TRIANGLES:
1016                 result = "GL_TRIANGLES";
1017                 break;
1018         case PRIMITIVE_TYPE_TRIANGLES_ADJACENCY:
1019                 result = "GL_TRIANGLES_ADJACENCY";
1020                 break;
1021         default:
1022                 DE_ASSERT(0);
1023                 break;
1024         }
1025
1026         return result;
1027 }
1028
1029 /** Tells if it is safe to use a specific draw call type.
1030  *
1031  *  @param draw_call Draw call type to use for the query.
1032  *
1033  *  @return True if corresponding GL entry-point is available.
1034  */
1035 bool PipelineStatisticsQueryUtilities::isDrawCallSupported(_draw_call_type draw_call, const glw::Functions& gl)
1036 {
1037
1038         bool result = false;
1039
1040         switch (draw_call)
1041         {
1042         case DRAW_CALL_TYPE_GLDRAWARRAYS:
1043                 result = (gl.drawArrays != DE_NULL);
1044                 break;
1045         case DRAW_CALL_TYPE_GLDRAWARRAYSINDIRECT:
1046                 result = (gl.drawArraysIndirect != DE_NULL);
1047                 break;
1048         case DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCED:
1049                 result = (gl.drawArraysInstanced != DE_NULL);
1050                 break;
1051         case DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCEDBASEINSTANCE:
1052                 result = (gl.drawArraysInstancedBaseInstance != DE_NULL);
1053                 break;
1054         case DRAW_CALL_TYPE_GLDRAWELEMENTS:
1055                 result = (gl.drawElements != DE_NULL);
1056                 break;
1057         case DRAW_CALL_TYPE_GLDRAWELEMENTSBASEVERTEX:
1058                 result = (gl.drawElementsBaseVertex != DE_NULL);
1059                 break;
1060         case DRAW_CALL_TYPE_GLDRAWELEMENTSINDIRECT:
1061                 result = (gl.drawElementsIndirect != DE_NULL);
1062                 break;
1063         case DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCED:
1064                 result = (gl.drawElementsInstanced != DE_NULL);
1065                 break;
1066         case DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEINSTANCE:
1067                 result = (gl.drawElementsInstancedBaseInstance != DE_NULL);
1068                 break;
1069         case DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE:
1070                 result = (gl.drawElementsInstancedBaseVertexBaseInstance != DE_NULL);
1071                 break;
1072         case DRAW_CALL_TYPE_GLDRAWRANGEELEMENTS:
1073                 result = (gl.drawRangeElements != DE_NULL);
1074                 break;
1075         case DRAW_CALL_TYPE_GLDRAWRANGEELEMENTSBASEVERTEX:
1076                 result = (gl.drawRangeElementsBaseVertex != DE_NULL);
1077                 break;
1078
1079         default:
1080         {
1081                 TCU_FAIL("Unrecognized draw call type");
1082         }
1083         } /* switch (draw_call) */
1084
1085         return result;
1086 }
1087
1088 /** Tells if user-specified draw call type is an instanced draw call.
1089  *
1090  *  @param draw_call Input value to use for the conversion.
1091  *
1092  *  @return true if @param draw_call corresponds to an instanced draw call,
1093  *          false otherwise.
1094  **/
1095 bool PipelineStatisticsQueryUtilities::isInstancedDrawCall(_draw_call_type draw_call)
1096 {
1097         bool result =
1098                 (draw_call == PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWARRAYSINDIRECT ||
1099                  draw_call == PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCED ||
1100                  draw_call == PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCEDBASEINSTANCE ||
1101                  draw_call == PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSINDIRECT ||
1102                  draw_call == PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCED ||
1103                  draw_call == PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEINSTANCE ||
1104                  draw_call == PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE);
1105
1106         return result;
1107 }
1108
1109 /** Tells if the running GL implementation supports user-specified pipeline
1110  *  statistics query.
1111  *
1112  *  @param value          GL enum definining the pipeline statistics query type
1113  *                        that should be used for the query.
1114  *  @param context_info   glu::ContextInfo instance that can be used by the method.
1115  *  @param render_context glu::RenderContext instance that can be used by the method.
1116  *
1117  *  @return true if the query is supported, false otherwise. This method will return
1118  *          true for unrecognized enums.
1119  **/
1120 bool PipelineStatisticsQueryUtilities::isQuerySupported(glw::GLenum value, const glu::ContextInfo& context_info,
1121                                                                                                                 const glu::RenderContext& render_context)
1122 {
1123         bool result = true;
1124
1125         switch (value)
1126         {
1127         case GL_GEOMETRY_SHADER_INVOCATIONS:
1128         case GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB:
1129         {
1130                 if (!glu::contextSupports(render_context.getType(), glu::ApiType::core(3, 2)) &&
1131                         !context_info.isExtensionSupported("GL_ARB_geometry_shader4"))
1132                 {
1133                         result = false;
1134                 }
1135
1136                 break;
1137         }
1138
1139         case GL_TESS_CONTROL_SHADER_PATCHES_ARB:
1140         case GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB:
1141         {
1142                 if (!glu::contextSupports(render_context.getType(), glu::ApiType::compatibility(4, 0)) &&
1143                         !context_info.isExtensionSupported("GL_ARB_tessellation_shader"))
1144                 {
1145                         result = false;
1146                 }
1147
1148                 break;
1149         }
1150
1151         case GL_COMPUTE_SHADER_INVOCATIONS_ARB:
1152         {
1153                 if (!glu::contextSupports(render_context.getType(), glu::ApiType::core(4, 3)) &&
1154                         !context_info.isExtensionSupported("GL_ARB_compute_shader"))
1155                 {
1156                         result = false;
1157                 }
1158
1159                 break;
1160         }
1161         } /* switch (value) */
1162
1163         return result;
1164 }
1165
1166 /** Takes a filled _test_execution_result structure and performs the validation
1167  *  of the embedded data.
1168  *
1169  *  @param run_result                   A filled _test_execution_result structure that
1170  *                                      should be used as input by the method.
1171  *  @param n_expected_values            Number of possible expected values.
1172  *  @param expected_values              Array of possible expected values.
1173  *  @param should_check_qo_bo_values    true if the method should also verify the values
1174  *                                      retrieved from a query buffer object, false
1175  *                                      if it is OK to ignore them.
1176  *  @param query_type                   Pipeline statistics query type that was used to
1177  *                                      capture the results stored in @param run_result .
1178  *  @param draw_call_type_ptr           Type of the draw call that was used to capture the
1179  *                                      results stored in @param run_result .
1180  *  @param primitive_type_ptr           Primitive type that was used for the draw call that
1181  *                                      was used to capture the results stored in @param
1182  *                                      run_result .
1183  *  @param is_primitive_restart_enabled true if "Primitive Restart" rendering mode had been enabled
1184  *                                      when the draw call used to capture the results was made.
1185  *  @param test_context                 tcu::TestContext instance that the method can use.
1186  *  @param verification_type            Tells how the captured values should be compared against the
1187  *                                      reference value.
1188  *
1189  *  @return true if the result values were found valid, false otherwise.
1190  **/
1191 bool PipelineStatisticsQueryUtilities::verifyResultValues(
1192         const _test_execution_result& run_result, unsigned int n_expected_values, const glw::GLuint64* expected_values,
1193         bool should_check_qo_bo_values, const glw::GLenum query_type, const _draw_call_type* draw_call_type_ptr,
1194         const _primitive_type* primitive_type_ptr, bool is_primitive_restart_enabled, tcu::TestContext& test_context,
1195         _verification_type verification_type)
1196 {
1197         bool result = true;
1198
1199         /* Make sure all values are set to one of the expected values */
1200         std::string draw_call_name;
1201         std::string primitive_name;
1202
1203         bool is_result_int_valid           = false;
1204         bool is_result_int64_valid       = false;
1205         bool is_result_uint_valid         = false;
1206         bool is_result_uint64_valid     = false;
1207         bool is_result_qo_int_valid     = false;
1208         bool is_result_qo_int64_valid  = false;
1209         bool is_result_qo_uint_valid   = false;
1210         bool is_result_qo_uint64_valid = false;
1211
1212         if (draw_call_type_ptr != DE_NULL)
1213         {
1214                 draw_call_name = getStringForDrawCallType(*draw_call_type_ptr);
1215         }
1216         else
1217         {
1218                 draw_call_name = "(does not apply)";
1219         }
1220
1221         if (primitive_type_ptr != DE_NULL)
1222         {
1223                 primitive_name = getStringForPrimitiveType(*primitive_type_ptr);
1224         }
1225         else
1226         {
1227                 primitive_name = "(does not apply)";
1228         }
1229
1230         for (unsigned int n_expected_value = 0; n_expected_value < n_expected_values; ++n_expected_value)
1231         {
1232                 glw::GLuint64 expected_value = 0;
1233
1234                 expected_value = expected_values[n_expected_value];
1235
1236                 if ((verification_type == VERIFICATION_TYPE_EXACT_MATCH &&
1237                          (glw::GLuint64)run_result.result_int == expected_value) ||
1238                         (verification_type == VERIFICATION_TYPE_EQUAL_OR_GREATER &&
1239                          (glw::GLuint64)run_result.result_int >= expected_value))
1240                 {
1241                         is_result_int_valid = true;
1242                 }
1243
1244                 if (run_result.int64_written && ((verification_type == VERIFICATION_TYPE_EXACT_MATCH &&
1245                                                                                   run_result.result_int64 == (glw::GLint64)expected_value) ||
1246                                                                                  (verification_type == VERIFICATION_TYPE_EQUAL_OR_GREATER &&
1247                                                                                   run_result.result_int64 >= (glw::GLint64)expected_value)))
1248                 {
1249                         is_result_int64_valid = true;
1250                 }
1251
1252                 if ((verification_type == VERIFICATION_TYPE_EXACT_MATCH &&
1253                          (glw::GLuint64)run_result.result_uint == expected_value) ||
1254                         (verification_type == VERIFICATION_TYPE_EQUAL_OR_GREATER &&
1255                          (glw::GLuint64)run_result.result_uint >= expected_value))
1256                 {
1257                         is_result_uint_valid = true;
1258                 }
1259
1260                 if (run_result.uint64_written &&
1261                         ((verification_type == VERIFICATION_TYPE_EXACT_MATCH && run_result.result_uint64 == expected_value) ||
1262                          (verification_type == VERIFICATION_TYPE_EQUAL_OR_GREATER && run_result.result_uint64 >= expected_value)))
1263                 {
1264                         is_result_uint64_valid = true;
1265                 }
1266
1267                 if (should_check_qo_bo_values)
1268                 {
1269                         if ((verification_type == VERIFICATION_TYPE_EXACT_MATCH &&
1270                                  (glw::GLuint64)run_result.result_qo_int == expected_value) ||
1271                                 (verification_type == VERIFICATION_TYPE_EQUAL_OR_GREATER &&
1272                                  (glw::GLuint64)run_result.result_qo_int >= expected_value))
1273                         {
1274                                 is_result_qo_int_valid = true;
1275                         }
1276
1277                         if (run_result.int64_written && ((verification_type == VERIFICATION_TYPE_EXACT_MATCH &&
1278                                                                                           run_result.result_qo_int64 == (glw::GLint64)expected_value) ||
1279                                                                                          (verification_type == VERIFICATION_TYPE_EQUAL_OR_GREATER &&
1280                                                                                           run_result.result_qo_int64 >= (glw::GLint64)expected_value)))
1281                         {
1282                                 is_result_qo_int64_valid = true;
1283                         }
1284
1285                         if ((verification_type == VERIFICATION_TYPE_EXACT_MATCH &&
1286                                  (glw::GLuint64)run_result.result_qo_uint == expected_value) ||
1287                                 (verification_type == VERIFICATION_TYPE_EQUAL_OR_GREATER &&
1288                                  (glw::GLuint64)run_result.result_qo_uint >= expected_value))
1289                         {
1290                                 is_result_qo_uint_valid = true;
1291                         }
1292
1293                         if (run_result.uint64_written && ((verification_type == VERIFICATION_TYPE_EXACT_MATCH &&
1294                                                                                            run_result.result_qo_uint64 == expected_value) ||
1295                                                                                           (verification_type == VERIFICATION_TYPE_EQUAL_OR_GREATER &&
1296                                                                                            run_result.result_qo_uint64 >= expected_value)))
1297                         {
1298                                 is_result_qo_uint64_valid = true;
1299                         }
1300                 } /* if (should_check_qo_bo_values) */
1301         }        /* for (both expected values) */
1302
1303         if (!is_result_int_valid)
1304         {
1305                 std::string log = PipelineStatisticsQueryUtilities::getVerifyResultValuesErrorString<glw::GLint>(
1306                         run_result.result_int, "non-QO BO int32", n_expected_values, expected_values, query_type, draw_call_name,
1307                         primitive_name, is_primitive_restart_enabled);
1308
1309                 test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1310
1311                 result = false;
1312         }
1313
1314         if (run_result.int64_written && !is_result_int64_valid)
1315         {
1316                 std::string log = PipelineStatisticsQueryUtilities::getVerifyResultValuesErrorString<glw::GLint64>(
1317                         run_result.result_int64, "non-QO BO int64", n_expected_values, expected_values, query_type, draw_call_name,
1318                         primitive_name, is_primitive_restart_enabled);
1319
1320                 test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1321
1322                 result = false;
1323         }
1324
1325         if (!is_result_uint_valid)
1326         {
1327                 std::string log = PipelineStatisticsQueryUtilities::getVerifyResultValuesErrorString<glw::GLuint>(
1328                         run_result.result_uint, "non-QO BO uint32", n_expected_values, expected_values, query_type, draw_call_name,
1329                         primitive_name, is_primitive_restart_enabled);
1330
1331                 test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1332
1333                 result = false;
1334         }
1335
1336         if (run_result.uint64_written && !is_result_uint64_valid)
1337         {
1338                 std::string log = PipelineStatisticsQueryUtilities::getVerifyResultValuesErrorString<glw::GLuint64>(
1339                         run_result.result_uint, "non-QO BO uint64", n_expected_values, expected_values, query_type, draw_call_name,
1340                         primitive_name, is_primitive_restart_enabled);
1341
1342                 test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1343
1344                 result = false;
1345         }
1346
1347         if (should_check_qo_bo_values)
1348         {
1349                 if (!is_result_qo_int_valid)
1350                 {
1351                         std::string log = PipelineStatisticsQueryUtilities::getVerifyResultValuesErrorString<glw::GLint>(
1352                                 run_result.result_qo_int, "QO BO int32", n_expected_values, expected_values, query_type, draw_call_name,
1353                                 primitive_name, is_primitive_restart_enabled);
1354
1355                         test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1356
1357                         result = false;
1358                 }
1359
1360                 if (run_result.int64_written && !is_result_qo_int64_valid)
1361                 {
1362                         std::string log = PipelineStatisticsQueryUtilities::getVerifyResultValuesErrorString<glw::GLint64>(
1363                                 run_result.result_qo_int64, "QO BO int64", n_expected_values, expected_values, query_type,
1364                                 draw_call_name, primitive_name, is_primitive_restart_enabled);
1365
1366                         test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1367
1368                         result = false;
1369                 }
1370
1371                 if (!is_result_qo_uint_valid)
1372                 {
1373                         std::string log = PipelineStatisticsQueryUtilities::getVerifyResultValuesErrorString<glw::GLuint>(
1374                                 run_result.result_qo_uint, "QO BO uint32", n_expected_values, expected_values, query_type,
1375                                 draw_call_name, primitive_name, is_primitive_restart_enabled);
1376
1377                         test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1378
1379                         result = false;
1380                 }
1381
1382                 if (run_result.uint64_written && !is_result_qo_uint64_valid)
1383                 {
1384                         std::string log = PipelineStatisticsQueryUtilities::getVerifyResultValuesErrorString<glw::GLuint64>(
1385                                 run_result.result_qo_uint64, "QO BO uint64", n_expected_values, expected_values, query_type,
1386                                 draw_call_name, primitive_name, is_primitive_restart_enabled);
1387
1388                         test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1389
1390                         result = false;
1391                 }
1392         }
1393
1394         return result;
1395 }
1396
1397 /** Constructor.
1398  *
1399  *  @param context     Rendering context
1400  *  @param name        Test name
1401  *  @param description Test description
1402  */
1403 PipelineStatisticsQueryTestAPICoverage1::PipelineStatisticsQueryTestAPICoverage1(deqp::Context& context)
1404         : TestCase(context, "api_coverage_invalid_glbeginquery_calls",
1405                            "Verifies that an attempt to assign a different query object type "
1406                            "to an object thas has already been assigned a type, results in "
1407                            "an error.")
1408         , m_qo_id(0)
1409 {
1410         /* Left blank intentionally */
1411 }
1412
1413 /** Deinitializes all GL objects that were created during test execution. */
1414 void PipelineStatisticsQueryTestAPICoverage1::deinit()
1415 {
1416         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1417
1418         if (m_qo_id != 0)
1419         {
1420                 gl.deleteQueries(1, &m_qo_id);
1421
1422                 m_qo_id = 0;
1423         }
1424 }
1425
1426 /** Executes test iteration.
1427  *
1428  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1429  */
1430 tcu::TestNode::IterateResult PipelineStatisticsQueryTestAPICoverage1::iterate()
1431 {
1432         const glu::ContextInfo& context_info   = m_context.getContextInfo();
1433         bool                                    has_passed       = true;
1434         glu::RenderContext&             render_context = m_context.getRenderContext();
1435         glu::ContextType                contextType     = m_context.getRenderContext().getType();
1436
1437         /* Only continue if GL_ARB_pipeline_statistics_query extension is supported */
1438         if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
1439                 !context_info.isExtensionSupported("GL_ARB_pipeline_statistics_query"))
1440         {
1441                 throw tcu::NotSupportedError("GL_ARB_pipeline_statistics_query extension is not supported");
1442         }
1443
1444         /* Verify that a query object which has been assigned a pipeline statistics query target A,
1445          * cannot be assigned another type B (assuming A != B) */
1446         const glw::Functions& gl = render_context.getFunctions();
1447
1448         for (unsigned int n_current_item = 0; n_current_item < PipelineStatisticsQueryUtilities::n_query_targets;
1449                  ++n_current_item)
1450         {
1451                 glw::GLenum current_pq = PipelineStatisticsQueryUtilities::query_targets[n_current_item];
1452
1453                 /* Make sure the query is supported */
1454                 if (!PipelineStatisticsQueryUtilities::isQuerySupported(current_pq, context_info, render_context))
1455                 {
1456                         continue;
1457                 }
1458
1459                 /* Generate a new query object */
1460                 gl.genQueries(1, &m_qo_id);
1461                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries() call failed.");
1462
1463                 /* Assign a type to the query object */
1464                 gl.beginQuery(current_pq, m_qo_id);
1465                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery() call failed.");
1466
1467                 gl.endQuery(current_pq);
1468                 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery() call failed.");
1469
1470                 for (unsigned int n_different_item = 0; n_different_item < PipelineStatisticsQueryUtilities::n_query_targets;
1471                          ++n_different_item)
1472                 {
1473                         glw::GLenum different_pq = PipelineStatisticsQueryUtilities::query_targets[n_different_item];
1474
1475                         if (current_pq == different_pq)
1476                         {
1477                                 /* Skip valid iterations */
1478                                 continue;
1479                         }
1480
1481                         /* Make sure the other query type is supported */
1482                         if (!PipelineStatisticsQueryUtilities::isQuerySupported(different_pq, context_info, render_context))
1483                         {
1484                                 continue;
1485                         }
1486
1487                         /* Try using a different type for the same object */
1488                         glw::GLenum error_code = GL_NO_ERROR;
1489
1490                         gl.beginQuery(different_pq, m_qo_id);
1491
1492                         /* Has GL_INVALID_OPERATION error been generated? */
1493                         error_code = gl.getError();
1494
1495                         if (error_code != GL_INVALID_OPERATION)
1496                         {
1497                                 m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected error code "
1498                                                                                                                            "["
1499                                                                    << error_code << "]"
1500                                                                                                         " generated when using glBeginQuery() for a query object of type "
1501                                                                                                         "["
1502                                                                    << PipelineStatisticsQueryUtilities::getStringForEnum(current_pq)
1503                                                                    << "]"
1504                                                                           ", when used for a query type "
1505                                                                           "["
1506                                                                    << PipelineStatisticsQueryUtilities::getStringForEnum(different_pq) << "]"
1507                                                                    << tcu::TestLog::EndMessage;
1508
1509                                 has_passed = false;
1510                         }
1511
1512                         if (error_code == GL_NO_ERROR)
1513                         {
1514                                 /* Clean up before we continue */
1515                                 gl.endQuery(different_pq);
1516                                 GLU_EXPECT_NO_ERROR(gl.getError(),
1517                                                                         "glEndQuery() should not have failed for a successful glBeginQuery() call");
1518                         }
1519                 } /* for (all query object types) */
1520
1521                 /* We need to switch to a new pipeline statistics query, so
1522                  * delete the query object */
1523                 gl.deleteQueries(1, &m_qo_id);
1524                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries() call failed.");
1525         } /* for (all pipeline statistics query object types) */
1526
1527         if (has_passed)
1528         {
1529                 /* Test case passed */
1530                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1531         }
1532         else
1533         {
1534                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1535         }
1536
1537         return STOP;
1538 }
1539
1540 /** Constructor.
1541  *
1542  *  @param context     Rendering context
1543  *  @param name        Test name
1544  *  @param description Test description
1545  */
1546 PipelineStatisticsQueryTestAPICoverage2::PipelineStatisticsQueryTestAPICoverage2(deqp::Context& context)
1547         : TestCase(context, "api_coverage_unsupported_calls",
1548                            "Verifies that an attempt of using unsupported pipeline statistics queries"
1549                            " results in a GL_INVALID_ENUM error.")
1550         , m_qo_id(0)
1551 {
1552         /* Left blank intentionally */
1553 }
1554
1555 /** Deinitializes all GL objects that were created during test execution. */
1556 void PipelineStatisticsQueryTestAPICoverage2::deinit()
1557 {
1558         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1559
1560         if (m_qo_id != 0)
1561         {
1562                 gl.deleteQueries(1, &m_qo_id);
1563
1564                 m_qo_id = 0;
1565         }
1566 }
1567
1568 /** Executes test iteration.
1569  *
1570  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1571  */
1572 tcu::TestNode::IterateResult PipelineStatisticsQueryTestAPICoverage2::iterate()
1573 {
1574         const glu::ContextInfo& context_info   = m_context.getContextInfo();
1575         glw::GLenum                             error_code       = GL_NO_ERROR;
1576         bool                                    has_passed       = true;
1577         glu::RenderContext&             render_context = m_context.getRenderContext();
1578         const glw::Functions&   gl                         = render_context.getFunctions();
1579         glu::ContextType                contextType     = m_context.getRenderContext().getType();
1580
1581         /* Only continue if GL_ARB_pipeline_statistics_query extension is supported */
1582         if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
1583                 !m_context.getContextInfo().isExtensionSupported("GL_ARB_pipeline_statistics_query"))
1584         {
1585                 throw tcu::NotSupportedError("GL_ARB_pipeline_statistics_query extension is not supported");
1586         }
1587
1588         /* Generate a query object we will use for the tests */
1589         gl.genQueries(1, &m_qo_id);
1590         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries() call failed.");
1591
1592         const glw::GLenum query_types[] = { GL_GEOMETRY_SHADER_INVOCATIONS, GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB,
1593                                                                                 GL_TESS_CONTROL_SHADER_PATCHES_ARB, GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB,
1594                                                                                 GL_COMPUTE_SHADER_INVOCATIONS_ARB };
1595         const unsigned int n_query_types = sizeof(query_types) / sizeof(query_types[0]);
1596
1597         for (unsigned int n_query_type = 0; n_query_type < n_query_types; ++n_query_type)
1598         {
1599                 glw::GLenum query_type = query_types[n_query_type];
1600
1601                 if (!PipelineStatisticsQueryUtilities::isQuerySupported(query_type, context_info, render_context))
1602                 {
1603                         gl.beginQuery(query_type, m_qo_id);
1604
1605                         error_code = gl.getError();
1606                         if (error_code != GL_INVALID_ENUM)
1607                         {
1608                                 m_testCtx.getLog() << tcu::TestLog::Message
1609                                                                    << "glBeginQuery() call did not generate a GL_INVALID_ENUM error "
1610                                                                           "for an unsupported query type "
1611                                                                           "["
1612                                                                    << PipelineStatisticsQueryUtilities::getStringForEnum(query_type) << "]"
1613                                                                    << tcu::TestLog::EndMessage;
1614
1615                                 has_passed = false;
1616                         }
1617
1618                         /* If the query succeeded, stop it before we continue */
1619                         if (error_code == GL_NO_ERROR)
1620                         {
1621                                 gl.endQuery(query_type);
1622
1623                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery() call failed.");
1624                         }
1625                 } /* if (query is not supported) */
1626         }        /* for (all query types) */
1627
1628         if (has_passed)
1629         {
1630                 /* Test case passed */
1631                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1632         }
1633         else
1634         {
1635                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1636         }
1637
1638         return STOP;
1639 }
1640
1641 /** Constructor.
1642  *
1643  *  @param context     Rendering context
1644  *  @param name        Test name
1645  *  @param description Test description
1646  */
1647 PipelineStatisticsQueryTestFunctionalBase::PipelineStatisticsQueryTestFunctionalBase(deqp::Context& context,
1648                                                                                                                                                                          const char*    name,
1649                                                                                                                                                                          const char*    description)
1650         : TestCase(context, name, description)
1651         , m_bo_qo_id(0)
1652         , m_fbo_id(0)
1653         , m_po_id(0)
1654         , m_qo_id(0)
1655         , m_to_id(0)
1656         , m_vao_id(0)
1657         , m_vbo_id(0)
1658         , m_to_height(64)
1659         , m_to_width(64)
1660         , m_current_draw_call_type(PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_COUNT)
1661         , m_current_primitive_type(PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_COUNT)
1662         , m_indirect_draw_call_baseinstance_argument(0)
1663         , m_indirect_draw_call_basevertex_argument(0)
1664         , m_indirect_draw_call_count_argument(0)
1665         , m_indirect_draw_call_first_argument(0)
1666         , m_indirect_draw_call_firstindex_argument(0)
1667         , m_indirect_draw_call_primcount_argument(0)
1668 {
1669         /* Left blank intentionally */
1670 }
1671
1672 /** Creates a program object that can be used for dispatch/draw calls, using
1673  *  user-specified shader bodies. The method can either create a compute program,
1674  *  or a regular rendering program.
1675  *
1676  *  ID of the initialized program object is stored in m_po_id.
1677  *
1678  *  @param cs_body Compute shader body. If not NULL, all other arguments must
1679  *                 be NULL.
1680  *  @param fs_body Fragment shader body. If not NULL, @param cs_body must be NULL.
1681  *  @param gs_body Geometry shader body. If not NULL, @param cs_body must be NULL.
1682  *  @param tc_body Tess control shader body. If not NULL, @param cs_body must be NULL.
1683  *  @param te_body Tess evaluation shader body. If not NULL, @param cs_body must be NULL.
1684  *  @param vs_body Vertex shader body. If not NULL, @param cs_body must be NULL.
1685  *
1686  * */
1687 void PipelineStatisticsQueryTestFunctionalBase::buildProgram(const char* cs_body, const char* fs_body,
1688                                                                                                                          const char* gs_body, const char* tc_body,
1689                                                                                                                          const char* te_body, const char* vs_body)
1690 {
1691         const glw::Functions& gl        = m_context.getRenderContext().getFunctions();
1692         glw::GLuint                       cs_id = 0;
1693         glw::GLuint                       fs_id = 0;
1694         glw::GLuint                       gs_id = 0;
1695         glw::GLuint                       tc_id = 0;
1696         glw::GLuint                       te_id = 0;
1697         glw::GLuint                       vs_id = 0;
1698
1699         /* Sanity checks */
1700         DE_ASSERT((cs_body != DE_NULL && (fs_body == DE_NULL && gs_body == DE_NULL && tc_body == DE_NULL &&
1701                                                                           te_body == DE_NULL && vs_body == DE_NULL)) ||
1702                           (cs_body == DE_NULL && (fs_body != DE_NULL || gs_body != DE_NULL || tc_body != DE_NULL ||
1703                                                                           te_body != DE_NULL || vs_body != DE_NULL)));
1704
1705         /* Any existing program object already initialzied? Purge it before we continue */
1706         if (m_po_id != 0)
1707         {
1708                 gl.deleteProgram(m_po_id);
1709                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram() call failed.");
1710
1711                 m_po_id = 0;
1712         }
1713
1714         /* Generate all shader objects we'll need to use for the program */
1715         if (cs_body != DE_NULL)
1716         {
1717                 cs_id = gl.createShader(GL_COMPUTE_SHADER);
1718         }
1719
1720         if (fs_body != DE_NULL)
1721         {
1722                 fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1723         }
1724
1725         if (gs_body != DE_NULL)
1726         {
1727                 gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1728         }
1729
1730         if (tc_body != DE_NULL)
1731         {
1732                 tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
1733         }
1734
1735         if (te_body != DE_NULL)
1736         {
1737                 te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
1738         }
1739
1740         if (vs_body != DE_NULL)
1741         {
1742                 vs_id = gl.createShader(GL_VERTEX_SHADER);
1743         }
1744
1745         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1746
1747         /* Create a program object */
1748         m_po_id = gl.createProgram();
1749
1750         GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1751
1752         /* Set source code of the shaders we've created */
1753         if (cs_id != 0)
1754         {
1755                 gl.shaderSource(cs_id, 1,                       /* count */
1756                                                 &cs_body, DE_NULL); /* length */
1757         }
1758
1759         if (fs_id != 0)
1760         {
1761                 gl.shaderSource(fs_id, 1,                       /* count */
1762                                                 &fs_body, DE_NULL); /* length */
1763         }
1764
1765         if (gs_id != 0)
1766         {
1767                 gl.shaderSource(gs_id, 1,                       /* count */
1768                                                 &gs_body, DE_NULL); /* length */
1769         }
1770
1771         if (tc_id != 0)
1772         {
1773                 gl.shaderSource(tc_id, 1,                       /* count */
1774                                                 &tc_body, DE_NULL); /* length */
1775         }
1776
1777         if (te_id != 0)
1778         {
1779                 gl.shaderSource(te_id, 1,                       /* count */
1780                                                 &te_body, DE_NULL); /* length */
1781         }
1782
1783         if (vs_id != 0)
1784         {
1785                 gl.shaderSource(vs_id, 1,                       /* count */
1786                                                 &vs_body, DE_NULL); /* length */
1787         }
1788
1789         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
1790
1791         /* Compile the shaders */
1792         const glw::GLuint  so_ids[] = { cs_id, fs_id, gs_id, tc_id, te_id, vs_id };
1793         const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
1794
1795         for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
1796         {
1797                 glw::GLint  compile_status = GL_FALSE;
1798                 glw::GLuint so_id                  = so_ids[n_so_id];
1799
1800                 if (so_id != 0)
1801                 {
1802                         gl.compileShader(so_id);
1803                         GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
1804
1805                         gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
1806                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
1807
1808                         if (compile_status == GL_FALSE)
1809                         {
1810                                 TCU_FAIL("Shader compilation failed.");
1811                         }
1812
1813                         gl.attachShader(m_po_id, so_id);
1814                         GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
1815                 } /* if (so_id != 0) */
1816         }        /* for (all shader objects) */
1817
1818         /* Link the program object */
1819         glw::GLint link_status = GL_FALSE;
1820
1821         gl.linkProgram(m_po_id);
1822         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
1823
1824         gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
1825         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
1826
1827         if (link_status == GL_FALSE)
1828         {
1829                 TCU_FAIL("Program linking failed.");
1830         }
1831
1832         /* Release the shader objects - we no longer need them */
1833         if (cs_id != 0)
1834         {
1835                 gl.deleteShader(cs_id);
1836         }
1837
1838         if (fs_id != 0)
1839         {
1840                 gl.deleteShader(fs_id);
1841         }
1842
1843         if (gs_id != 0)
1844         {
1845                 gl.deleteShader(gs_id);
1846         }
1847
1848         if (tc_id != 0)
1849         {
1850                 gl.deleteShader(tc_id);
1851         }
1852
1853         if (te_id != 0)
1854         {
1855                 gl.deleteShader(te_id);
1856         }
1857
1858         if (vs_id != 0)
1859         {
1860                 gl.deleteShader(vs_id);
1861         }
1862
1863         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call(s) failed.");
1864 }
1865
1866 /** Deinitializes all GL objects that were created during test execution.
1867  *  Also calls the inheriting object's deinitObjects() method.
1868  **/
1869 void PipelineStatisticsQueryTestFunctionalBase::deinit()
1870 {
1871         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1872
1873         if (m_bo_qo_id != 0)
1874         {
1875                 gl.deleteBuffers(1, &m_bo_qo_id);
1876
1877                 m_bo_qo_id = 0;
1878         }
1879
1880         if (m_fbo_id != 0)
1881         {
1882                 gl.deleteFramebuffers(1, &m_fbo_id);
1883
1884                 m_fbo_id = 0;
1885         }
1886
1887         if (m_po_id != 0)
1888         {
1889                 gl.deleteProgram(m_po_id);
1890
1891                 m_po_id = 0;
1892         }
1893
1894         if (m_qo_id != 0)
1895         {
1896                 gl.deleteQueries(1, &m_qo_id);
1897
1898                 m_qo_id = 0;
1899         }
1900
1901         if (m_to_id != 0)
1902         {
1903                 gl.deleteTextures(1, &m_to_id);
1904
1905                 m_to_id = 0;
1906         }
1907
1908         if (m_vao_id != 0)
1909         {
1910                 gl.deleteVertexArrays(1, &m_vao_id);
1911
1912                 m_vao_id = 0;
1913         }
1914
1915         if (m_vbo_id != 0)
1916         {
1917                 gl.deleteBuffers(1, &m_vbo_id);
1918
1919                 m_vbo_id = 0;
1920         }
1921
1922         deinitObjects();
1923 }
1924
1925 /** Dummy method that should be overloaded by inheriting methods.
1926  *
1927  *  The method can be thought as of a placeholder for code that deinitializes
1928  *  test-specific GL objects.
1929  **/
1930 void PipelineStatisticsQueryTestFunctionalBase::deinitObjects()
1931 {
1932         /* Left blank intentionally - this method should be overloaded by deriving
1933          * classes.
1934          */
1935 }
1936
1937 /** Initializes a framebuffer object that can be used by inheriting tests
1938  *  for holding rendered data.
1939  **/
1940 void PipelineStatisticsQueryTestFunctionalBase::initFBO()
1941 {
1942         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1943
1944         /* Set up a framebuffer object */
1945         gl.genFramebuffers(1, &m_fbo_id);
1946         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
1947
1948         gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
1949         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
1950
1951         /* Set up a texture object we will later use as a color attachment for the FBO */
1952         gl.genTextures(1, &m_to_id);
1953         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
1954
1955         gl.bindTexture(GL_TEXTURE_2D, m_to_id);
1956         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
1957
1958         gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
1959                                         GL_RGBA8, m_to_width, m_to_height);
1960         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
1961
1962         /* Set up the TO as a color attachment */
1963         gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0); /* level */
1964         GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
1965
1966         gl.viewport(0, 0, m_to_width, m_to_height);
1967         GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
1968 }
1969
1970 /** A dummy method, which can be thought of as a placeholder to initialize
1971  *  test-specific GL objects.
1972  **/
1973 void PipelineStatisticsQueryTestFunctionalBase::initObjects()
1974 {
1975         /* Left blank intentionally - this method should be overloaded by deriving
1976          * classes.
1977          */
1978 }
1979
1980 /** Initializes a vertex array object which is going to be used for the draw calls.
1981  *  The initialized VAO's ID is going to be stored under m_vao_id. Zeroth vertex
1982  *  array attribute will be configured to use @param n_components_per_vertex components
1983  *  and will use vertex buffer object defined by ID stored in m_vbo_id, whose data
1984  *  are expected to start at an offset defined by m_vbo_vertex_data_offset.
1985  *
1986  *  @param n_components_per_vertex As per description.
1987  */
1988 void PipelineStatisticsQueryTestFunctionalBase::initVAO(unsigned int n_components_per_vertex)
1989 {
1990         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1991
1992         /* Release an VAO that's already been created */
1993         if (m_vao_id != 0)
1994         {
1995                 gl.deleteVertexArrays(1, &m_vao_id);
1996
1997                 m_vao_id = 0;
1998         }
1999
2000         /* Generate a new one */
2001         gl.genVertexArrays(1, &m_vao_id);
2002         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2003
2004         gl.bindVertexArray(m_vao_id);
2005         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2006
2007         /* Set it up */
2008         gl.vertexAttribPointer(0,                                                                                       /* index */
2009                                                    n_components_per_vertex, GL_FLOAT, GL_FALSE, /* normalized */
2010                                                    0,                                                                                   /* stride */
2011                                                    (glw::GLvoid*)(deUintptr)m_vbo_vertex_data_offset);
2012         GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
2013
2014         gl.enableVertexAttribArray(0); /* index */
2015         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
2016
2017         gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo_id);
2018         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2019 }
2020
2021 /** Initializes a vertex buffer object and stores its ID under m_vbo_id.
2022  *  It is assumed index data is expressed in GL_UNSIGNED_INT.
2023  *
2024  *  The following fields will be modified by the method:
2025  *
2026  *  m_vbo_n_indices:                          Will hold the number of indices stored in index
2027  *                                            data buffer.
2028  *  m_vbo_vertex_data_offset:                 Will hold the offset, from which the vertex
2029  *                                            data will be stored in VBO.
2030  *  m_vbo_index_data_offset:                  Will hold the offset, from which the index
2031  *                                            data will be stored in VBO.
2032  *  m_vbo_indirect_arrays_argument_offset:    Will hold the offset, from which
2033  *                                            glDrawArraysIndirect() arguments will be
2034  *                                            stored in VBO.
2035  *  m_vbo_indirect_elements_argument_offset:  Will hold the offset, from which
2036  *                                            glDrawElementsIndirect() arguments will be
2037  *                                            stored in VBO.
2038  *  m_indirect_draw_call_firstindex_argument: Will be updated to point to the location, from
2039  *                                            which index data starts.
2040  *
2041  *  @param raw_vertex_data                        Pointer to a buffer that holds vertex data
2042  *                                                which should be used when constructing the VBO.
2043  *                                                Must not be NULL.
2044  *  @param raw_vertex_data_size                   Number of bytes available for reading under
2045  *                                                @param raw_vertex_data.
2046  *  @param raw_index_data                         Pointer to a buffer that holds index data
2047  *                                                which should be used when constructing the VBO.
2048  *                                                Must not be NULL.
2049  *  @param raw_index_data_size                    Number of bytes available for reading under
2050  *                                                @param raw_index_data .
2051  *  @param indirect_draw_bo_count_argument        Argument to be used for indirect draw calls'
2052  *                                                "count" argument.
2053  *  @param indirect_draw_bo_primcount_argument    Argument to be used for indirect draw calls'
2054  *                                                "primcount" argument.
2055  *  @param indirect_draw_bo_baseinstance_argument Argument to be used for indirect draw calls'
2056  *                                                "baseinstance" argument.
2057  *  @param indirect_draw_bo_first_argument        Argument to be used for indirect draw calls'
2058  *                                                "first" argument.
2059  *  @param indirect_draw_bo_basevertex_argument   Argument to be used for indirect draw calls'
2060  *                                                "basevertex" argument.
2061  *
2062  **/
2063 void PipelineStatisticsQueryTestFunctionalBase::initVBO(
2064         const float* raw_vertex_data, unsigned int raw_vertex_data_size, const unsigned int* raw_index_data,
2065         unsigned int raw_index_data_size, unsigned int indirect_draw_bo_count_argument,
2066         unsigned int indirect_draw_bo_primcount_argument, unsigned int indirect_draw_bo_baseinstance_argument,
2067         unsigned int indirect_draw_bo_first_argument, unsigned int indirect_draw_bo_basevertex_argument)
2068 {
2069         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2070
2071         /* If we already have initialized a VBO, delete it before we continue */
2072         if (m_vbo_id != 0)
2073         {
2074                 gl.deleteBuffers(1, &m_vbo_id);
2075
2076                 m_vbo_id = 0;
2077         }
2078
2079         /* Our BO storage is formed as below:
2080          *
2081          * [raw vertex data]
2082          * [raw index data]
2083          * [indirect glDrawArrays() call arguments]
2084          * [indirect glDrawElements() call arguments]
2085          *
2086          * We store the relevant offsets in member fields, so that they can be used by actual test
2087          * implementation.
2088          */
2089         const unsigned int indirect_arrays_draw_call_arguments_size   = sizeof(unsigned int) * 4; /* as per spec */
2090         const unsigned int indirect_elements_draw_call_arguments_size = sizeof(unsigned int) * 5; /* as per spec */
2091
2092         m_vbo_n_indices                                           = raw_index_data_size / sizeof(unsigned int);
2093         m_vbo_vertex_data_offset                          = 0;
2094         m_vbo_index_data_offset                           = raw_vertex_data_size;
2095         m_vbo_indirect_arrays_argument_offset = m_vbo_index_data_offset + raw_index_data_size;
2096         m_vbo_indirect_elements_argument_offset =
2097                 m_vbo_indirect_arrays_argument_offset + indirect_arrays_draw_call_arguments_size;
2098
2099         /* Set up 'firstindex' argument so that it points at correct index data location */
2100         DE_ASSERT((m_vbo_index_data_offset % sizeof(unsigned int)) == 0);
2101
2102         m_indirect_draw_call_firstindex_argument =
2103                 static_cast<unsigned int>(m_vbo_index_data_offset / sizeof(unsigned int));
2104
2105         /* Form indirect draw call argument buffers */
2106         unsigned int arrays_draw_call_arguments[] = { indirect_draw_bo_count_argument, indirect_draw_bo_primcount_argument,
2107                                                                                                   indirect_draw_bo_first_argument,
2108                                                                                                   indirect_draw_bo_baseinstance_argument };
2109         unsigned int elements_draw_call_arguments[] = {
2110                 indirect_draw_bo_count_argument, indirect_draw_bo_primcount_argument, m_indirect_draw_call_firstindex_argument,
2111                 indirect_draw_bo_basevertex_argument, indirect_draw_bo_baseinstance_argument
2112         };
2113
2114         /* Set up BO storage */
2115         const unsigned int bo_data_size =
2116                 m_vbo_indirect_elements_argument_offset + indirect_elements_draw_call_arguments_size;
2117
2118         gl.genBuffers(1, &m_vbo_id);
2119         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2120
2121         gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_id);
2122         gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_vbo_id);
2123         gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo_id);
2124         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
2125
2126         gl.bufferData(GL_ARRAY_BUFFER, bo_data_size, DE_NULL, /* data */
2127                                   GL_STATIC_DRAW);
2128         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2129
2130         gl.bufferSubData(GL_ARRAY_BUFFER, m_vbo_vertex_data_offset, raw_vertex_data_size, raw_vertex_data);
2131         gl.bufferSubData(GL_ARRAY_BUFFER, m_vbo_index_data_offset, raw_index_data_size, raw_index_data);
2132         gl.bufferSubData(GL_ARRAY_BUFFER, m_vbo_indirect_arrays_argument_offset, sizeof(arrays_draw_call_arguments),
2133                                          arrays_draw_call_arguments);
2134         gl.bufferSubData(GL_ARRAY_BUFFER, m_vbo_indirect_elements_argument_offset, sizeof(elements_draw_call_arguments),
2135                                          elements_draw_call_arguments);
2136         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
2137 }
2138
2139 /** Performs the actual test.
2140  *
2141  *  @return Always STOP.
2142  **/
2143 tcu::TestNode::IterateResult PipelineStatisticsQueryTestFunctionalBase::iterate()
2144 {
2145         bool has_passed = true;
2146         glu::ContextType contextType = m_context.getRenderContext().getType();
2147
2148         /* Carry on only if GL_ARB_pipeline_statistics_query extension is supported */
2149         if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
2150                 !m_context.getContextInfo().isExtensionSupported("GL_ARB_pipeline_statistics_query"))
2151         {
2152                 throw tcu::NotSupportedError("GL_ARB_pipeline_statistics_query extension is not supported");
2153         }
2154
2155         /* Initialize QO BO storage if GL_ARB_query_buffer_object is supported */
2156         if (m_context.getContextInfo().isExtensionSupported("GL_ARB_query_buffer_object"))
2157         {
2158                 initQOBO();
2159
2160                 DE_ASSERT(m_bo_qo_id != 0);
2161         }
2162
2163         /* Initialize other test-specific objects */
2164         initObjects();
2165
2166         /* Iterate through all pipeline statistics query object types */
2167         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2168
2169         for (unsigned int n_query_target = 0; n_query_target < PipelineStatisticsQueryUtilities::n_query_targets;
2170                  ++n_query_target)
2171         {
2172                 glw::GLenum current_query_target = PipelineStatisticsQueryUtilities::query_targets[n_query_target];
2173
2174                 if (shouldExecuteForQueryTarget(current_query_target))
2175                 {
2176                         /* Initialize the query object */
2177                         gl.genQueries(1, &m_qo_id);
2178                         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries() call failed.");
2179
2180                         /* Execute the test for the particular query target. */
2181                         has_passed &= executeTest(current_query_target);
2182
2183                         /* Delete the query object */
2184                         gl.deleteQueries(1, &m_qo_id);
2185                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries() call failed.");
2186
2187                         m_qo_id = 0;
2188                 }
2189         } /* for (all query targets) */
2190
2191         if (has_passed)
2192         {
2193                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2194         }
2195         else
2196         {
2197                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2198         }
2199
2200         return STOP;
2201 }
2202
2203 /** Initializes a query buffer object. */
2204 void PipelineStatisticsQueryTestFunctionalBase::initQOBO()
2205 {
2206         const glw::Functions gl = m_context.getRenderContext().getFunctions();
2207
2208         /* Set up the buffer object we will use for storage of query object results */
2209         unsigned char bo_data[PipelineStatisticsQueryUtilities::qo_bo_size];
2210
2211         memset(bo_data, 0xFF, sizeof(bo_data));
2212
2213         gl.genBuffers(1, &m_bo_qo_id);
2214         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2215
2216         gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_qo_id);
2217         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2218
2219         gl.bufferData(GL_ARRAY_BUFFER, PipelineStatisticsQueryUtilities::qo_bo_size, bo_data, GL_STATIC_DRAW);
2220         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2221 }
2222
2223 /** Executes a draw call, whose type is specified under pThis->m_current_draw_call_type.
2224  *
2225  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctionalBase instance, which
2226  *               should be used to extract the draw call type.
2227  *
2228  *  @return Always true.
2229  **/
2230 bool PipelineStatisticsQueryTestFunctionalBase::queryCallbackDrawCallHandler(void* pThis)
2231 {
2232         PipelineStatisticsQueryTestFunctionalBase* pInstance = (PipelineStatisticsQueryTestFunctionalBase*)pThis;
2233         const glw::Functions&                                      gl            = pInstance->m_context.getRenderContext().getFunctions();
2234
2235         /* Issue the draw call */
2236         glw::GLenum primitive_type =
2237                 PipelineStatisticsQueryUtilities::getEnumForPrimitiveType(pInstance->m_current_primitive_type);
2238
2239         switch (pInstance->m_current_draw_call_type)
2240         {
2241         case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWARRAYS:
2242         {
2243                 gl.drawArrays(primitive_type, pInstance->m_indirect_draw_call_first_argument,
2244                                           pInstance->m_indirect_draw_call_count_argument);
2245
2246                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
2247
2248                 break;
2249         }
2250
2251         case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWARRAYSINDIRECT:
2252         {
2253                 gl.drawArraysIndirect(primitive_type,
2254                                                           (const glw::GLvoid*)(deUintptr)pInstance->m_vbo_indirect_arrays_argument_offset);
2255
2256                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArraysIndirect() call failed.");
2257
2258                 break;
2259         }
2260
2261         case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCED:
2262         {
2263                 gl.drawArraysInstanced(primitive_type, pInstance->m_indirect_draw_call_first_argument,
2264                                                            pInstance->m_indirect_draw_call_count_argument,
2265                                                            pInstance->m_indirect_draw_call_primcount_argument);
2266
2267                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArraysInstanced() call failed.");
2268
2269                 break;
2270         }
2271
2272         case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCEDBASEINSTANCE:
2273         {
2274                 gl.drawArraysInstancedBaseInstance(primitive_type, pInstance->m_indirect_draw_call_first_argument,
2275                                                                                    pInstance->m_indirect_draw_call_count_argument,
2276                                                                                    pInstance->m_indirect_draw_call_primcount_argument,
2277                                                                                    pInstance->m_indirect_draw_call_baseinstance_argument);
2278
2279                 break;
2280         }
2281
2282         case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTS:
2283         {
2284                 gl.drawElements(primitive_type, pInstance->m_indirect_draw_call_count_argument, GL_UNSIGNED_INT,
2285                                                 (glw::GLvoid*)(deUintptr)pInstance->m_vbo_index_data_offset);
2286
2287                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements() call failed.");
2288
2289                 break;
2290         }
2291
2292         case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSBASEVERTEX:
2293         {
2294                 gl.drawElementsBaseVertex(primitive_type, pInstance->m_indirect_draw_call_count_argument, GL_UNSIGNED_INT,
2295                                                                   (glw::GLvoid*)(deUintptr)pInstance->m_vbo_index_data_offset,
2296                                                                   pInstance->m_indirect_draw_call_basevertex_argument);
2297
2298                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsBaseVertex() call failed.");
2299
2300                 break;
2301         }
2302
2303         case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSINDIRECT:
2304         {
2305                 gl.drawElementsIndirect(primitive_type, GL_UNSIGNED_INT,
2306                                                                 (glw::GLvoid*)(deUintptr)pInstance->m_vbo_indirect_elements_argument_offset);
2307
2308                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsIndirect() call failed.");
2309
2310                 break;
2311         }
2312
2313         case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCED:
2314         {
2315                 gl.drawElementsInstanced(primitive_type, pInstance->m_indirect_draw_call_count_argument, GL_UNSIGNED_INT,
2316                                                                  (glw::GLvoid*)(deUintptr)pInstance->m_vbo_index_data_offset,
2317                                                                  pInstance->m_indirect_draw_call_primcount_argument);
2318
2319                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsInstanced() call failed.");
2320
2321                 break;
2322         }
2323
2324         case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEINSTANCE:
2325         {
2326                 gl.drawElementsInstancedBaseInstance(
2327                         primitive_type, pInstance->m_indirect_draw_call_count_argument, GL_UNSIGNED_INT,
2328                         (glw::GLvoid*)(deUintptr)pInstance->m_vbo_index_data_offset,
2329                         pInstance->m_indirect_draw_call_primcount_argument, pInstance->m_indirect_draw_call_baseinstance_argument);
2330
2331                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsInstancedBaseInstance() call failed.");
2332
2333                 break;
2334         }
2335
2336         case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE:
2337         {
2338                 gl.drawElementsInstancedBaseVertexBaseInstance(
2339                         primitive_type, pInstance->m_indirect_draw_call_count_argument, GL_UNSIGNED_INT,
2340                         (glw::GLvoid*)(deUintptr)pInstance->m_vbo_index_data_offset,
2341                         pInstance->m_indirect_draw_call_primcount_argument, pInstance->m_indirect_draw_call_basevertex_argument,
2342                         pInstance->m_indirect_draw_call_baseinstance_argument);
2343
2344                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsInstancedBaseVertexBaseInstance() call failed.");
2345
2346                 break;
2347         }
2348
2349         case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWRANGEELEMENTS:
2350         {
2351                 gl.drawRangeElements(primitive_type, 0, /* start */
2352                                                          pInstance->m_vbo_n_indices, pInstance->m_indirect_draw_call_count_argument,
2353                                                          GL_UNSIGNED_INT, (glw::GLvoid*)(deUintptr)pInstance->m_vbo_index_data_offset);
2354
2355                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawRangeElements() call failed.");
2356
2357                 break;
2358         }
2359
2360         case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWRANGEELEMENTSBASEVERTEX:
2361         {
2362                 gl.drawRangeElementsBaseVertex(primitive_type, 0,                                                                  /* start */
2363                                                                            pInstance->m_indirect_draw_call_count_argument - 1, /* end */
2364                                                                            pInstance->m_indirect_draw_call_count_argument, GL_UNSIGNED_INT,
2365                                                                            (glw::GLvoid*)(deUintptr)pInstance->m_vbo_index_data_offset,
2366                                                                            pInstance->m_indirect_draw_call_basevertex_argument);
2367
2368                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawRangeElementsBaseVertex() call failed.");
2369
2370                 break;
2371         }
2372
2373         default:
2374         {
2375                 TCU_FAIL("Unrecognized draw call type");
2376         }
2377         } /* switch (m_current_draw_call_type) */
2378
2379         return true;
2380 }
2381
2382 /** Tells whether the test instance should be executed for user-specified query target.
2383  *  Base class implementation returns true for all values of @param query_target.
2384  *
2385  *  @param query_target Query target to be used for the call.
2386  *
2387  *  @return Always true.
2388  **/
2389 bool PipelineStatisticsQueryTestFunctionalBase::shouldExecuteForQueryTarget(glw::GLenum query_target)
2390 {
2391         (void)query_target;
2392         return true;
2393 }
2394
2395 /** Constructor.
2396  *
2397  *  @param context Rendering context.
2398  **/
2399 PipelineStatisticsQueryTestFunctional1::PipelineStatisticsQueryTestFunctional1(deqp::Context& context)
2400         : PipelineStatisticsQueryTestFunctionalBase(context, "functional_default_qo_values",
2401                                                                                                 "Verifies that all pipeline statistics query objects "
2402                                                                                                 "use a default value of 0.")
2403 {
2404         /* Left blank intentionally */
2405 }
2406
2407 /** Executes a test iteration for user-specified query target.
2408  *
2409  *  @param current_query_target Pipeline statistics query target to execute the iteration
2410  *                              for.
2411  *
2412  *  @return true if the test passed for the iteration, false otherwise.
2413  **/
2414 bool PipelineStatisticsQueryTestFunctional1::executeTest(glw::GLenum current_query_target)
2415 {
2416         bool                                                                                                     result = true;
2417         PipelineStatisticsQueryUtilities::_test_execution_result run_result;
2418
2419         if (!PipelineStatisticsQueryUtilities::executeQuery(
2420                         current_query_target, m_qo_id, m_bo_qo_id, DE_NULL, /* pfn_draw */
2421                         DE_NULL,                                                                                        /* draw_user_arg */
2422                         m_context.getRenderContext(), m_testCtx, m_context.getContextInfo(), &run_result))
2423         {
2424                 m_testCtx.getLog() << tcu::TestLog::Message << "Could not retrieve test run results for query target "
2425                                                                                                            "["
2426                                                    << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target) << "]"
2427                                                    << tcu::TestLog::EndMessage;
2428
2429                 result = false;
2430         }
2431         else
2432         {
2433                 const glw::GLuint64 expected_value = 0;
2434
2435                 result &= PipelineStatisticsQueryUtilities::verifyResultValues(
2436                         run_result, 1, &expected_value, m_qo_id != 0, /* should_check_qo_bo_values */
2437                         current_query_target, DE_NULL, DE_NULL,
2438                         false, /* is_primitive_restart_enabled */
2439                         m_testCtx, PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_EXACT_MATCH);
2440         } /* if (run results were obtained successfully) */
2441
2442         return result;
2443 }
2444
2445 /** Constructor.
2446  *
2447  *  @param context Rendering context
2448  */
2449 PipelineStatisticsQueryTestFunctional2::PipelineStatisticsQueryTestFunctional2(deqp::Context& context)
2450         : PipelineStatisticsQueryTestFunctionalBase(context, "functional_non_rendering_commands_do_not_affect_queries",
2451                                                                                                 "Verifies that non-rendering commands do not affect query"
2452                                                                                                 " values.")
2453         , m_bo_id(0)
2454         , m_fbo_draw_id(0)
2455         , m_fbo_read_id(0)
2456         , m_to_draw_fbo_id(0)
2457         , m_to_read_fbo_id(0)
2458         , m_to_height(16)
2459         , m_to_width(16)
2460 {
2461         /* Left blank intentionally */
2462 }
2463
2464 /** Deinitializes all GL objects that were created during test execution. */
2465 void PipelineStatisticsQueryTestFunctional2::deinitObjects()
2466 {
2467         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2468
2469         if (m_bo_id != 0)
2470         {
2471                 gl.deleteBuffers(1, &m_bo_id);
2472
2473                 m_bo_id = 0;
2474         }
2475
2476         if (m_fbo_draw_id != 0)
2477         {
2478                 gl.deleteFramebuffers(1, &m_fbo_draw_id);
2479
2480                 m_fbo_draw_id = 0;
2481         }
2482
2483         if (m_fbo_read_id != 0)
2484         {
2485                 gl.deleteFramebuffers(1, &m_fbo_read_id);
2486
2487                 m_fbo_read_id = 0;
2488         }
2489
2490         if (m_to_draw_fbo_id != 0)
2491         {
2492                 gl.deleteTextures(1, &m_to_draw_fbo_id);
2493
2494                 m_to_draw_fbo_id = 0;
2495         }
2496
2497         if (m_to_read_fbo_id != 0)
2498         {
2499                 gl.deleteTextures(1, &m_to_read_fbo_id);
2500
2501                 m_to_read_fbo_id = 0;
2502         }
2503 }
2504
2505 /** Callback handler which calls glBlitFramebuffer() API function and makes sure it
2506  *  was executed successfully.
2507  *
2508  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2509  *               be NULL.
2510  *
2511  *  @return Always true.
2512  **/
2513 bool PipelineStatisticsQueryTestFunctional2::executeBlitFramebufferTest(void* pThis)
2514 {
2515         PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2516         const glw::Functions&                                   gl               = data_ptr->m_context.getRenderContext().getFunctions();
2517
2518         /* Framebuffer objects are bound to their FB targets at this point */
2519         gl.blitFramebuffer(0,                                              /* srcX0 */
2520                                            0,                                              /* srcY0 */
2521                                            data_ptr->m_to_width,           /* srcX1 */
2522                                            data_ptr->m_to_height,         /* srcY1 */
2523                                            0,                                              /* dstX0 */
2524                                            0,                                              /* dstY0 */
2525                                            data_ptr->m_to_width << 1,  /* dstX1 */
2526                                            data_ptr->m_to_height << 1, /* dstY1 */
2527                                            GL_COLOR_BUFFER_BIT,            /* mask */
2528                                            GL_LINEAR);                             /* filter */
2529
2530         GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() call failed.");
2531
2532         return true;
2533 }
2534
2535 /** Callback handler which calls glBufferSubData() API function and makes sure it
2536  *  was executed successfully.
2537  *
2538  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2539  *               be NULL.
2540  *
2541  *  @return Always true.
2542  **/
2543 bool PipelineStatisticsQueryTestFunctional2::executeBufferSubDataTest(void* pThis)
2544 {
2545         PipelineStatisticsQueryTestFunctional2* data_ptr           = (PipelineStatisticsQueryTestFunctional2*)pThis;
2546         const glw::Functions&                                   gl                         = data_ptr->m_context.getRenderContext().getFunctions();
2547         const unsigned int                                              test_data_size = (PipelineStatisticsQueryTestFunctional2::bo_size / 2);
2548         unsigned char                                                   test_bo_data[test_data_size];
2549
2550         memset(test_bo_data, 0xFF, test_data_size);
2551
2552         gl.bindBuffer(GL_ARRAY_BUFFER, data_ptr->m_bo_id);
2553         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2554
2555         gl.bufferSubData(GL_ARRAY_BUFFER, 0, /* offset */
2556                                          test_data_size, test_bo_data);
2557         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
2558
2559         return true;
2560 }
2561
2562 /** Callback handler which calls glClearBufferfv() API function and makes sure it
2563  *  was executed successfully.
2564  *
2565  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2566  *               be NULL.
2567  *
2568  *  @return Always true.
2569  **/
2570 bool PipelineStatisticsQueryTestFunctional2::executeClearBufferfvColorBufferTest(void* pThis)
2571 {
2572         const glw::GLfloat                                              clear_color[4] = { 0, 0.1f, 0.2f, 0.3f };
2573         PipelineStatisticsQueryTestFunctional2* data_ptr           = (PipelineStatisticsQueryTestFunctional2*)pThis;
2574         const glw::Functions&                                   gl                         = data_ptr->m_context.getRenderContext().getFunctions();
2575
2576         gl.clearBufferfv(GL_COLOR, 0, /* drawbuffer */
2577                                          clear_color);
2578         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferfv() call failed.");
2579
2580         return true;
2581 }
2582
2583 /** Callback handler which calls glClearBufferfv() API function and makes sure it
2584  *  was executed successfully.
2585  *
2586  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2587  *               be NULL.
2588  *
2589  *  @return Always true.
2590  **/
2591 bool PipelineStatisticsQueryTestFunctional2::executeClearBufferfvDepthBufferTest(void* pThis)
2592 {
2593         const glw::GLfloat                                              clear_depth = 0.1f;
2594         PipelineStatisticsQueryTestFunctional2* data_ptr        = (PipelineStatisticsQueryTestFunctional2*)pThis;
2595         const glw::Functions&                                   gl                      = data_ptr->m_context.getRenderContext().getFunctions();
2596
2597         gl.clearBufferfv(GL_DEPTH, 0, /* drawbuffer */
2598                                          &clear_depth);
2599         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferfv() call failed.");
2600
2601         return true;
2602 }
2603
2604 /** Callback handler which calls glClearBufferiv() API function and makes sure it
2605  *  was executed successfully.
2606  *
2607  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2608  *               be NULL.
2609  *
2610  *  @return Always true.
2611  **/
2612 bool PipelineStatisticsQueryTestFunctional2::executeClearBufferivStencilBufferTest(void* pThis)
2613 {
2614         const glw::GLint                                                clear_stencil = 123;
2615         PipelineStatisticsQueryTestFunctional2* data_ptr          = (PipelineStatisticsQueryTestFunctional2*)pThis;
2616         const glw::Functions&                                   gl                        = data_ptr->m_context.getRenderContext().getFunctions();
2617
2618         gl.clearBufferiv(GL_STENCIL, 0, /* drawbuffer */
2619                                          &clear_stencil);
2620         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferfv() call failed.");
2621
2622         return true;
2623 }
2624
2625 /** Callback handler which calls glClearBufferSubData() API function and makes sure it
2626  *  was executed successfully.
2627  *
2628  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2629  *               be NULL.
2630  *
2631  *  @return true if glClearBufferSubData() is available, false otherwise.
2632  **/
2633 bool PipelineStatisticsQueryTestFunctional2::executeClearBufferSubDataTest(void* pThis)
2634 {
2635         PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2636         const glw::Functions&                                   gl               = data_ptr->m_context.getRenderContext().getFunctions();
2637         bool                                                                    result   = true;
2638
2639         if (!glu::contextSupports(data_ptr->m_context.getRenderContext().getType(), glu::ApiType::core(4, 3)) &&
2640                 gl.clearBufferSubData == NULL)
2641         {
2642                 /* API is unavailable */
2643                 return false;
2644         }
2645
2646         /* Execute the API call */
2647         const unsigned char value = 0xFF;
2648
2649         gl.clearBufferSubData(GL_ARRAY_BUFFER, GL_R8, 0, /* offset */
2650                                                   data_ptr->bo_size, GL_RED, GL_UNSIGNED_BYTE, &value);
2651         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferSubData() call failed.");
2652
2653         /* All done */
2654         return result;
2655 }
2656
2657 /** Callback handler which calls glClear() API function configured to clear color
2658  *  buffer and makes sure it was executed successfully.
2659  *
2660  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2661  *               be NULL.
2662  *
2663  *  @return Always true.
2664  **/
2665 bool PipelineStatisticsQueryTestFunctional2::executeClearColorBufferTest(void* pThis)
2666 {
2667         PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2668         const glw::Functions&                                   gl               = data_ptr->m_context.getRenderContext().getFunctions();
2669
2670         gl.clear(GL_COLOR_BUFFER_BIT);
2671         GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
2672
2673         return true;
2674 }
2675
2676 /** Callback handler which calls glClear() API function configured to clear depth
2677  *  buffer and makes sure it was executed successfully.
2678  *
2679  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2680  *               be NULL.
2681  *
2682  *  @return Always true.
2683  **/
2684 bool PipelineStatisticsQueryTestFunctional2::executeClearDepthBufferTest(void* pThis)
2685 {
2686         PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2687         const glw::Functions&                                   gl               = data_ptr->m_context.getRenderContext().getFunctions();
2688
2689         gl.clear(GL_DEPTH_BUFFER_BIT);
2690         GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
2691
2692         return true;
2693 }
2694
2695 /** Callback handler which calls glClear() API function configured to clear stencil
2696  *  buffer and makes sure it was executed successfully.
2697  *
2698  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2699  *               be NULL.
2700  *
2701  *  @return Always true.
2702  **/
2703 bool PipelineStatisticsQueryTestFunctional2::executeClearStencilBufferTest(void* pThis)
2704 {
2705         PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2706         const glw::Functions&                                   gl               = data_ptr->m_context.getRenderContext().getFunctions();
2707
2708         gl.clear(GL_STENCIL_BUFFER_BIT);
2709         GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
2710
2711         return true;
2712 }
2713
2714 /** Callback handler which calls glClearTexSubImage() API function (if available).
2715  *
2716  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2717  *               be NULL.
2718  *
2719  *  @return true if the function is supported by the running GL implementation, false
2720  *               otherwise.
2721  **/
2722 bool PipelineStatisticsQueryTestFunctional2::executeClearTexSubImageTest(void* pThis)
2723 {
2724         PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2725         const glw::Functions&                                   gl               = data_ptr->m_context.getRenderContext().getFunctions();
2726         bool                                                                    result   = true;
2727
2728         if (!glu::contextSupports(data_ptr->m_context.getRenderContext().getType(), glu::ApiType::core(4, 4)) &&
2729                 gl.clearTexSubImage == NULL)
2730         {
2731                 /* API is unavailable */
2732                 return false;
2733         }
2734
2735         /* Execute the API call */
2736         const unsigned char test_value = 0xFF;
2737
2738         gl.clearTexSubImage(data_ptr->m_to_draw_fbo_id, 0,                                                      /* level */
2739                                                 0,                                                                                                              /* xoffset */
2740                                                 0,                                                                                                              /* yoffset */
2741                                                 0,                                                                                                              /* zoffset */
2742                                                 data_ptr->m_to_width / 2, data_ptr->m_to_height / 2, 1, /* depth */
2743                                                 GL_RED, GL_UNSIGNED_BYTE, &test_value);
2744         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearTexSubImage() call failed.");
2745
2746         /* All done */
2747         return result;
2748 }
2749
2750 /** Callback handler which calls glCopyImageSubData() API function (if available).
2751  *
2752  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2753  *               be NULL.
2754  *
2755  *  @return true if the function is supported by the running GL implementation, false
2756  *               otherwise.
2757  **/
2758 bool PipelineStatisticsQueryTestFunctional2::executeCopyImageSubDataTest(void* pThis)
2759 {
2760         PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2761         const glw::Functions&                                   gl               = data_ptr->m_context.getRenderContext().getFunctions();
2762         bool                                                                    result   = true;
2763
2764         if (!glu::contextSupports(data_ptr->m_context.getRenderContext().getType(), glu::ApiType::core(4, 3)) &&
2765                 gl.copyImageSubData == NULL)
2766         {
2767                 /* API is unavailable */
2768                 return false;
2769         }
2770
2771         /* Execute the API call */
2772         gl.copyImageSubData(data_ptr->m_to_draw_fbo_id, GL_TEXTURE_2D, 0,                        /* srcLevel */
2773                                                 0,                                                                                                               /* srcX */
2774                                                 0,                                                                                                               /* srcY */
2775                                                 0,                                                                                                               /* srcZ */
2776                                                 data_ptr->m_to_read_fbo_id, GL_TEXTURE_2D, 0,                    /* dstLevel */
2777                                                 0,                                                                                                               /* dstX */
2778                                                 0,                                                                                                               /* dstY */
2779                                                 0,                                                                                                               /* dstZ */
2780                                                 data_ptr->m_to_width / 2, data_ptr->m_to_height / 2, 1); /* src_depth */
2781         GLU_EXPECT_NO_ERROR(gl.getError(), "glCopyImageSubData() call failed.");
2782
2783         /* All done */
2784         return result;
2785 }
2786
2787 /** Callback handler which calls glTexSubImage2D().
2788  *
2789  *  @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2790  *               be NULL.
2791  *
2792  *  @return true Always true.
2793  **/
2794 bool PipelineStatisticsQueryTestFunctional2::executeTexSubImageTest(void* pThis)
2795 {
2796         PipelineStatisticsQueryTestFunctional2* data_ptr           = (PipelineStatisticsQueryTestFunctional2*)pThis;
2797         const glw::Functions&                                   gl                         = data_ptr->m_context.getRenderContext().getFunctions();
2798         const unsigned int                                              test_data_size = PipelineStatisticsQueryTestFunctional2::bo_size / 2;
2799         unsigned char                                                   test_data[test_data_size];
2800
2801         memset(test_data, 0xFF, test_data_size);
2802
2803         gl.texSubImage2D(GL_TEXTURE_2D, 0, /* level */
2804                                          0,                                /* xoffset */
2805                                          0,                                /* yoffset */
2806                                          data_ptr->m_to_width / 2, data_ptr->m_to_height / 2, GL_RED, GL_UNSIGNED_BYTE, test_data);
2807         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
2808
2809         return true;
2810 }
2811
2812 /** Executes a test iteration for user-specified query target.
2813  *
2814  *  @param current_query_target Pipeline statistics query target to execute the iteration
2815  *                              for.
2816  *
2817  *  @return true if the test passed for the iteration, false otherwise.
2818  **/
2819 bool PipelineStatisticsQueryTestFunctional2::executeTest(glw::GLenum current_query_target)
2820 {
2821         bool                                                                                                                    result = true;
2822         PipelineStatisticsQueryUtilities::_test_execution_result                run_result;
2823         const PipelineStatisticsQueryUtilities::PFNQUERYDRAWHANDLERPROC query_draw_handlers[] = {
2824                 executeBlitFramebufferTest,
2825                 executeBufferSubDataTest,
2826                 executeClearBufferfvColorBufferTest,
2827                 executeClearBufferfvDepthBufferTest,
2828                 executeClearBufferivStencilBufferTest,
2829                 executeClearBufferSubDataTest,
2830                 executeClearColorBufferTest,
2831                 executeClearDepthBufferTest,
2832                 executeClearStencilBufferTest,
2833                 executeClearTexSubImageTest,
2834                 executeCopyImageSubDataTest,
2835                 executeTexSubImageTest,
2836         };
2837         const unsigned int n_query_draw_handlers = sizeof(query_draw_handlers) / sizeof(query_draw_handlers[0]);
2838
2839         for (unsigned int n = 0; n < n_query_draw_handlers; ++n)
2840         {
2841                 const PipelineStatisticsQueryUtilities::PFNQUERYDRAWHANDLERPROC& draw_handler_pfn = query_draw_handlers[n];
2842
2843                 /* Query executors can return false if a given test cannot be executed, given
2844                  * work environment constraint (eg. insufficient GL version). In case of an error,
2845                  * they will throw an exception.
2846                  */
2847                 if (draw_handler_pfn(this))
2848                 {
2849                         if (!PipelineStatisticsQueryUtilities::executeQuery(
2850                                         current_query_target, m_qo_id, m_bo_qo_id, DE_NULL, /* pfn_draw */
2851                                         DE_NULL,                                                                                        /* draw_user_arg */
2852                                         m_context.getRenderContext(), m_testCtx, m_context.getContextInfo(), &run_result))
2853                         {
2854                                 m_testCtx.getLog() << tcu::TestLog::Message << "Query execution failed for query target "
2855                                                                                                                            "["
2856                                                                    << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target) << "]"
2857                                                                    << tcu::TestLog::EndMessage;
2858
2859                                 result = false;
2860                         }
2861                         else
2862                         {
2863                                 const glw::GLuint64 expected_value = 0;
2864                                 bool                            has_passed       = true;
2865
2866                                 has_passed = PipelineStatisticsQueryUtilities::verifyResultValues(
2867                                         run_result, 1, &expected_value, m_qo_id != 0,  /* should_check_qo_bo_values */
2868                                         current_query_target, DE_NULL, DE_NULL, false, /* is_primitive_restart_enabled */
2869                                         m_testCtx, PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_EXACT_MATCH);
2870
2871                                 if (!has_passed)
2872                                 {
2873                                         m_testCtx.getLog() << tcu::TestLog::Message << "Test failed for iteration index [" << n << "]."
2874                                                                            << tcu::TestLog::EndMessage;
2875
2876                                         result = false;
2877                                 }
2878                         } /* if (run results were obtained successfully) */
2879                 }        /* if (draw handler executed successfully) */
2880         }
2881
2882         return result;
2883 }
2884
2885 /* Initializes all GL objects used by the test */
2886 void PipelineStatisticsQueryTestFunctional2::initObjects()
2887 {
2888         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2889
2890         /* Set up a buffer object we will use for one of the tests */
2891         gl.genBuffers(1, &m_bo_id);
2892         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2893
2894         gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
2895         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
2896
2897         gl.bufferData(GL_ARRAY_BUFFER, bo_size, DE_NULL, /* data */
2898                                   GL_STATIC_DRAW);
2899         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2900
2901         /* Set up texture objects we will  use as color attachments for test FBOs */
2902         gl.genTextures(1, &m_to_draw_fbo_id);
2903         gl.genTextures(1, &m_to_read_fbo_id);
2904         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
2905
2906         gl.bindTexture(GL_TEXTURE_2D, m_to_draw_fbo_id);
2907         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
2908
2909         gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
2910                                         GL_RGBA8, m_to_width, m_to_height);
2911         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
2912
2913         gl.bindTexture(GL_TEXTURE_2D, m_to_read_fbo_id);
2914         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
2915
2916         gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
2917                                         GL_RGBA8, m_to_width, m_to_height);
2918         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
2919
2920         /* Set up framebuffer objects */
2921         gl.genFramebuffers(1, &m_fbo_draw_id);
2922         gl.genFramebuffers(1, &m_fbo_read_id);
2923         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call(s) failed.");
2924
2925         gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_draw_id);
2926         gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read_id);
2927         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call(s) failed.");
2928
2929         gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_draw_fbo_id, 0); /* level */
2930         gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_read_fbo_id, 0); /* level */
2931         GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call(s) failed.");
2932 }
2933
2934 /** Constructor.
2935  *
2936  *  @param context Rendering context
2937  */
2938 PipelineStatisticsQueryTestFunctional3::PipelineStatisticsQueryTestFunctional3(deqp::Context& context)
2939         : PipelineStatisticsQueryTestFunctionalBase(
2940                   context, "functional_primitives_vertices_submitted_and_clipping_input_output_primitives",
2941                   "Verifies that GL_PRIMITIVES_SUBMITTED_ARB, GL_VERTICES_SUBMITTED_ARB, "
2942                   "GL_CLIPPING_INPUT_PRIMITIVES_ARB, and GL_CLIPPING_OUTPUT_PRIMITIVES_ARB "
2943                   "queries work correctly.")
2944         , m_is_primitive_restart_enabled(false)
2945 {
2946         /* Left blank intentionally */
2947 }
2948
2949 /** Deinitializes all GL objects that were created during test execution. */
2950 void PipelineStatisticsQueryTestFunctional3::deinitObjects()
2951 {
2952         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2953
2954         if (m_po_id != 0)
2955         {
2956                 gl.deleteProgram(m_po_id);
2957
2958                 m_po_id = 0;
2959         }
2960
2961         /* Disable "primitive restart" functionality */
2962         gl.disable(GL_PRIMITIVE_RESTART);
2963         GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed.");
2964 }
2965
2966 /** Executes a test iteration for user-specified query target.
2967  *
2968  *  @param current_query_target Pipeline statistics query target to execute the iteration
2969  *                              for.
2970  *
2971  *  @return true if the test passed for the iteration, false otherwise.
2972  **/
2973 bool PipelineStatisticsQueryTestFunctional3::executeTest(glw::GLenum current_query_target)
2974 {
2975         const glw::Functions&                                                                    gl             = m_context.getRenderContext().getFunctions();
2976         bool                                                                                                     result = true;
2977         PipelineStatisticsQueryUtilities::_test_execution_result run_result;
2978
2979         /* Sanity check: This method should only be called for GL_VERTICES_SUBMITTED_ARB,
2980          * GL_PRIMITIVES_SUBMITTED_ARB, GL_CLIPPING_INPUT_PRIMITIVES_ARB and
2981          * GL_CLIPPING_OUTPUT_PRIMITIVES_ARB queries */
2982         DE_ASSERT(current_query_target == GL_VERTICES_SUBMITTED_ARB ||
2983                           current_query_target == GL_PRIMITIVES_SUBMITTED_ARB ||
2984                           current_query_target == GL_CLIPPING_INPUT_PRIMITIVES_ARB ||
2985                           current_query_target == GL_CLIPPING_OUTPUT_PRIMITIVES_ARB);
2986
2987         /* Set up VBO. We don't really care much about the visual outcome,
2988          * so any data will do.
2989          */
2990         const unsigned int n_vertex_components = 2;
2991         const float                vertex_data[]           = { -0.1f, 0.2f, 0.3f,  0.1f,  0.2f,  -0.7f, 0.5f,  -0.5f,
2992                                                                   0.0f,  0.0f, -0.6f, -0.9f, -0.3f, 0.3f,  -0.5f, -0.5f };
2993         const unsigned int index_data[] = {
2994                 0, 6, 2, 1, 3, 5, 4,
2995         };
2996         const unsigned int n_indices = sizeof(index_data) / sizeof(index_data[0]);
2997
2998         m_indirect_draw_call_baseinstance_argument = 1;
2999         m_indirect_draw_call_basevertex_argument   = 0;
3000         m_indirect_draw_call_count_argument                = n_indices;
3001         m_indirect_draw_call_first_argument                = 0;
3002         m_indirect_draw_call_primcount_argument = 3;
3003
3004         initVBO(vertex_data, sizeof(vertex_data), index_data, sizeof(index_data), m_indirect_draw_call_count_argument,
3005                         m_indirect_draw_call_primcount_argument, m_indirect_draw_call_baseinstance_argument,
3006                         m_indirect_draw_call_first_argument, m_indirect_draw_call_basevertex_argument);
3007
3008         initVAO(n_vertex_components);
3009
3010         /* Verify that the query works correctly both when primitive restart functionality
3011          * is disabled and enabled */
3012         const bool                 pr_statuses[] = { false, true };
3013         const unsigned int n_pr_statuses = sizeof(pr_statuses) / sizeof(pr_statuses[0]);
3014
3015         for (unsigned int n_pr_status = 0; n_pr_status < n_pr_statuses; ++n_pr_status)
3016         {
3017                 m_is_primitive_restart_enabled = pr_statuses[n_pr_status];
3018
3019                 /* Primitive restart should never be enabled for GL_CLIPPING_INPUT_PRIMITIVES_ARB query. */
3020                 if ((current_query_target == GL_CLIPPING_INPUT_PRIMITIVES_ARB ||
3021                          current_query_target == GL_CLIPPING_OUTPUT_PRIMITIVES_ARB) &&
3022                         m_is_primitive_restart_enabled)
3023                 {
3024                         continue;
3025                 }
3026
3027                 /* Configure 'primitive restart' functionality */
3028                 if (!m_is_primitive_restart_enabled)
3029                 {
3030                         gl.disable(GL_PRIMITIVE_RESTART);
3031                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed.");
3032                 }
3033                 else
3034                 {
3035                         gl.primitiveRestartIndex(0);
3036                         GLU_EXPECT_NO_ERROR(gl.getError(), "glPrimitiveRestartIndex() call failed.");
3037
3038                         gl.enable(GL_PRIMITIVE_RESTART);
3039                         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed.");
3040                 }
3041
3042                 /* Iterate through all primitive types */
3043                 for (unsigned int n_primitive_type = 0;
3044                          n_primitive_type < PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_COUNT; ++n_primitive_type)
3045                 {
3046                         m_current_primitive_type = (PipelineStatisticsQueryUtilities::_primitive_type)n_primitive_type;
3047
3048                         /* Exclude patches from the test */
3049                         if (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_PATCHES)
3050                         {
3051                                 continue;
3052                         }
3053
3054                         /* Iterate through all draw call types while the query is enabled (skip DrawArrays calls if primitive restart is enabled) */
3055                         for (unsigned int n_draw_call_type =
3056                                          (m_is_primitive_restart_enabled ? PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTS :
3057                                                                                                            0);
3058                                  n_draw_call_type < PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_COUNT; ++n_draw_call_type)
3059                         {
3060                                 m_current_draw_call_type = (PipelineStatisticsQueryUtilities::_draw_call_type)n_draw_call_type;
3061
3062                                 /* Only continue if the draw call is supported by the context */
3063                                 if (!PipelineStatisticsQueryUtilities::isDrawCallSupported(m_current_draw_call_type, gl))
3064                                 {
3065                                         continue;
3066                                 }
3067
3068                                 if (!PipelineStatisticsQueryUtilities::executeQuery(
3069                                                 current_query_target, m_qo_id, m_bo_qo_id, queryCallbackDrawCallHandler,
3070                                                 (PipelineStatisticsQueryTestFunctionalBase*)this, m_context.getRenderContext(), m_testCtx,
3071                                                 m_context.getContextInfo(), &run_result))
3072                                 {
3073                                         m_testCtx.getLog() << tcu::TestLog::Message
3074                                                                            << "Could not retrieve test run results for query target "
3075                                                                                   "["
3076                                                                            << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target)
3077                                                                            << "]" << tcu::TestLog::EndMessage;
3078
3079                                         result = false;
3080                                 }
3081                                 else
3082                                 {
3083                                         glw::GLuint64                                                                            expected_values[4] = { 0 };
3084                                         unsigned int                                                                             n_expected_values  = 0;
3085                                         PipelineStatisticsQueryUtilities::_verification_type verification_type =
3086                                                 PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_EXACT_MATCH;
3087
3088                                         if (current_query_target == GL_CLIPPING_OUTPUT_PRIMITIVES_ARB)
3089                                         {
3090                                                 verification_type = PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_EQUAL_OR_GREATER;
3091                                         }
3092
3093                                         if (current_query_target == GL_VERTICES_SUBMITTED_ARB)
3094                                         {
3095                                                 getExpectedVerticesSubmittedQueryResult(m_current_primitive_type, &n_expected_values,
3096                                                                                                                                 expected_values);
3097                                         }
3098                                         else
3099                                         {
3100                                                 getExpectedPrimitivesSubmittedQueryResult(m_current_primitive_type, &n_expected_values,
3101                                                                                                                                   expected_values);
3102                                         }
3103
3104                                         result &= PipelineStatisticsQueryUtilities::verifyResultValues(
3105                                                 run_result, n_expected_values, expected_values, m_qo_id != 0, /* should_check_qo_bo_values */
3106                                                 current_query_target, &m_current_draw_call_type, &m_current_primitive_type,
3107                                                 m_is_primitive_restart_enabled, m_testCtx, verification_type);
3108
3109                                 } /* if (run results were obtained successfully) */
3110                         }        /* for (all draw call types) */
3111                 }                 /* for (all primitive types) */
3112         }                         /* for (both when primitive restart is disabled and enabled) */
3113
3114         return result;
3115 }
3116
3117 /** Returns the expected result value(s) for a GL_PRIMITIVES_SUBMITTED_ARB query. There
3118  *  can be either one or two result values, depending on how the implementation handles
3119  *  incomplete primitives.
3120  *
3121  *  @param current_primitive_type Primitive type used for the draw call, for which
3122  *                                the query would be executed
3123  *  @param out_result1_written    Deref will be set to true, if the first result value
3124  *                                was written to @param out_result1. Otherwise, it will
3125  *                                be set to false.
3126  *  @param out_result1            Deref will be set to the first of the acceptable
3127  *                                result values, if @param out_result1_written was set
3128  *                                to true.
3129  *  @param out_result2_written    Deref will be set to true, if the second result value
3130  *                                was written to @param out_result2. Otherwise, it will
3131  *                                be set to false.
3132  *  @param out_result2            Deref will be set to the second of the acceptable
3133  *                                result values, if @param out_result2_written was set
3134  *                                to true.
3135  *
3136  **/
3137 void PipelineStatisticsQueryTestFunctional3::getExpectedPrimitivesSubmittedQueryResult(
3138         PipelineStatisticsQueryUtilities::_primitive_type current_primitive_type, unsigned int* out_results_written,
3139         glw::GLuint64 out_results[4])
3140 {
3141         unsigned int n_input_vertices = m_indirect_draw_call_count_argument;
3142
3143         *out_results_written = 0;
3144
3145         /* Sanity checks */
3146         DE_ASSERT(current_primitive_type != PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_PATCHES);
3147
3148         /* Carry on */
3149         if (m_is_primitive_restart_enabled)
3150         {
3151                 /* Primitive restart functionality in our test removes a single index.
3152                  *
3153                  * Note: This also applies to arrayed draw calls, since we're testing
3154                  *       GL_PRIMITIVE_RESTART rendering mode, and we're using a primitive
3155                  *       restart index of 0.
3156                  **/
3157                 n_input_vertices--;
3158         }
3159
3160         switch (current_primitive_type)
3161         {
3162         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_POINTS:
3163         {
3164                 out_results[(*out_results_written)++] = n_input_vertices;
3165
3166                 break;
3167         }
3168
3169         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINE_LOOP:
3170         {
3171                 if (n_input_vertices > 2)
3172                 {
3173                         out_results[(*out_results_written)++] = n_input_vertices;
3174                 }
3175                 else if (n_input_vertices > 1)
3176                 {
3177                         out_results[(*out_results_written)++] = 1;
3178                 }
3179                 else
3180                 {
3181                         out_results[(*out_results_written)++] = 0;
3182                 }
3183
3184                 break;
3185         } /* PRIMITIVE_TYPE_LINE_LOOP */
3186
3187         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLE_FAN:
3188         {
3189                 if (n_input_vertices > 2)
3190                 {
3191                         out_results[(*out_results_written)++] = n_input_vertices - 2;
3192                 }
3193                 else
3194                 {
3195                         out_results[(*out_results_written)++] = 0;
3196
3197                         if (n_input_vertices >= 1)
3198                         {
3199                                 /* If the submitted triangle fan is incomplete, also include the case
3200                                  * where the incomplete triangle fan's vertices are counted as a primitive.
3201                                  */
3202                                 out_results[(*out_results_written)++] = 1;
3203                         }
3204                 }
3205
3206                 break;
3207         }
3208
3209         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINE_STRIP:
3210         {
3211                 if (n_input_vertices > 1)
3212                 {
3213                         out_results[(*out_results_written)++] = n_input_vertices - 1;
3214                 }
3215                 else
3216                 {
3217                         out_results[(*out_results_written)++] = 0;
3218
3219                         if (n_input_vertices > 0)
3220                         {
3221                                 /* If the submitted line strip is incomplete, also include the case
3222                                  * where the incomplete line's vertices are counted as a primitive.
3223                                  */
3224                                 out_results[(*out_results_written)++] = 1;
3225                         }
3226                 }
3227
3228                 break;
3229         }
3230
3231         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLE_STRIP:
3232         {
3233                 if (n_input_vertices > 2)
3234                 {
3235                         out_results[(*out_results_written)++] = n_input_vertices - 2;
3236                 }
3237                 else
3238                 {
3239                         out_results[(*out_results_written)++] = 0;
3240
3241                         if (n_input_vertices >= 1)
3242                         {
3243                                 /* If the submitted triangle strip is incomplete, also include the case
3244                                  * where the incomplete triangle's vertices are counted as a primitive.
3245                                  */
3246                                 out_results[(*out_results_written)++] = 1;
3247                         }
3248                 }
3249
3250                 break;
3251         }
3252
3253         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES:
3254         {
3255                 out_results[(*out_results_written)++] = n_input_vertices / 2;
3256
3257                 /* If the submitted line is incomplete, also include the case where
3258                  * the incomplete line's vertices are counted as a primitive.
3259                  */
3260                 if (n_input_vertices > 0 && (n_input_vertices % 2) != 0)
3261                 {
3262                         out_results[(*out_results_written)++] = n_input_vertices / 2 + 1;
3263                 }
3264
3265                 break;
3266         }
3267
3268         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES_ADJACENCY:
3269         {
3270                 out_results[(*out_results_written)++] = n_input_vertices / 4;
3271
3272                 /* If the submitted line is incomplete, also include the case where
3273                  * the incomplete line's vertices are counted as a primitive.
3274                  */
3275                 if (n_input_vertices > 0 && (n_input_vertices % 4) != 0)
3276                 {
3277                         out_results[(*out_results_written)++] = n_input_vertices / 4 + 1;
3278                 }
3279
3280                 break;
3281         }
3282
3283         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES:
3284         {
3285                 out_results[(*out_results_written)++] = n_input_vertices / 3;
3286
3287                 /* If the submitted triangle is incomplete, also include the case
3288                  * when the incomplete triangle's vertices are counted as a primitive.
3289                  */
3290                 if (n_input_vertices > 0 && (n_input_vertices % 3) != 0)
3291                 {
3292                         out_results[(*out_results_written)++] = n_input_vertices / 3 + 1;
3293                 }
3294
3295                 break;
3296         }
3297
3298         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES_ADJACENCY:
3299         {
3300                 out_results[(*out_results_written)++] = n_input_vertices / 6;
3301
3302                 /* If the submitted triangle is incomplete, also include the case
3303                  * when the incomplete triangle's vertices are counted as a primitive.
3304                  */
3305                 if (n_input_vertices > 0 && (n_input_vertices % 6) != 0)
3306                 {
3307                         out_results[(*out_results_written)++] = n_input_vertices / 6 + 1;
3308                 }
3309
3310                 break;
3311         }
3312
3313         default:
3314         {
3315                 TCU_FAIL("Unrecognized primitive type");
3316         }
3317         } /* switch (current_primitive_type) */
3318
3319         if (PipelineStatisticsQueryUtilities::isInstancedDrawCall(m_current_draw_call_type))
3320         {
3321                 for (unsigned int i = 0; i < *out_results_written; ++i)
3322                 {
3323                         out_results[i] *= m_indirect_draw_call_primcount_argument;
3324                 }
3325         } /* if (instanced draw call type) */
3326 }
3327
3328 /** Returns the expected result value(s) for a GL_VERTICES_SUBMITTED_ARB query. There
3329  *  can be either one or two result values, depending on how the implementation handles
3330  *  incomplete primitives.
3331  *
3332  *  @param current_primitive_type Primitive type used for the draw call, for which
3333  *                                the query would be executed
3334  *  @param out_result1_written    Deref will be set to true, if the first result value
3335  *                                was written to @param out_result1. Otherwise, it will
3336  *                                be set to false.
3337  *  @param out_result1            Deref will be set to the first of the acceptable
3338  *                                result values, if @param out_result1_written was set
3339  *                                to true.
3340  *  @param out_result2_written    Deref will be set to true, if the second result value
3341  *                                was written to @param out_result2. Otherwise, it will
3342  *                                be set to false.
3343  *  @param out_result2            Deref will be set to the second of the acceptable
3344  *                                result values, if @param out_result2_written was set
3345  *                                to true.
3346  *
3347  **/
3348 void PipelineStatisticsQueryTestFunctional3::getExpectedVerticesSubmittedQueryResult(
3349         PipelineStatisticsQueryUtilities::_primitive_type current_primitive_type, unsigned int* out_results_written,
3350         glw::GLuint64 out_results[4])
3351 {
3352         unsigned int n_input_vertices = m_indirect_draw_call_count_argument;
3353
3354         *out_results_written = 0;
3355
3356         /* Sanity checks */
3357         DE_ASSERT(current_primitive_type != PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_PATCHES);
3358
3359         /* Carry on */
3360         if (m_is_primitive_restart_enabled)
3361         {
3362                 /* Primitive restart functionality in our test removes a single index.
3363                  *
3364                  * Note: This also applies to arrayed draw calls, since we're testing
3365                  *       GL_PRIMITIVE_RESTART rendering mode, and we're using a primitive
3366                  *       restart index of 0.
3367                  **/
3368                 n_input_vertices--;
3369         }
3370
3371         switch (current_primitive_type)
3372         {
3373         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_POINTS:
3374         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINE_STRIP:
3375         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLE_FAN:
3376         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLE_STRIP:
3377         {
3378                 out_results[(*out_results_written)++] = n_input_vertices;
3379
3380                 break;
3381         }
3382
3383         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINE_LOOP:
3384         {
3385                 out_results[(*out_results_written)++] = n_input_vertices;
3386
3387                 /* Allow line loops to count the first vertex twice as that vertex
3388                  * is part of both the first and the last primitives.
3389                  */
3390                 out_results[(*out_results_written)++] = n_input_vertices + 1;
3391                 break;
3392         }
3393
3394         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES:
3395         {
3396                 out_results[(*out_results_written)++] = n_input_vertices;
3397
3398                 /* If the submitted line is incomplete, also include the case where
3399                  * the incomplete line's vertices are not counted.
3400                  */
3401                 if (n_input_vertices > 0 && (n_input_vertices % 2) != 0)
3402                 {
3403                         out_results[(*out_results_written)++] = n_input_vertices - 1;
3404                 }
3405
3406                 break;
3407         }
3408
3409         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES_ADJACENCY:
3410         {
3411                 /* Allow implementations to both include or exclude the adjacency
3412                  * vertices.
3413                  */
3414                 out_results[(*out_results_written)++] = n_input_vertices;
3415                 out_results[(*out_results_written)++] = n_input_vertices / 2;
3416
3417                 /* If the submitted line is incomplete, also include the case where
3418                  * the incomplete line's vertices are not counted.
3419                  */
3420                 if (n_input_vertices > 0 && (n_input_vertices % 4) != 0)
3421                 {
3422                         out_results[(*out_results_written)++] = n_input_vertices - (n_input_vertices % 4);
3423                         out_results[(*out_results_written)++] = (n_input_vertices - (n_input_vertices % 4)) / 2;
3424                 }
3425
3426                 break;
3427         }
3428
3429         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES:
3430         {
3431                 out_results[(*out_results_written)++] = n_input_vertices;
3432
3433                 /* If the submitted triangle is incomplete, also include the case
3434                  * when the incomplete triangle's vertices are not counted.
3435                  */
3436                 if (n_input_vertices > 0 && (n_input_vertices % 3) != 0)
3437                 {
3438                         out_results[(*out_results_written)++] = n_input_vertices - (n_input_vertices % 3);
3439                 }
3440
3441                 break;
3442         }
3443
3444         case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES_ADJACENCY:
3445         {
3446                 /* Allow implementations to both include or exclude the adjacency
3447                  * vertices.
3448                  */
3449                 out_results[(*out_results_written)++] = n_input_vertices;
3450                 out_results[(*out_results_written)++] = n_input_vertices / 2;
3451
3452                 /* If the submitted triangle is incomplete, also include the case
3453                  * when the incomplete triangle's vertices are not counted.
3454                  */
3455                 if (n_input_vertices > 0 && (n_input_vertices % 6) != 0)
3456                 {
3457                         out_results[(*out_results_written)++] = n_input_vertices - (n_input_vertices % 6);
3458                         out_results[(*out_results_written)++] = (n_input_vertices - (n_input_vertices % 6)) / 2;
3459                 }
3460
3461                 break;
3462         }
3463
3464         default:
3465         {
3466                 TCU_FAIL("Unrecognized primitive type");
3467         }
3468         } /* switch (current_primitive_type) */
3469
3470         if (PipelineStatisticsQueryUtilities::isInstancedDrawCall(m_current_draw_call_type))
3471         {
3472                 for (unsigned int i = 0; i < *out_results_written; ++i)
3473                 {
3474                         out_results[i] *= m_indirect_draw_call_primcount_argument;
3475                 }
3476         } /* if (instanced draw call type) */
3477 }
3478
3479 /** Initializes GL objects used by the test */
3480 void PipelineStatisticsQueryTestFunctional3::initObjects()
3481 {
3482         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3483
3484         buildProgram(DE_NULL,                                                                                              /* cs_body */
3485                                  PipelineStatisticsQueryUtilities::dummy_fs_code, DE_NULL, /* gs_body */
3486                                  DE_NULL,                                                                                                  /* tc_body */
3487                                  DE_NULL,                                                                                                  /* te_body */
3488                                  PipelineStatisticsQueryUtilities::dummy_vs_code);
3489
3490         gl.useProgram(m_po_id);
3491         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3492 }
3493
3494 /** Tells whether the test instance should be executed for user-specified query target.
3495  *
3496  *  @param query_target Query target to be used for the call.
3497  *
3498  *  @return true  if @param query_target is either GL_VERTICES_SUBMITTED_ARB,
3499  *                GL_PRIMITIVES_SUBMITTED_ARB, GL_CLIPPING_INPUT_PRIMITIVES_ARB, or
3500  *                GL_CLIPPING_OUTPUT_PRIMITIVES_ARB.
3501  *          false otherwise.
3502  **/
3503 bool PipelineStatisticsQueryTestFunctional3::shouldExecuteForQueryTarget(glw::GLenum query_target)
3504 {
3505         return (query_target == GL_VERTICES_SUBMITTED_ARB || query_target == GL_PRIMITIVES_SUBMITTED_ARB ||
3506                         query_target == GL_CLIPPING_INPUT_PRIMITIVES_ARB || query_target == GL_CLIPPING_OUTPUT_PRIMITIVES_ARB);
3507 }
3508
3509 /** Constructor.
3510  *
3511  *  @param context Rendering context
3512  */
3513 PipelineStatisticsQueryTestFunctional4::PipelineStatisticsQueryTestFunctional4(deqp::Context& context)
3514         : PipelineStatisticsQueryTestFunctionalBase(context, "functional_vertex_shader_invocations",
3515                                                                                                 "Verifies GL_VERTEX_SHADER_INVOCATIONS_ARB query works correctly")
3516 {
3517         /* Left blank intentionally */
3518 }
3519
3520 /** Deinitializes all GL objects that were created during test execution. */
3521 void PipelineStatisticsQueryTestFunctional4::deinitObjects()
3522 {
3523         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3524
3525         if (m_po_id != 0)
3526         {
3527                 gl.deleteProgram(m_po_id);
3528
3529                 m_po_id = 0;
3530         }
3531 }
3532
3533 /** Executes a test iteration for user-specified query target.
3534  *
3535  *  @param current_query_target Pipeline statistics query target to execute the iteration
3536  *                              for.
3537  *
3538  *  @return true if the test passed for the iteration, false otherwise.
3539  **/
3540 bool PipelineStatisticsQueryTestFunctional4::executeTest(glw::GLenum current_query_target)
3541 {
3542         const glw::Functions&                                                                    gl             = m_context.getRenderContext().getFunctions();
3543         bool                                                                                                     result = true;
3544         PipelineStatisticsQueryUtilities::_test_execution_result run_result;
3545
3546         /* Sanity check: This method should only be called for GL_VERTEX_SHADER_INVOCATIONS_ARB
3547          * query */
3548         DE_ASSERT(current_query_target == GL_VERTEX_SHADER_INVOCATIONS_ARB);
3549
3550         /* Set up VBO. */
3551         const unsigned int n_vertex_components = 2;
3552         const float                vertex_data[]  = { -0.1f, 0.2f, 0.3f, 0.1f, 0.2f, -0.7f, 0.5f, -0.5f, 0.0f, 0.0f, 0.1f, 0.2f };
3553         const unsigned int index_data[]   = { 4, 3, 2, 1, 0 };
3554         const unsigned int n_data_indices = sizeof(index_data) / sizeof(index_data[0]);
3555
3556         /* Issue the test for 1 to 5 indices */
3557         for (unsigned int n_indices = 1; n_indices < n_data_indices; ++n_indices)
3558         {
3559                 m_indirect_draw_call_baseinstance_argument = 1;
3560                 m_indirect_draw_call_basevertex_argument   = 1;
3561                 m_indirect_draw_call_count_argument                = n_indices;
3562                 m_indirect_draw_call_first_argument                = 0;
3563                 m_indirect_draw_call_primcount_argument = 4;
3564
3565                 initVBO(vertex_data, sizeof(vertex_data), index_data, sizeof(index_data), m_indirect_draw_call_count_argument,
3566                                 m_indirect_draw_call_primcount_argument, m_indirect_draw_call_baseinstance_argument,
3567                                 m_indirect_draw_call_first_argument, m_indirect_draw_call_basevertex_argument);
3568
3569                 initVAO(n_vertex_components);
3570
3571                 /* Iterate through all primitive types */
3572                 for (unsigned int n_primitive_type = 0;
3573                          n_primitive_type < PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_COUNT; ++n_primitive_type)
3574                 {
3575                         m_current_primitive_type = (PipelineStatisticsQueryUtilities::_primitive_type)n_primitive_type;
3576
3577                         /* Exclude patches from the test */
3578                         if (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_PATCHES)
3579                         {
3580                                 continue;
3581                         }
3582
3583                         /* Exclude the primitive types, for which the number of indices is insufficient to form
3584                          * a primitive.
3585                          */
3586                         if ((m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINE_LOOP &&
3587                                  n_indices < 2) ||
3588                                 (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINE_STRIP &&
3589                                  n_indices < 2) ||
3590                                 (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES && n_indices < 2) ||
3591                                 (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLE_FAN &&
3592                                  n_indices < 3) ||
3593                                 (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLE_STRIP &&
3594                                  n_indices < 3) ||
3595                                 (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES &&
3596                                  n_indices < 3))
3597                         {
3598                                 /* Skip the iteration */
3599                                 continue;
3600                         }
3601
3602                         /* Exclude adjacency primitive types from the test, since we're not using geometry shader stage. */
3603                         if (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES_ADJACENCY ||
3604                                 m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES_ADJACENCY)
3605                         {
3606                                 continue;
3607                         }
3608
3609                         /* Iterate through all draw call types */
3610                         for (unsigned int n_draw_call_type = 0;
3611                                  n_draw_call_type < PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_COUNT; ++n_draw_call_type)
3612                         {
3613                                 m_current_draw_call_type = (PipelineStatisticsQueryUtilities::_draw_call_type)n_draw_call_type;
3614
3615                                 /* Only continue if the draw call is supported by the context */
3616                                 if (!PipelineStatisticsQueryUtilities::isDrawCallSupported(m_current_draw_call_type, gl))
3617                                 {
3618                                         continue;
3619                                 }
3620
3621                                 /* Execute the query */
3622                                 if (!PipelineStatisticsQueryUtilities::executeQuery(
3623                                                 current_query_target, m_qo_id, m_bo_qo_id, queryCallbackDrawCallHandler,
3624                                                 (PipelineStatisticsQueryTestFunctionalBase*)this, m_context.getRenderContext(), m_testCtx,
3625                                                 m_context.getContextInfo(), &run_result))
3626                                 {
3627                                         m_testCtx.getLog() << tcu::TestLog::Message
3628                                                                            << "Could not retrieve test run results for query target "
3629                                                                                   "["
3630                                                                            << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target)
3631                                                                            << "]" << tcu::TestLog::EndMessage;
3632
3633                                         result = false;
3634                                 }
3635                                 else
3636                                 {
3637                                         static const glw::GLuint64 expected_value = 1;
3638
3639                                         /* Compare it against query result values */
3640                                         result &= PipelineStatisticsQueryUtilities::verifyResultValues(
3641                                                 run_result, 1, &expected_value, m_qo_id != 0, /* should_check_qo_bo_values */
3642                                                 current_query_target, &m_current_draw_call_type, &m_current_primitive_type,
3643                                                 false, /* is_primitive_restart_enabled */
3644                                                 m_testCtx, PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_EQUAL_OR_GREATER);
3645
3646                                 } /* if (run results were obtained successfully) */
3647                         }        /* for (all draw call types) */
3648                 }                 /* for (all primitive types) */
3649         }                         /* for (1 to 5 indices) */
3650
3651         return result;
3652 }
3653
3654 /** Initializes all GL objects used by the test */
3655 void PipelineStatisticsQueryTestFunctional4::initObjects()
3656 {
3657         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3658
3659         buildProgram(DE_NULL, /* cs_body */
3660                                  DE_NULL, /* fs_body */
3661                                  DE_NULL, /* gs_body */
3662                                  DE_NULL, /* tc_body */
3663                                  DE_NULL, /* te_body */
3664                                  PipelineStatisticsQueryUtilities::dummy_vs_code);
3665
3666         gl.useProgram(m_po_id);
3667         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3668 }
3669
3670 /** Tells whether the test instance should be executed for user-specified query target.
3671  *
3672  *  @param query_target Query target to be used for the call.
3673  *
3674  *  @return true  if @param query_target is GL_VERTEX_SHADER_INVOCATIONS_ARB.
3675  *          false otherwise.
3676  **/
3677 bool PipelineStatisticsQueryTestFunctional4::shouldExecuteForQueryTarget(glw::GLenum query_target)
3678 {
3679         return (query_target == GL_VERTEX_SHADER_INVOCATIONS_ARB);
3680 }
3681
3682 /** Constructor.
3683  *
3684  *  @param context Rendering context
3685  */
3686 PipelineStatisticsQueryTestFunctional5::PipelineStatisticsQueryTestFunctional5(deqp::Context& context)
3687         : PipelineStatisticsQueryTestFunctionalBase(context, "functional_tess_queries",
3688                                                                                                 "Verifies that GL_TESS_CONTROL_SHADER_PATCHES_ARB and "
3689                                                                                                 "GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB queries "
3690                                                                                                 "work correctly.")
3691 {
3692         /* Left blank intentionally */
3693 }
3694
3695 /** Deinitializes all GL objects that were created during test execution. */
3696 void PipelineStatisticsQueryTestFunctional5::deinitObjects()
3697 {
3698         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3699
3700         if (m_po_id != 0)
3701         {
3702                 gl.deleteProgram(m_po_id);
3703
3704                 m_po_id = 0;
3705         }
3706 }
3707
3708 /** Executes a test iteration for user-specified query target.
3709  *
3710  *  @param current_query_target Pipeline statistics query target to execute the iteration
3711  *                              for.
3712  *
3713  *  @return true if the test passed for the iteration, false otherwise.
3714  **/
3715 bool PipelineStatisticsQueryTestFunctional5::executeTest(glw::GLenum current_query_target)
3716 {
3717         const glw::Functions&                                                                    gl             = m_context.getRenderContext().getFunctions();
3718         bool                                                                                                     result = true;
3719         PipelineStatisticsQueryUtilities::_test_execution_result run_result;
3720
3721         /* Sanity check: This method should only be called for GL_TESS_CONTROL_SHADER_PATCHES_ARB and
3722          * GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB queries. */
3723         DE_ASSERT(current_query_target == GL_TESS_CONTROL_SHADER_PATCHES_ARB ||
3724                           current_query_target == GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB);
3725
3726         /* Set up VBO. */
3727         const unsigned int n_vertex_components = 2;
3728         const float                vertex_data[]           = {
3729                 -0.1f, 0.2f, 0.2f, -0.7f, 0.5f, -0.5f,
3730         };
3731         const unsigned int index_data[] = { 2, 1, 0 };
3732
3733         m_indirect_draw_call_baseinstance_argument = 1;
3734         m_indirect_draw_call_basevertex_argument   = 1;
3735         m_indirect_draw_call_count_argument                = 3; /* default GL_PATCH_VERTICES value */
3736         m_indirect_draw_call_first_argument                = 0;
3737         m_indirect_draw_call_primcount_argument = 4;
3738
3739         initVBO(vertex_data, sizeof(vertex_data), index_data, sizeof(index_data), m_indirect_draw_call_count_argument,
3740                         m_indirect_draw_call_primcount_argument, m_indirect_draw_call_baseinstance_argument,
3741                         m_indirect_draw_call_first_argument, m_indirect_draw_call_basevertex_argument);
3742
3743         initVAO(n_vertex_components);
3744
3745         /* Set up the primitive type */
3746         m_current_primitive_type = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_PATCHES;
3747
3748         /* Iterate through all draw call types */
3749         for (unsigned int n_draw_call_type = 0; n_draw_call_type < PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_COUNT;
3750                  ++n_draw_call_type)
3751         {
3752                 m_current_draw_call_type = (PipelineStatisticsQueryUtilities::_draw_call_type)n_draw_call_type;
3753
3754                 /* Only continue if the draw call is supported by the context */
3755                 if (!PipelineStatisticsQueryUtilities::isDrawCallSupported(m_current_draw_call_type, gl))
3756                 {
3757                         continue;
3758                 }
3759
3760                 /* Execute the query */
3761                 if (!PipelineStatisticsQueryUtilities::executeQuery(
3762                                 current_query_target, m_qo_id, m_bo_qo_id, queryCallbackDrawCallHandler,
3763                                 (PipelineStatisticsQueryTestFunctionalBase*)this, m_context.getRenderContext(), m_testCtx,
3764                                 m_context.getContextInfo(), &run_result))
3765                 {
3766                         m_testCtx.getLog() << tcu::TestLog::Message << "Could not retrieve test run results for query target "
3767                                                                                                                    "["
3768                                                            << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target) << "]"
3769                                                            << tcu::TestLog::EndMessage;
3770
3771                         result = false;
3772                 }
3773                 else
3774                 {
3775                         static const glw::GLuint64 expected_value = 1; /* as per test spec */
3776
3777                         /* Compare it against query result values */
3778                         result &= PipelineStatisticsQueryUtilities::verifyResultValues(
3779                                 run_result, 1, &expected_value, m_qo_id != 0, /* should_check_qo_bo_values */
3780                                 current_query_target, &m_current_draw_call_type, &m_current_primitive_type,
3781                                 false, /* is_primitive_restart_enabled */
3782                                 m_testCtx, PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_EQUAL_OR_GREATER);
3783
3784                 } /* if (run results were obtained successfully) */
3785         }        /* for (all draw call types) */
3786
3787         return result;
3788 }
3789
3790 /** Initializes all GL objects used by the test */
3791 void PipelineStatisticsQueryTestFunctional5::initObjects()
3792 {
3793         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3794
3795         /* This test should not execute if we're not running at least a GL4.0 context */
3796         if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)))
3797         {
3798                 throw tcu::NotSupportedError("OpenGL 4.0+ is required to run this test.");
3799         }
3800
3801         buildProgram(DE_NULL,                                                                                              /* cs_body */
3802                                  PipelineStatisticsQueryUtilities::dummy_fs_code, DE_NULL, /* gs_body */
3803                                  PipelineStatisticsQueryUtilities::dummy_tc_code, PipelineStatisticsQueryUtilities::dummy_te_code,
3804                                  PipelineStatisticsQueryUtilities::dummy_vs_code);
3805
3806         gl.useProgram(m_po_id);
3807         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3808 }
3809
3810 /** Tells whether the test instance should be executed for user-specified query target.
3811  *
3812  *  @param query_target Query target to be used for the call.
3813  *
3814  *  @return true  if @param query_target is either GL_TESS_CONTROL_SHADER_PATCHES_ARB,
3815  *                or GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB.
3816  *          false otherwise.
3817  **/
3818 bool PipelineStatisticsQueryTestFunctional5::shouldExecuteForQueryTarget(glw::GLenum query_target)
3819 {
3820         return (query_target == GL_TESS_CONTROL_SHADER_PATCHES_ARB ||
3821                         query_target == GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB);
3822 }
3823
3824 /** Constructor.
3825  *
3826  *  @param context Rendering context
3827  */
3828 PipelineStatisticsQueryTestFunctional6::PipelineStatisticsQueryTestFunctional6(deqp::Context& context)
3829         : PipelineStatisticsQueryTestFunctionalBase(context, "functional_geometry_shader_queries",
3830                                                                                                 "Verifies that GL_GEOMETRY_SHADER_INVOCATIONS and "
3831                                                                                                 "GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB queries "
3832                                                                                                 "work correctly.")
3833         , m_n_primitives_emitted_by_gs(3)
3834         , m_n_streams_emitted_by_gs(3)
3835 {
3836         /* Left blank intentionally */
3837 }
3838
3839 /** Deinitializes all GL objects that were created during test execution. */
3840 void PipelineStatisticsQueryTestFunctional6::deinitObjects()
3841 {
3842         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3843
3844         if (m_po_id != 0)
3845         {
3846                 gl.deleteProgram(m_po_id);
3847
3848                 m_po_id = 0;
3849         }
3850 }
3851
3852 /** Executes a test iteration for user-specified query target.
3853  *
3854  *  @param current_query_target Pipeline statistics query target to execute the iteration
3855  *                              for.
3856  *
3857  *  @return true if the test passed for the iteration, false otherwise.
3858  **/
3859 bool PipelineStatisticsQueryTestFunctional6::executeTest(glw::GLenum current_query_target)
3860 {
3861         const glw::Functions&                                                                    gl             = m_context.getRenderContext().getFunctions();
3862         bool                                                                                                     result = true;
3863         PipelineStatisticsQueryUtilities::_test_execution_result run_result;
3864
3865         /* Sanity check: This method should only be called for GL_GEOMETRY_SHADER_INVOCATIONS and
3866          * GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB queries. */
3867         DE_ASSERT(current_query_target == GL_GEOMETRY_SHADER_INVOCATIONS ||
3868                           current_query_target == GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB);
3869
3870         /* Set up VBO. */
3871         const unsigned int n_vertex_components = 2;
3872         const float                vertex_data[]           = {
3873                 -0.1f, 0.2f, 0.2f, -0.7f, 0.5f, -0.5f, 0.1f, -0.2f, -0.2f, 0.7f, -0.5f, 0.5f,
3874         };
3875         const unsigned int index_data[]                    = { 2, 1, 0 };
3876         m_indirect_draw_call_baseinstance_argument = 1;
3877         m_indirect_draw_call_basevertex_argument   = 1;
3878         m_indirect_draw_call_count_argument =
3879                 3; /* note: we will update the argument per iteration, so just use anything for now */
3880         m_indirect_draw_call_first_argument             = 0;
3881         m_indirect_draw_call_primcount_argument = 4;
3882
3883         initVBO(vertex_data, sizeof(vertex_data), index_data, sizeof(index_data), m_indirect_draw_call_count_argument,
3884                         m_indirect_draw_call_primcount_argument, m_indirect_draw_call_baseinstance_argument,
3885                         m_indirect_draw_call_first_argument, m_indirect_draw_call_basevertex_argument);
3886
3887         initVAO(n_vertex_components);
3888
3889         /* Iterate over all input primitives supported by geometry shaders */
3890         for (int gs_input_it = static_cast<int>(PipelineStatisticsQueryUtilities::GEOMETRY_SHADER_INPUT_FIRST);
3891                  gs_input_it != static_cast<int>(PipelineStatisticsQueryUtilities::GEOMETRY_SHADER_INPUT_COUNT); ++gs_input_it)
3892         {
3893                 PipelineStatisticsQueryUtilities::_geometry_shader_input gs_input =
3894                         static_cast<PipelineStatisticsQueryUtilities::_geometry_shader_input>(gs_input_it);
3895                 /* Set up the 'count' argument and update the VBO contents */
3896                 m_indirect_draw_call_count_argument = PipelineStatisticsQueryUtilities::getNumberOfVerticesForGSInput(gs_input);
3897
3898                 /* Update the VBO contents */
3899                 gl.bufferSubData(
3900                         GL_ARRAY_BUFFER,
3901                         m_vbo_indirect_arrays_argument_offset, /* the very first argument is 'count' which we need to update */
3902                         sizeof(m_indirect_draw_call_count_argument), &m_indirect_draw_call_count_argument);
3903                 gl.bufferSubData(
3904                         GL_ARRAY_BUFFER,
3905                         m_vbo_indirect_elements_argument_offset, /* the very first argument is 'count' which we need to update */
3906                         sizeof(m_indirect_draw_call_count_argument), &m_indirect_draw_call_count_argument);
3907                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
3908
3909                 for (int gs_output_it = static_cast<int>(PipelineStatisticsQueryUtilities::GEOMETRY_SHADER_OUTPUT_FIRST);
3910                          gs_output_it != static_cast<int>(PipelineStatisticsQueryUtilities::GEOMETRY_SHADER_OUTPUT_COUNT);
3911                          ++gs_output_it)
3912                 {
3913                         PipelineStatisticsQueryUtilities::_geometry_shader_output gs_output =
3914                                 static_cast<PipelineStatisticsQueryUtilities::_geometry_shader_output>(gs_output_it);
3915                         /* For GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB query, we need to test both single-stream and
3916                          * multi-stream geometry shaders.
3917                          *
3918                          * For GL_GEOMETRY_SHADER_INVOCATIONS, we only need a single iteration.
3919                          **/
3920                         const unsigned int n_internal_iterations =
3921                                 (current_query_target == GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB) ? 2 : 1;
3922
3923                         for (unsigned int n_internal_iteration = 0; n_internal_iteration < n_internal_iterations;
3924                                  ++n_internal_iteration)
3925                         {
3926                                 /* Build the test program. */
3927                                 std::string gs_body;
3928
3929                                 if (n_internal_iteration == 1)
3930                                 {
3931                                         /* This path will only be entered for GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB query.
3932                                          *
3933                                          * OpenGL does not support multiple vertex streams for output primitive types other than
3934                                          * points.
3935                                          */
3936                                         if (gs_output != PipelineStatisticsQueryUtilities::GEOMETRY_SHADER_OUTPUT_POINTS)
3937                                         {
3938                                                 continue;
3939                                         }
3940
3941                                         /* Build a multi-streamed geometry shader */
3942                                         gs_body = PipelineStatisticsQueryUtilities::buildGeometryShaderBody(
3943                                                 gs_input, gs_output, m_n_primitives_emitted_by_gs, m_n_streams_emitted_by_gs);
3944                                 }
3945                                 else
3946                                 {
3947                                         gs_body = PipelineStatisticsQueryUtilities::buildGeometryShaderBody(
3948                                                 gs_input, gs_output, m_n_primitives_emitted_by_gs, 1); /* n_streams */
3949                                 }
3950
3951                                 buildProgram(DE_NULL,                                                                                                                                   /* cs_body */
3952                                                          PipelineStatisticsQueryUtilities::dummy_fs_code, gs_body.c_str(), DE_NULL, /* tc_body */
3953                                                          DE_NULL,                                                                                                                                       /* te_body */
3954                                                          PipelineStatisticsQueryUtilities::dummy_vs_code);
3955
3956                                 gl.useProgram(m_po_id);
3957                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3958
3959                                 /* Set up the primitive type */
3960                                 m_current_primitive_type = PipelineStatisticsQueryUtilities::getPrimitiveTypeFromGSInput(gs_input);
3961
3962                                 /* Iterate through all draw call types */
3963                                 for (unsigned int n_draw_call_type = 0;
3964                                          n_draw_call_type < PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_COUNT; ++n_draw_call_type)
3965                                 {
3966                                         m_current_draw_call_type = (PipelineStatisticsQueryUtilities::_draw_call_type)n_draw_call_type;
3967
3968                                         /* Only continue if the draw call is supported by the context */
3969                                         if (!PipelineStatisticsQueryUtilities::isDrawCallSupported(m_current_draw_call_type, gl))
3970                                         {
3971                                                 continue;
3972                                         }
3973
3974                                         /* Execute the query */
3975                                         if (!PipelineStatisticsQueryUtilities::executeQuery(
3976                                                         current_query_target, m_qo_id, m_bo_qo_id, queryCallbackDrawCallHandler,
3977                                                         (PipelineStatisticsQueryTestFunctionalBase*)this, m_context.getRenderContext(), m_testCtx,
3978                                                         m_context.getContextInfo(), &run_result))
3979                                         {
3980                                                 m_testCtx.getLog()
3981                                                         << tcu::TestLog::Message << "Could not retrieve test run results for query target "
3982                                                                                                                 "["
3983                                                         << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target) << "]"
3984                                                         << tcu::TestLog::EndMessage;
3985
3986                                                 result = false;
3987                                         }
3988                                         else
3989                                         {
3990                                                 unsigned int                                                                             n_expected_values  = 0;
3991                                                 glw::GLuint64                                                                            expected_values[2] = { 0 };
3992                                                 PipelineStatisticsQueryUtilities::_verification_type verification_type =
3993                                                         PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_UNDEFINED;
3994
3995                                                 if (current_query_target == GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB)
3996                                                 {
3997                                                         n_expected_values  = 2;
3998                                                         expected_values[0] = m_n_primitives_emitted_by_gs;
3999                                                         expected_values[1] = m_n_primitives_emitted_by_gs;
4000                                                         verification_type  = PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_EXACT_MATCH;
4001
4002                                                         if (n_internal_iteration == 1)
4003                                                         {
4004                                                                 /* Multi-stream geometry shader case. Count in non-default vertex streams */
4005                                                                 for (unsigned int n_stream = 1; n_stream < m_n_streams_emitted_by_gs; ++n_stream)
4006                                                                 {
4007                                                                         expected_values[1] += (m_n_primitives_emitted_by_gs + n_stream);
4008                                                                 } /* for (non-default streams) */
4009                                                         }
4010
4011                                                         if (PipelineStatisticsQueryUtilities::isInstancedDrawCall(m_current_draw_call_type))
4012                                                         {
4013                                                                 expected_values[0] *= m_indirect_draw_call_primcount_argument;
4014                                                                 expected_values[1] *= m_indirect_draw_call_primcount_argument;
4015                                                         }
4016                                                 }
4017                                                 else
4018                                                 {
4019                                                         n_expected_values  = 1;
4020                                                         expected_values[0] = 1; /* as per test spec */
4021                                                         verification_type  = PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_EQUAL_OR_GREATER;
4022                                                 }
4023
4024                                                 /* Compare it against query result values */
4025                                                 result &= PipelineStatisticsQueryUtilities::verifyResultValues(
4026                                                         run_result, n_expected_values, expected_values,
4027                                                         m_qo_id != 0, /* should_check_qo_bo_values */
4028                                                         current_query_target, &m_current_draw_call_type, &m_current_primitive_type,
4029                                                         false, /* is_primitive_restart_enabled */
4030                                                         m_testCtx, verification_type);
4031
4032                                         } /* if (run results were obtained successfully) */
4033                                 }        /* for (all draw call types) */
4034                         }                 /* for (all internal iterations) */
4035                 }                         /* for (all geometry shader output primitive types) */
4036         }                                 /* for (all geometry shader input primitive types) */
4037         return result;
4038 }
4039
4040 /** Initializes all GL objects used by the test */
4041 void PipelineStatisticsQueryTestFunctional6::initObjects()
4042 {
4043         /* This test should not execute if we're not running at least a GL3.2 context */
4044         if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 2)))
4045         {
4046                 throw tcu::NotSupportedError("OpenGL 3.2+ is required to run this test.");
4047         }
4048 }
4049
4050 /** Tells whether the test instance should be executed for user-specified query target.
4051  *
4052  *  @param query_target Query target to be used for the call.
4053  *
4054  *  @return true  if @param query_target is either GL_GEOMETRY_SHADER_INVOCATIONS, or
4055  *                GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB.
4056  *          false otherwise.
4057  **/
4058 bool PipelineStatisticsQueryTestFunctional6::shouldExecuteForQueryTarget(glw::GLenum query_target)
4059 {
4060         return (query_target == GL_GEOMETRY_SHADER_INVOCATIONS ||
4061                         query_target == GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB);
4062 }
4063
4064 /** Constructor.
4065  *
4066  *  @param context Rendering context
4067  */
4068 PipelineStatisticsQueryTestFunctional7::PipelineStatisticsQueryTestFunctional7(deqp::Context& context)
4069         : PipelineStatisticsQueryTestFunctionalBase(context, "functional_fragment_shader_invocations",
4070                                                                                                 "Verifies GL_FRAGMENT_SHADER_INVOCATIONS_ARB queries "
4071                                                                                                 "work correctly.")
4072 {
4073         /* Left blank intentionally */
4074 }
4075
4076 /** Deinitializes all GL objects that were created during test execution. */
4077 void PipelineStatisticsQueryTestFunctional7::deinitObjects()
4078 {
4079         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4080
4081         if (m_po_id != 0)
4082         {
4083                 gl.deleteProgram(m_po_id);
4084
4085                 m_po_id = 0;
4086         }
4087 }
4088
4089 /** Executes a test iteration for user-specified query target.
4090  *
4091  *  @param current_query_target Pipeline statistics query target to execute the iteration
4092  *                              for.
4093  *
4094  *  @return true if the test passed for the iteration, false otherwise.
4095  **/
4096 bool PipelineStatisticsQueryTestFunctional7::executeTest(glw::GLenum current_query_target)
4097 {
4098         const glw::Functions&                                                                    gl             = m_context.getRenderContext().getFunctions();
4099         bool                                                                                                     result = true;
4100         PipelineStatisticsQueryUtilities::_test_execution_result run_result;
4101
4102         /* Sanity check: This method should only be called for GL_FRAGMENT_SHADER_INVOCATIONS_ARB query */
4103         DE_ASSERT(current_query_target == GL_FRAGMENT_SHADER_INVOCATIONS_ARB);
4104
4105         /* Set up VBO. */
4106         const unsigned int n_vertex_components = 2;
4107         const float                vertex_data[]           = { 0.0f,  0.75f, -0.75f, -0.75f, 0.75f, -0.75f, 0.3f, 0.7f,
4108                                                                   -0.4f, 0.2f,  0.6f,   -0.3f,  -0.3f, -0.7f,  0.0f, 0.0f };
4109         const unsigned int index_data[] = { 0, 2, 1, 3, 4, 5, 6, 7 };
4110
4111         m_indirect_draw_call_baseinstance_argument = 1;
4112         m_indirect_draw_call_basevertex_argument   = 1;
4113         m_indirect_draw_call_count_argument =
4114                 3; /* this value will be updated in the actual loop, so use anything for now */
4115         m_indirect_draw_call_first_argument             = 0;
4116         m_indirect_draw_call_primcount_argument = 4;
4117
4118         initFBO();
4119         initVBO(vertex_data, sizeof(vertex_data), index_data, sizeof(index_data), m_indirect_draw_call_count_argument,
4120                         m_indirect_draw_call_primcount_argument, m_indirect_draw_call_baseinstance_argument,
4121                         m_indirect_draw_call_first_argument, m_indirect_draw_call_basevertex_argument);
4122
4123         initVAO(n_vertex_components);
4124
4125         /* Iterate over all primitive types */
4126         for (int current_primitive_type_it = static_cast<int>(PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_FIRST);
4127                  current_primitive_type_it < static_cast<int>(PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_COUNT);
4128                  ++current_primitive_type_it)
4129         {
4130                 PipelineStatisticsQueryUtilities::_primitive_type current_primitive_type =
4131                         static_cast<PipelineStatisticsQueryUtilities::_primitive_type>(current_primitive_type_it);
4132                 /* Exclude 'patches' primitive type */
4133                 if (current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_PATCHES)
4134                 {
4135                         continue;
4136                 }
4137
4138                 m_current_primitive_type = current_primitive_type;
4139
4140                 /* Update 'count' argument so that we only use as many vertices as needed for current
4141                  * primitive type.
4142                  */
4143                 unsigned int count_argument_value =
4144                         PipelineStatisticsQueryUtilities::getNumberOfVerticesForPrimitiveType(m_current_primitive_type);
4145
4146                 m_indirect_draw_call_count_argument = count_argument_value;
4147
4148                 gl.bufferSubData(GL_ARRAY_BUFFER, m_vbo_indirect_arrays_argument_offset, sizeof(unsigned int),
4149                                                  &m_indirect_draw_call_count_argument);
4150                 gl.bufferSubData(GL_ARRAY_BUFFER, m_vbo_indirect_elements_argument_offset, sizeof(unsigned int),
4151                                                  &m_indirect_draw_call_count_argument);
4152
4153                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
4154
4155                 /* Iterate through all draw call types */
4156                 for (unsigned int n_draw_call_type = 0;
4157                          n_draw_call_type < PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_COUNT; ++n_draw_call_type)
4158                 {
4159                         m_current_draw_call_type = (PipelineStatisticsQueryUtilities::_draw_call_type)n_draw_call_type;
4160
4161                         /* Only continue if the draw call is supported by the context */
4162                         if (!PipelineStatisticsQueryUtilities::isDrawCallSupported(m_current_draw_call_type, gl))
4163                         {
4164                                 continue;
4165                         }
4166
4167                         /* Clear the buffers before we proceed */
4168                         gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4169                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
4170
4171                         /* Execute the query */
4172                         if (!PipelineStatisticsQueryUtilities::executeQuery(
4173                                         current_query_target, m_qo_id, m_bo_qo_id, queryCallbackDrawCallHandler,
4174                                         (PipelineStatisticsQueryTestFunctionalBase*)this, m_context.getRenderContext(), m_testCtx,
4175                                         m_context.getContextInfo(), &run_result))
4176                         {
4177                                 m_testCtx.getLog() << tcu::TestLog::Message << "Could not retrieve test run results for query target "
4178                                                                                                                            "["
4179                                                                    << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target) << "]"
4180                                                                    << tcu::TestLog::EndMessage;
4181
4182                                 result = false;
4183                         }
4184                         else
4185                         {
4186                                 static const glw::GLuint64 expected_value = 1; /* as per test spec */
4187
4188                                 /* Compare it against query result values */
4189                                 result &= PipelineStatisticsQueryUtilities::verifyResultValues(
4190                                         run_result, 1, &expected_value, m_qo_id != 0, /* should_check_qo_bo_values */
4191                                         current_query_target, &m_current_draw_call_type, &m_current_primitive_type,
4192                                         false, /* is_primitive_restart_enabled */
4193                                         m_testCtx, PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_EQUAL_OR_GREATER);
4194
4195                         } /* if (run results were obtained successfully) */
4196                 }        /* for (all draw call types) */
4197         }                 /* for (all primitive types) */
4198
4199         return result;
4200 }
4201
4202 /** Initializes all GL objects used by the test */
4203 void PipelineStatisticsQueryTestFunctional7::initObjects()
4204 {
4205         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4206
4207         buildProgram(DE_NULL,                                                                                              /* cs_body */
4208                                  PipelineStatisticsQueryUtilities::dummy_fs_code, DE_NULL, /* gs_body */
4209                                  DE_NULL,                                                                                                  /* tc_body */
4210                                  DE_NULL,                                                                                                  /* te_body */
4211                                  PipelineStatisticsQueryUtilities::dummy_vs_code);
4212
4213         gl.useProgram(m_po_id);
4214         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
4215 }
4216
4217 /** Tells whether the test instance should be executed for user-specified query target.
4218  *
4219  *  @param query_target Query target to be used for the call.
4220  *
4221  *  @return true  if @param query_target is GL_FRAGMENT_SHADER_INVOCATIONS_ARB.
4222  *          false otherwise.
4223  **/
4224 bool PipelineStatisticsQueryTestFunctional7::shouldExecuteForQueryTarget(glw::GLenum query_target)
4225 {
4226         return (query_target == GL_FRAGMENT_SHADER_INVOCATIONS_ARB);
4227 }
4228
4229 /** Constructor.
4230  *
4231  *  @param context Rendering context
4232  */
4233 PipelineStatisticsQueryTestFunctional8::PipelineStatisticsQueryTestFunctional8(deqp::Context& context)
4234         : PipelineStatisticsQueryTestFunctionalBase(context, "functional_compute_shader_invocations",
4235                                                                                                 "Verifies that GL_COMPUTE_SHADER_INVOCATIONS_ARB queries "
4236                                                                                                 "work correctly.")
4237         , m_bo_dispatch_compute_indirect_args_offset(0)
4238         , m_bo_id(0)
4239         , m_current_iteration(0)
4240 {
4241         /* Left blank intentionally */
4242 }
4243
4244 /** Deinitializes all GL objects that were created during test execution. */
4245 void PipelineStatisticsQueryTestFunctional8::deinitObjects()
4246 {
4247         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4248
4249         if (m_bo_id != 0)
4250         {
4251                 gl.deleteBuffers(1, &m_bo_id);
4252
4253                 m_bo_id = 0;
4254         }
4255 }
4256
4257 /** Executes a test iteration for user-specified query target.
4258  *
4259  *  @param current_query_target Pipeline statistics query target to execute the iteration
4260  *                              for.
4261  *
4262  *  @return true if the test passed for the iteration, false otherwise.
4263  **/
4264 bool PipelineStatisticsQueryTestFunctional8::executeTest(glw::GLenum current_query_target)
4265 {
4266         bool                                                                                                     result = true;
4267         PipelineStatisticsQueryUtilities::_test_execution_result run_result;
4268
4269         /* Sanity check: This method should only be called for
4270          * GL_COMPUTE_SHADER_INVOCATIONS_ARB queries. */
4271         DE_ASSERT(current_query_target == GL_COMPUTE_SHADER_INVOCATIONS_ARB);
4272
4273         /* This test needs to be run in two iterations:
4274          *
4275          * 1. glDispatchCompute() should be called.
4276          * 2. glDispatchComputeIndirect() should be called.
4277          *
4278          */
4279         for (m_current_iteration = 0; m_current_iteration < 2; /* as per description */
4280                  ++m_current_iteration)
4281         {
4282                 /* Execute the query */
4283                 if (!PipelineStatisticsQueryUtilities::executeQuery(
4284                                 current_query_target, m_qo_id, m_bo_qo_id, queryCallbackDispatchCallHandler, this,
4285                                 m_context.getRenderContext(), m_testCtx, m_context.getContextInfo(), &run_result))
4286                 {
4287                         m_testCtx.getLog() << tcu::TestLog::Message << "Could not retrieve test run results for query target "
4288                                                                                                                    "["
4289                                                            << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target) << "]"
4290                                                            << tcu::TestLog::EndMessage;
4291
4292                         result = false;
4293                 }
4294                 else
4295                 {
4296                         static const glw::GLuint64 expected_value = 1; /* as per test spec */
4297
4298                         /* Compare it against query result values */
4299                         result &= PipelineStatisticsQueryUtilities::verifyResultValues(
4300                                 run_result, 1, &expected_value, m_qo_id != 0,  /* should_check_qo_bo_values */
4301                                 current_query_target, DE_NULL, DE_NULL, false, /* is_primitive_restart_enabled */
4302                                 m_testCtx, PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_EQUAL_OR_GREATER);
4303                 } /* if (run results were obtained successfully) */
4304         }        /* for (both iterations) */
4305
4306         return result;
4307 }
4308
4309 /** Initializes all GL objects used by the test */
4310 void PipelineStatisticsQueryTestFunctional8::initObjects()
4311 {
4312         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4313
4314         buildProgram(PipelineStatisticsQueryUtilities::dummy_cs_code, DE_NULL, /* fs_body */
4315                                  DE_NULL,                                                                                                  /* gs_body */
4316                                  DE_NULL,                                                                                                  /* tc_body */
4317                                  DE_NULL,                                                                                                  /* te_body */
4318                                  DE_NULL);                                                                                                 /* vs_body */
4319
4320         gl.useProgram(m_po_id);
4321         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
4322
4323         /* Init BO to hold atomic counter data, as well as the indirect dispatch compute
4324          * draw call arguments */
4325         unsigned int       atomic_counter_value = 0;
4326         const unsigned int bo_size                              = sizeof(unsigned int) * (1 /* counter value */ + 3 /* draw call args */);
4327
4328         const unsigned int drawcall_args[] = {
4329                 1, /* num_groups_x */
4330                 1, /* num_groups_y */
4331                 1  /* num_groups_z */
4332         };
4333
4334         gl.genBuffers(1, &m_bo_id);
4335         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
4336
4337         gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
4338         gl.bindBuffer(GL_DISPATCH_INDIRECT_BUFFER, m_bo_id);
4339         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
4340
4341         gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, /* index */
4342                                           m_bo_id);
4343         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
4344
4345         gl.bufferData(GL_ARRAY_BUFFER, bo_size, DE_NULL, GL_STATIC_DRAW);
4346         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
4347
4348         gl.bufferSubData(GL_ARRAY_BUFFER, 0, /* offset */
4349                                          sizeof(unsigned int), &atomic_counter_value);
4350         gl.bufferSubData(GL_ARRAY_BUFFER, sizeof(unsigned int), /* offset */
4351                                          sizeof(drawcall_args), drawcall_args);
4352         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
4353
4354         /* Store rthe offset, at which the draw call args start */
4355         m_bo_dispatch_compute_indirect_args_offset = sizeof(unsigned int);
4356 }
4357
4358 /** Either issues a regular or indirect compute shader dispatch call, and then verifies
4359  *  the call has executed without any error being generated. The regular dispatch call
4360  *  will be executed if pInstance->m_current_iteration is equal to 0, otherwise the
4361  *  method will use the indirect version.
4362  *
4363  *  @param pInstance Pointer to a PipelineStatisticsQueryTestFunctional8 instance.
4364  */
4365 bool PipelineStatisticsQueryTestFunctional8::queryCallbackDispatchCallHandler(void* pInstance)
4366 {
4367         glw::GLenum                                                             error_code = GL_NO_ERROR;
4368         PipelineStatisticsQueryTestFunctional8* pThis     = (PipelineStatisticsQueryTestFunctional8*)pInstance;
4369         bool                                                                    result   = true;
4370         const glw::Functions&                                   gl                 = pThis->m_context.getRenderContext().getFunctions();
4371
4372         if (pThis->m_current_iteration == 0)
4373         {
4374                 gl.dispatchCompute(1,  /* num_groups_x */
4375                                                    1,  /* num_groups_y */
4376                                                    1); /* num_groups_z */
4377         }
4378         else
4379         {
4380                 gl.dispatchComputeIndirect(pThis->m_bo_dispatch_compute_indirect_args_offset);
4381         }
4382
4383         error_code = gl.getError();
4384         if (error_code != GL_NO_ERROR)
4385         {
4386                 pThis->m_testCtx.getLog() << tcu::TestLog::Message
4387                                                                   << ((pThis->m_current_iteration == 0) ? "glDispatchCompute()" :
4388                                                                                                                                                   "glDispatchComputeIndirect()")
4389                                                                   << " call failed with error code "
4390                                                                          "["
4391                                                                   << error_code << "]." << tcu::TestLog::EndMessage;
4392
4393                 result = false;
4394         }
4395
4396         return result;
4397 }
4398
4399 /** Tells whether the test instance should be executed for user-specified query target.
4400  *
4401  *  @param query_target Query target to be used for the call.
4402  *
4403  *  @return true  if @param query_target is GL_COMPUT_SHADER_INVOCATIONS_ARB.
4404  *          false otherwise.
4405  **/
4406 bool PipelineStatisticsQueryTestFunctional8::shouldExecuteForQueryTarget(glw::GLenum query_target)
4407 {
4408         return (query_target == GL_COMPUTE_SHADER_INVOCATIONS_ARB);
4409 }
4410
4411 /** Constructor.
4412  *
4413  *  @param context Rendering context.
4414  */
4415 PipelineStatisticsQueryTests::PipelineStatisticsQueryTests(deqp::Context& context)
4416         : TestCaseGroup(context, "pipeline_statistics_query_tests_ARB",
4417                                         "Contains conformance tests that verify GL implementation's support "
4418                                         "for GL_ARB_pipeline_statistics_query extension.")
4419 {
4420         /* Left blank intentionally */
4421 }
4422
4423 /** Initializes the test group contents. */
4424 void PipelineStatisticsQueryTests::init()
4425 {
4426         addChild(new PipelineStatisticsQueryTestAPICoverage1(m_context));
4427         addChild(new PipelineStatisticsQueryTestAPICoverage2(m_context));
4428         addChild(new PipelineStatisticsQueryTestFunctional1(m_context));
4429         addChild(new PipelineStatisticsQueryTestFunctional2(m_context));
4430         addChild(new PipelineStatisticsQueryTestFunctional3(m_context));
4431         addChild(new PipelineStatisticsQueryTestFunctional4(m_context));
4432         addChild(new PipelineStatisticsQueryTestFunctional5(m_context));
4433         addChild(new PipelineStatisticsQueryTestFunctional6(m_context));
4434         addChild(new PipelineStatisticsQueryTestFunctional7(m_context));
4435         addChild(new PipelineStatisticsQueryTestFunctional8(m_context));
4436 }
4437 } /* glcts namespace */