1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 */ /*-------------------------------------------------------------------*/
26 * \file gl4cPipelineStatisticsQueryTests.cpp
27 * \brief Implements conformance tests for GL_ARB_pipeline_statistics_query functionality
28 */ /*-------------------------------------------------------------------*/
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"
41 #ifndef GL_VERTICES_SUBMITTED_ARB
42 #define GL_VERTICES_SUBMITTED_ARB (0x82EE)
44 #ifndef GL_PRIMITIVES_SUBMITTED_ARB
45 #define GL_PRIMITIVES_SUBMITTED_ARB (0x82EF)
47 #ifndef GL_VERTEX_SHADER_INVOCATIONS_ARB
48 #define GL_VERTEX_SHADER_INVOCATIONS_ARB (0x82F0)
50 #ifndef GL_TESS_CONTROL_SHADER_PATCHES_ARB
51 #define GL_TESS_CONTROL_SHADER_PATCHES_ARB (0x82F1)
53 #ifndef GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB
54 #define GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB (0x82F2)
56 #ifndef GL_GEOMETRY_SHADER_INVOCATIONS
57 #define GL_GEOMETRY_SHADER_INVOCATIONS (0x887F)
59 #ifndef GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB
60 #define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB (0x82F3)
62 #ifndef GL_FRAGMENT_SHADER_INVOCATIONS_ARB
63 #define GL_FRAGMENT_SHADER_INVOCATIONS_ARB (0x82F4)
65 #ifndef GL_COMPUTE_SHADER_INVOCATIONS_ARB
66 #define GL_COMPUTE_SHADER_INVOCATIONS_ARB (0x82F5)
68 #ifndef GL_CLIPPING_INPUT_PRIMITIVES_ARB
69 #define GL_CLIPPING_INPUT_PRIMITIVES_ARB (0x82F6)
71 #ifndef GL_CLIPPING_OUTPUT_PRIMITIVES_ARB
72 #define GL_CLIPPING_OUTPUT_PRIMITIVES_ARB (0x82F7)
77 const char* PipelineStatisticsQueryUtilities::dummy_cs_code =
80 "layout(local_size_x=1, local_size_y = 1, local_size_z = 1) in;\n"
82 "layout(binding = 0) uniform atomic_uint test_counter;\n"
86 " atomicCounterIncrement(test_counter);\n"
88 const char* PipelineStatisticsQueryUtilities::dummy_fs_code = "#version 130\n"
94 " result = gl_FragCoord;\n"
96 const char* PipelineStatisticsQueryUtilities::dummy_tc_code =
99 "layout(vertices = 3) out;\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"
111 const char* PipelineStatisticsQueryUtilities::dummy_te_code =
114 "layout(triangles) in;\n"
118 " gl_Position = gl_TessCoord.xyxy * gl_in[gl_PrimitiveID].gl_Position;\n"
120 const char* PipelineStatisticsQueryUtilities::dummy_vs_code = "#version 130\n"
122 "in vec4 position;\n"
126 " gl_Position = position;\n"
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,
143 const unsigned int PipelineStatisticsQueryUtilities::n_query_targets = sizeof(query_targets) / sizeof(query_targets[0]);
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;
154 /** Buffer object size required to run the second functional test. */
155 const unsigned int PipelineStatisticsQueryTestFunctional2::bo_size = 32;
157 /** Builds body of a geometry shader, given user-specified properties.
159 * This function works in two different ways:
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
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,
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.
175 * @return Geometry shader body.
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)
182 DE_ASSERT(n_primitives_to_emit_in_stream0 >= 1);
183 DE_ASSERT(n_streams >= 1);
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.
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);
195 for (unsigned int n_stream = 0; n_stream < n_streams; ++n_stream)
197 n_max_vertices += n_vertices_required_for_gs_output * (n_primitives_to_emit_in_stream0 + n_stream);
198 } /* for (all streams) */
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.
203 gs_body_sstream << ((n_streams > 1) ? "#version 400" : "#version 150\n") << "\n"
205 << gs_input_string << ") in;\n"
207 << gs_output_string << ", max_vertices=" << n_max_vertices << ") out;\n";
209 /* If we need to define multiple streams, do it now */
212 gs_body_sstream << "\n";
214 for (unsigned int n_stream = 0; n_stream < n_streams; ++n_stream)
216 gs_body_sstream << "layout(stream = " << n_stream << ") out vec4 out_stream" << n_stream << ";\n";
217 } /* for (all streams) */
218 } /* if (n_streams > 1) */
220 /* Contine forming actual body */
221 gs_body_sstream << "\n"
225 /* Emit primitives */
226 const unsigned int n_output_primitive_vertices =
227 PipelineStatisticsQueryUtilities::getNumberOfVerticesForGSOutput(gs_output);
229 for (unsigned int n_stream = 0; n_stream < n_streams; ++n_stream)
231 const unsigned int n_primitives_to_emit = n_primitives_to_emit_in_stream0 + n_stream;
233 for (unsigned int n_primitive = 0; n_primitive < n_primitives_to_emit; ++n_primitive)
235 for (unsigned int n_vertex = 0; n_vertex < n_output_primitive_vertices; ++n_vertex)
237 gs_body_sstream << " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n";
241 gs_body_sstream << " EmitVertex();\n";
245 gs_body_sstream << " EmitStreamVertex(" << n_stream << ");\n";
251 gs_body_sstream << " EndPrimitive();\n";
255 gs_body_sstream << " EndStreamPrimitive(" << n_stream << ");\n";
257 } /* for (all primitives the caller wants the shader to emit) */
258 } /* for (all streams) */
260 gs_body_sstream << "}\n";
262 return gs_body_sstream.str();
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.
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
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
288 * @return true if the test executed successfully, and @param out_result 's fields
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)
299 glw::GLenum error_code = GL_NO_ERROR;
300 const glw::Functions& gl = render_context.getFunctions();
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;
308 gl.getQueryiv(query_type, GL_QUERY_COUNTER_BITS, &n_query_bits);
310 error_code = gl.getError();
311 if (error_code != GL_NO_ERROR)
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;
321 if (n_query_bits == 0)
323 test_context.getLog() << tcu::TestLog::Message << "Skipping "
325 << PipelineStatisticsQueryUtilities::getStringForEnum(query_type)
327 ": zero bits available for counter storage"
328 << tcu::TestLog::EndMessage;
333 /* Start the query */
334 gl.beginQuery(query_type, qo_id);
336 error_code = gl.getError();
337 if (error_code != GL_NO_ERROR)
339 test_context.getLog() << tcu::TestLog::Message
340 << "A valid glBeginQuery() call generated the following error code:"
342 << error_code << "]" << tcu::TestLog::EndMessage;
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)
351 gl.bindBuffer(GL_QUERY_BUFFER, qo_bo_id);
353 error_code = gl.getError();
354 if (error_code != GL_NO_ERROR)
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:"
360 << error_code << "]" << tcu::TestLog::EndMessage;
362 /* Stop the query before we leave */
363 gl.endQuery(query_type);
366 } /* if (buffer binding operation failed) */
367 } /* if (GL_ARB_query_buffer_object extension is supported and the supplied QO BO id
371 /* Reset the QO BO id, so that we can skip the checks later */
375 /* Perform the draw calls, if any supplied call-back function pointer was supplied
377 if (pfn_draw != DE_NULL)
379 pfn_draw(draw_user_arg);
383 gl.endQuery(query_type);
385 error_code = gl.getError();
386 if (error_code != GL_NO_ERROR)
388 test_context.getLog() << tcu::TestLog::Message << "glEndQuery() call failed with error code"
390 << error_code << "]" << tcu::TestLog::EndMessage;
393 } /* if (glEndQuery() call failed) */
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:
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
403 const unsigned int iteration_index_wo_qo_bo = 0;
404 const unsigned int iteration_index_with_qo_bo = 1;
406 for (unsigned int n_iteration = 0; n_iteration < 2; /* as per description */
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;
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)
426 /* Determine the offsets we should use for the getter calls */
427 if (n_iteration == iteration_index_wo_qo_bo)
429 offset_int = &result_int;
430 offset_int64 = &result_int64;
431 offset_uint = &result_uint;
432 offset_uint64 = &result_uint64;
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;
442 /* Bind the QO BO if we need to use it for the getter calls */
443 if (n_iteration == iteration_index_with_qo_bo)
445 gl.bindBuffer(GL_QUERY_BUFFER, qo_bo_id);
449 gl.bindBuffer(GL_QUERY_BUFFER, 0 /* buffer */);
452 error_code = gl.getError();
453 if (error_code != GL_NO_ERROR)
455 test_context.getLog() << tcu::TestLog::Message
456 << "glBindBuffer() call failed for GL_QUERY_BUFFER target with error "
458 << error_code << "]" << tcu::TestLog::EndMessage;
463 /* Issue the getter calls.
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)))
468 gl.getQueryObjecti64v(qo_id, GL_QUERY_RESULT, offset_int64);
470 error_code = gl.getError();
471 if (error_code != GL_NO_ERROR)
473 test_context.getLog() << tcu::TestLog::Message << "glGetQueryObjecti64v() call failed with error "
475 << error_code << "]" << tcu::TestLog::EndMessage;
480 result_int64_written = true;
484 result_int64_written = false;
487 gl.getQueryObjectiv(qo_id, GL_QUERY_RESULT, offset_int);
489 error_code = gl.getError();
490 if (error_code != GL_NO_ERROR)
492 test_context.getLog() << tcu::TestLog::Message << "glGetQueryObjectiv() call failed with error "
494 << error_code << "]" << tcu::TestLog::EndMessage;
499 if (glu::contextSupports(render_context.getType(), glu::ApiType::core(3, 3)))
501 gl.getQueryObjectui64v(qo_id, GL_QUERY_RESULT, offset_uint64);
503 error_code = gl.getError();
504 if (error_code != GL_NO_ERROR)
506 test_context.getLog() << tcu::TestLog::Message << "glGetQueryObjectui64v() call failed with error "
508 << error_code << "]" << tcu::TestLog::EndMessage;
513 result_uint64_written = true;
517 result_uint64_written = false;
520 gl.getQueryObjectuiv(qo_id, GL_QUERY_RESULT, offset_uint);
522 error_code = gl.getError();
523 if (error_code != GL_NO_ERROR)
525 test_context.getLog() << tcu::TestLog::Message << "glGetQueryObjectuiv() call failed with error "
527 << error_code << "]" << tcu::TestLog::EndMessage;
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)
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);
539 error_code = gl.getError();
541 if (error_code != GL_NO_ERROR || bo_data_ptr == NULL)
543 test_context.getLog() << tcu::TestLog::Message << "QO BO mapping failed with error "
545 << error_code << "] and data ptr returned:"
547 << bo_data_ptr << "]" << tcu::TestLog::EndMessage;
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);
559 gl.unmapBuffer(GL_QUERY_BUFFER);
561 error_code = gl.getError();
562 if (error_code != GL_NO_ERROR)
564 test_context.getLog() << tcu::TestLog::Message << "QO BO unmapping failed with error "
566 << error_code << "]" << tcu::TestLog::EndMessage;
570 } /* if (QO BO iteration) */
572 /* Store the retrieved data in user-provided location */
573 if (n_iteration == iteration_index_with_qo_bo)
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;
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;
588 out_result->int64_written = result_int64_written;
589 out_result->uint64_written = result_uint64_written;
590 } /* for (both iterations) */
594 /** Retrieves a GLenum value corresponding to internal _primitive_type
597 * @param primitive_type Internal primitive type to use for the getter call.
599 * @return Corresponding GL value that can be used for the draw calls, or
600 * GL_NONE if the conversion failed.
603 glw::GLenum PipelineStatisticsQueryUtilities::getEnumForPrimitiveType(_primitive_type primitive_type)
605 glw::GLenum result = GL_NONE;
607 switch (primitive_type)
609 case PRIMITIVE_TYPE_POINTS:
612 case PRIMITIVE_TYPE_LINE_LOOP:
613 result = GL_LINE_LOOP;
615 case PRIMITIVE_TYPE_LINE_STRIP:
616 result = GL_LINE_STRIP;
618 case PRIMITIVE_TYPE_LINES:
621 case PRIMITIVE_TYPE_LINES_ADJACENCY:
622 result = GL_LINES_ADJACENCY;
624 case PRIMITIVE_TYPE_PATCHES:
627 case PRIMITIVE_TYPE_TRIANGLE_FAN:
628 result = GL_TRIANGLE_FAN;
630 case PRIMITIVE_TYPE_TRIANGLE_STRIP:
631 result = GL_TRIANGLE_STRIP;
633 case PRIMITIVE_TYPE_TRIANGLES:
634 result = GL_TRIANGLES;
636 case PRIMITIVE_TYPE_TRIANGLES_ADJACENCY:
637 result = GL_TRIANGLES_ADJACENCY;
642 TCU_FAIL("Unrecognized primitive type");
644 } /* switch (primitive_type) */
649 /** Retrieves a human-readable name for a _geometry_shader_input value.
651 * @param gs_input Internal _geometry_shader_input value to use for
654 * @return Human-readable string or empty string, if the conversion failed.
657 std::string PipelineStatisticsQueryUtilities::getGLSLStringForGSInput(_geometry_shader_input gs_input)
663 case GEOMETRY_SHADER_INPUT_POINTS:
666 case GEOMETRY_SHADER_INPUT_LINES:
669 case GEOMETRY_SHADER_INPUT_LINES_ADJACENCY:
670 result = "lines_adjacency";
672 case GEOMETRY_SHADER_INPUT_TRIANGLES:
673 result = "triangles";
675 case GEOMETRY_SHADER_INPUT_TRIANGLES_ADJACENCY:
676 result = "triangles_adjacency";
681 TCU_FAIL("Unrecognized geometry shader input enum");
683 } /* switch (gs_input) */
688 /** Retrieves a human-readable string for a _geometry_shader_output value.
690 * @param gs_output _geometry_shader_output value to use for the conversion.
692 * @return Requested value or empty string, if the value was not recognized.
695 std::string PipelineStatisticsQueryUtilities::getGLSLStringForGSOutput(_geometry_shader_output gs_output)
701 case GEOMETRY_SHADER_OUTPUT_POINTS:
704 case GEOMETRY_SHADER_OUTPUT_LINE_STRIP:
705 result = "line_strip";
707 case GEOMETRY_SHADER_OUTPUT_TRIANGLE_STRIP:
708 result = "triangle_strip";
713 TCU_FAIL("Unrecognized geometry shader output enum");
715 } /* switch (gs_output) */
720 /** Number of vertices the geometry shader can access on the input, if the shader
721 * uses @param gs_input input primitive type.
723 * @param gs_input Geometry shader input to use for the query.
725 * @return Requested value or 0 if @param gs_input was not recognized.
727 unsigned int PipelineStatisticsQueryUtilities::getNumberOfVerticesForGSInput(_geometry_shader_input gs_input)
729 unsigned int result = 0;
733 case GEOMETRY_SHADER_INPUT_POINTS:
736 case GEOMETRY_SHADER_INPUT_LINES:
739 case GEOMETRY_SHADER_INPUT_LINES_ADJACENCY:
742 case GEOMETRY_SHADER_INPUT_TRIANGLES:
745 case GEOMETRY_SHADER_INPUT_TRIANGLES_ADJACENCY:
751 TCU_FAIL("Unrecognized geometry shader input type");
753 } /* switch (gs_input) */
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.
762 * @param gs_output Primitive type to be outputted by the geometry shader.
764 * @return As per description, or 0 if @param gs_output was not recognized.
766 unsigned int PipelineStatisticsQueryUtilities::getNumberOfVerticesForGSOutput(_geometry_shader_output gs_output)
768 unsigned int n_result_vertices = 0;
772 case GEOMETRY_SHADER_OUTPUT_LINE_STRIP:
773 n_result_vertices = 2;
775 case GEOMETRY_SHADER_OUTPUT_POINTS:
776 n_result_vertices = 1;
778 case GEOMETRY_SHADER_OUTPUT_TRIANGLE_STRIP:
779 n_result_vertices = 3;
783 TCU_FAIL("Unrecognized geometry shader output type");
787 return n_result_vertices;
790 /** Returns the number of vertices a single primitive of type described by @param primitive_type
793 * @param primitive_type Primitive type to use for the query.
795 * @return Result value, or 0 if @param primive_type was not recognized.
797 unsigned int PipelineStatisticsQueryUtilities::getNumberOfVerticesForPrimitiveType(_primitive_type primitive_type)
799 unsigned int result = 0;
801 switch (primitive_type)
803 case PRIMITIVE_TYPE_POINTS:
806 case PRIMITIVE_TYPE_LINE_LOOP: /* fall-through */
807 case PRIMITIVE_TYPE_LINE_STRIP: /* fall-through */
808 case PRIMITIVE_TYPE_LINES:
811 case PRIMITIVE_TYPE_TRIANGLE_FAN: /* fall-through */
812 case PRIMITIVE_TYPE_TRIANGLE_STRIP: /* fall-through */
813 case PRIMITIVE_TYPE_TRIANGLES:
816 case PRIMITIVE_TYPE_LINES_ADJACENCY:
819 case PRIMITIVE_TYPE_TRIANGLES_ADJACENCY:
824 TCU_FAIL("Unrecognized primitive type");
825 } /* switch (primitive_type) */
830 /** Converts user-specified _geometry_shader_input value to a _primitive_type value.
832 * @param gs_input Input value for the conversion.
834 * @return Requested value, or PRIMITIVE_TYPE_COUNT if the user-specified value
837 PipelineStatisticsQueryUtilities::_primitive_type PipelineStatisticsQueryUtilities::getPrimitiveTypeFromGSInput(
838 _geometry_shader_input gs_input)
840 _primitive_type result = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_COUNT;
844 case GEOMETRY_SHADER_INPUT_POINTS:
845 result = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_POINTS;
847 case GEOMETRY_SHADER_INPUT_LINES:
848 result = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES;
850 case GEOMETRY_SHADER_INPUT_LINES_ADJACENCY:
851 result = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES_ADJACENCY;
853 case GEOMETRY_SHADER_INPUT_TRIANGLES:
854 result = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES;
856 case GEOMETRY_SHADER_INPUT_TRIANGLES_ADJACENCY:
857 result = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES_ADJACENCY;
862 TCU_FAIL("Unrecognized geometry shader input enum");
864 } /* switch (gs_input) */
869 /** Converts user-specified _draw_call_type value to a human-readable string.
871 * @param draw_call_type Input value to use for the conversion.
873 * @return Human-readable string, or "[?]" (without the quotation marks) if
874 * the input value was not recognized.
876 std::string PipelineStatisticsQueryUtilities::getStringForDrawCallType(_draw_call_type draw_call_type)
878 std::string result = "[?]";
880 switch (draw_call_type)
882 case DRAW_CALL_TYPE_GLDRAWARRAYS:
883 result = "glDrawArrays()";
885 case DRAW_CALL_TYPE_GLDRAWARRAYSINDIRECT:
886 result = "glDrawArraysIndirect()";
888 case DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCED:
889 result = "glDrawArraysInstanced()";
891 case DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCEDBASEINSTANCE:
892 result = "glDrawArraysInstancedBaseInstance()";
894 case DRAW_CALL_TYPE_GLDRAWELEMENTS:
895 result = "glDrawElements()";
897 case DRAW_CALL_TYPE_GLDRAWELEMENTSBASEVERTEX:
898 result = "glDrawElementsBaseVertex()";
900 case DRAW_CALL_TYPE_GLDRAWELEMENTSINDIRECT:
901 result = "glDrawElementsIndirect()";
903 case DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCED:
904 result = "glDrawElementsInstanced()";
906 case DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEINSTANCE:
907 result = "glDrawElementsInstancedBaseInstance()";
909 case DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE:
910 result = "glDrawElementsInstancedBaseVertexBaseInstance()";
912 case DRAW_CALL_TYPE_GLDRAWRANGEELEMENTS:
913 result = "glDrawRangeElements()";
915 case DRAW_CALL_TYPE_GLDRAWRANGEELEMENTSBASEVERTEX:
916 result = "glDrawRangeElementsBaseVertex()";
926 /** Converts a GL enum value expressing a pipeline statistics query type
927 * into a human-readable string.
929 * @param value Input value to use for the conversion.
931 * @return Human-readable string or "[?]" (without the quotation marks)
932 * if the input value was not recognized.
934 std::string PipelineStatisticsQueryUtilities::getStringForEnum(glw::GLenum value)
936 std::string result = "[?]";
940 case GL_CLIPPING_INPUT_PRIMITIVES_ARB:
941 result = "GL_CLIPPING_INPUT_PRIMITIVES_ARB";
943 case GL_CLIPPING_OUTPUT_PRIMITIVES_ARB:
944 result = "GL_CLIPPING_OUTPUT_PRIMITIVES_ARB";
946 case GL_COMPUTE_SHADER_INVOCATIONS_ARB:
947 result = "GL_COMPUTE_SHADER_INVOCATIONS_ARB";
949 case GL_FRAGMENT_SHADER_INVOCATIONS_ARB:
950 result = "GL_FRAGMENT_SHADER_INVOCATIONS_ARB";
952 case GL_GEOMETRY_SHADER_INVOCATIONS:
953 result = "GL_GEOMETRY_SHADER_INVOCATIONS";
955 case GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB:
956 result = "GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB";
958 case GL_PRIMITIVES_SUBMITTED_ARB:
959 result = "GL_PRIMITIVES_SUBMITTED_ARB";
961 case GL_TESS_CONTROL_SHADER_PATCHES_ARB:
962 result = "GL_TESS_CONTROL_SHADER_PATCHES_ARB";
964 case GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB:
965 result = "GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB";
967 case GL_VERTEX_SHADER_INVOCATIONS_ARB:
968 result = "GL_VERTEX_SHADER_INVOCATIONS_ARB";
970 case GL_VERTICES_SUBMITTED_ARB:
971 result = "GL_VERTICES_SUBMITTED_ARB";
973 } /* switch (value) */
978 /** Converts a _primitive_type value into a human-readable string.
980 * @param primitive_type Input value to use for the conversion.
982 * @return Requested string or "[?]" (without the quotation marks)
983 * if the input value was not recognized.
985 std::string PipelineStatisticsQueryUtilities::getStringForPrimitiveType(_primitive_type primitive_type)
987 std::string result = "[?]";
989 switch (primitive_type)
991 case PRIMITIVE_TYPE_POINTS:
992 result = "GL_POINTS";
994 case PRIMITIVE_TYPE_LINE_LOOP:
995 result = "GL_LINE_LOOP";
997 case PRIMITIVE_TYPE_LINE_STRIP:
998 result = "GL_LINE_STRIP";
1000 case PRIMITIVE_TYPE_LINES:
1001 result = "GL_LINES";
1003 case PRIMITIVE_TYPE_LINES_ADJACENCY:
1004 result = "GL_LINES_ADJACENCY";
1006 case PRIMITIVE_TYPE_PATCHES:
1007 result = "GL_PATCHES";
1009 case PRIMITIVE_TYPE_TRIANGLE_FAN:
1010 result = "GL_TRIANGLE_FAN";
1012 case PRIMITIVE_TYPE_TRIANGLE_STRIP:
1013 result = "GL_TRIANGLE_STRIP";
1015 case PRIMITIVE_TYPE_TRIANGLES:
1016 result = "GL_TRIANGLES";
1018 case PRIMITIVE_TYPE_TRIANGLES_ADJACENCY:
1019 result = "GL_TRIANGLES_ADJACENCY";
1029 /** Tells if it is safe to use a specific draw call type.
1031 * @param draw_call Draw call type to use for the query.
1033 * @return True if corresponding GL entry-point is available.
1035 bool PipelineStatisticsQueryUtilities::isDrawCallSupported(_draw_call_type draw_call, const glw::Functions& gl)
1038 bool result = false;
1042 case DRAW_CALL_TYPE_GLDRAWARRAYS:
1043 result = (gl.drawArrays != DE_NULL);
1045 case DRAW_CALL_TYPE_GLDRAWARRAYSINDIRECT:
1046 result = (gl.drawArraysIndirect != DE_NULL);
1048 case DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCED:
1049 result = (gl.drawArraysInstanced != DE_NULL);
1051 case DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCEDBASEINSTANCE:
1052 result = (gl.drawArraysInstancedBaseInstance != DE_NULL);
1054 case DRAW_CALL_TYPE_GLDRAWELEMENTS:
1055 result = (gl.drawElements != DE_NULL);
1057 case DRAW_CALL_TYPE_GLDRAWELEMENTSBASEVERTEX:
1058 result = (gl.drawElementsBaseVertex != DE_NULL);
1060 case DRAW_CALL_TYPE_GLDRAWELEMENTSINDIRECT:
1061 result = (gl.drawElementsIndirect != DE_NULL);
1063 case DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCED:
1064 result = (gl.drawElementsInstanced != DE_NULL);
1066 case DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEINSTANCE:
1067 result = (gl.drawElementsInstancedBaseInstance != DE_NULL);
1069 case DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE:
1070 result = (gl.drawElementsInstancedBaseVertexBaseInstance != DE_NULL);
1072 case DRAW_CALL_TYPE_GLDRAWRANGEELEMENTS:
1073 result = (gl.drawRangeElements != DE_NULL);
1075 case DRAW_CALL_TYPE_GLDRAWRANGEELEMENTSBASEVERTEX:
1076 result = (gl.drawRangeElementsBaseVertex != DE_NULL);
1081 TCU_FAIL("Unrecognized draw call type");
1083 } /* switch (draw_call) */
1088 /** Tells if user-specified draw call type is an instanced draw call.
1090 * @param draw_call Input value to use for the conversion.
1092 * @return true if @param draw_call corresponds to an instanced draw call,
1095 bool PipelineStatisticsQueryUtilities::isInstancedDrawCall(_draw_call_type draw_call)
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);
1109 /** Tells if the running GL implementation supports user-specified pipeline
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.
1117 * @return true if the query is supported, false otherwise. This method will return
1118 * true for unrecognized enums.
1120 bool PipelineStatisticsQueryUtilities::isQuerySupported(glw::GLenum value, const glu::ContextInfo& context_info,
1121 const glu::RenderContext& render_context)
1127 case GL_GEOMETRY_SHADER_INVOCATIONS:
1128 case GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB:
1130 if (!glu::contextSupports(render_context.getType(), glu::ApiType::core(3, 2)) &&
1131 !context_info.isExtensionSupported("GL_ARB_geometry_shader4"))
1139 case GL_TESS_CONTROL_SHADER_PATCHES_ARB:
1140 case GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB:
1142 if (!glu::contextSupports(render_context.getType(), glu::ApiType::compatibility(4, 0)) &&
1143 !context_info.isExtensionSupported("GL_ARB_tessellation_shader"))
1151 case GL_COMPUTE_SHADER_INVOCATIONS_ARB:
1153 if (!glu::contextSupports(render_context.getType(), glu::ApiType::core(4, 3)) &&
1154 !context_info.isExtensionSupported("GL_ARB_compute_shader"))
1161 } /* switch (value) */
1166 /** Takes a filled _test_execution_result structure and performs the validation
1167 * of the embedded data.
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
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
1189 * @return true if the result values were found valid, false otherwise.
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)
1199 /* Make sure all values are set to one of the expected values */
1200 std::string draw_call_name;
1201 std::string primitive_name;
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;
1212 if (draw_call_type_ptr != DE_NULL)
1214 draw_call_name = getStringForDrawCallType(*draw_call_type_ptr);
1218 draw_call_name = "(does not apply)";
1221 if (primitive_type_ptr != DE_NULL)
1223 primitive_name = getStringForPrimitiveType(*primitive_type_ptr);
1227 primitive_name = "(does not apply)";
1230 for (unsigned int n_expected_value = 0; n_expected_value < n_expected_values; ++n_expected_value)
1232 glw::GLuint64 expected_value = 0;
1234 expected_value = expected_values[n_expected_value];
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))
1241 is_result_int_valid = true;
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)))
1249 is_result_int64_valid = true;
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))
1257 is_result_uint_valid = true;
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)))
1264 is_result_uint64_valid = true;
1267 if (should_check_qo_bo_values)
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))
1274 is_result_qo_int_valid = true;
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)))
1282 is_result_qo_int64_valid = true;
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))
1290 is_result_qo_uint_valid = true;
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)))
1298 is_result_qo_uint64_valid = true;
1300 } /* if (should_check_qo_bo_values) */
1301 } /* for (both expected values) */
1303 if (!is_result_int_valid)
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);
1309 test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1314 if (run_result.int64_written && !is_result_int64_valid)
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);
1320 test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1325 if (!is_result_uint_valid)
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);
1331 test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1336 if (run_result.uint64_written && !is_result_uint64_valid)
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);
1342 test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1347 if (should_check_qo_bo_values)
1349 if (!is_result_qo_int_valid)
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);
1355 test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1360 if (run_result.int64_written && !is_result_qo_int64_valid)
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);
1366 test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1371 if (!is_result_qo_uint_valid)
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);
1377 test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1382 if (run_result.uint64_written && !is_result_qo_uint64_valid)
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);
1388 test_context.getLog() << tcu::TestLog::Message << log.c_str() << tcu::TestLog::EndMessage;
1399 * @param context Rendering context
1400 * @param name Test name
1401 * @param description Test description
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 "
1410 /* Left blank intentionally */
1413 /** Deinitializes all GL objects that were created during test execution. */
1414 void PipelineStatisticsQueryTestAPICoverage1::deinit()
1416 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1420 gl.deleteQueries(1, &m_qo_id);
1426 /** Executes test iteration.
1428 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1430 tcu::TestNode::IterateResult PipelineStatisticsQueryTestAPICoverage1::iterate()
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();
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"))
1441 throw tcu::NotSupportedError("GL_ARB_pipeline_statistics_query extension is not supported");
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();
1448 for (unsigned int n_current_item = 0; n_current_item < PipelineStatisticsQueryUtilities::n_query_targets;
1451 glw::GLenum current_pq = PipelineStatisticsQueryUtilities::query_targets[n_current_item];
1453 /* Make sure the query is supported */
1454 if (!PipelineStatisticsQueryUtilities::isQuerySupported(current_pq, context_info, render_context))
1459 /* Generate a new query object */
1460 gl.genQueries(1, &m_qo_id);
1461 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries() call failed.");
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.");
1467 gl.endQuery(current_pq);
1468 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery() call failed.");
1470 for (unsigned int n_different_item = 0; n_different_item < PipelineStatisticsQueryUtilities::n_query_targets;
1473 glw::GLenum different_pq = PipelineStatisticsQueryUtilities::query_targets[n_different_item];
1475 if (current_pq == different_pq)
1477 /* Skip valid iterations */
1481 /* Make sure the other query type is supported */
1482 if (!PipelineStatisticsQueryUtilities::isQuerySupported(different_pq, context_info, render_context))
1487 /* Try using a different type for the same object */
1488 glw::GLenum error_code = GL_NO_ERROR;
1490 gl.beginQuery(different_pq, m_qo_id);
1492 /* Has GL_INVALID_OPERATION error been generated? */
1493 error_code = gl.getError();
1495 if (error_code != GL_INVALID_OPERATION)
1497 m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected error code "
1499 << error_code << "]"
1500 " generated when using glBeginQuery() for a query object of type "
1502 << PipelineStatisticsQueryUtilities::getStringForEnum(current_pq)
1504 ", when used for a query type "
1506 << PipelineStatisticsQueryUtilities::getStringForEnum(different_pq) << "]"
1507 << tcu::TestLog::EndMessage;
1512 if (error_code == GL_NO_ERROR)
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");
1519 } /* for (all query object types) */
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) */
1529 /* Test case passed */
1530 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1534 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1542 * @param context Rendering context
1543 * @param name Test name
1544 * @param description Test description
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.")
1552 /* Left blank intentionally */
1555 /** Deinitializes all GL objects that were created during test execution. */
1556 void PipelineStatisticsQueryTestAPICoverage2::deinit()
1558 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1562 gl.deleteQueries(1, &m_qo_id);
1568 /** Executes test iteration.
1570 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1572 tcu::TestNode::IterateResult PipelineStatisticsQueryTestAPICoverage2::iterate()
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();
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"))
1585 throw tcu::NotSupportedError("GL_ARB_pipeline_statistics_query extension is not supported");
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.");
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]);
1597 for (unsigned int n_query_type = 0; n_query_type < n_query_types; ++n_query_type)
1599 glw::GLenum query_type = query_types[n_query_type];
1601 if (!PipelineStatisticsQueryUtilities::isQuerySupported(query_type, context_info, render_context))
1603 gl.beginQuery(query_type, m_qo_id);
1605 error_code = gl.getError();
1606 if (error_code != GL_INVALID_ENUM)
1608 m_testCtx.getLog() << tcu::TestLog::Message
1609 << "glBeginQuery() call did not generate a GL_INVALID_ENUM error "
1610 "for an unsupported query type "
1612 << PipelineStatisticsQueryUtilities::getStringForEnum(query_type) << "]"
1613 << tcu::TestLog::EndMessage;
1618 /* If the query succeeded, stop it before we continue */
1619 if (error_code == GL_NO_ERROR)
1621 gl.endQuery(query_type);
1623 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery() call failed.");
1625 } /* if (query is not supported) */
1626 } /* for (all query types) */
1630 /* Test case passed */
1631 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1635 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1643 * @param context Rendering context
1644 * @param name Test name
1645 * @param description Test description
1647 PipelineStatisticsQueryTestFunctionalBase::PipelineStatisticsQueryTestFunctionalBase(deqp::Context& context,
1649 const char* description)
1650 : TestCase(context, name, description)
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)
1669 /* Left blank intentionally */
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.
1676 * ID of the initialized program object is stored in m_po_id.
1678 * @param cs_body Compute shader body. If not NULL, all other arguments must
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.
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)
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;
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)));
1705 /* Any existing program object already initialzied? Purge it before we continue */
1708 gl.deleteProgram(m_po_id);
1709 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram() call failed.");
1714 /* Generate all shader objects we'll need to use for the program */
1715 if (cs_body != DE_NULL)
1717 cs_id = gl.createShader(GL_COMPUTE_SHADER);
1720 if (fs_body != DE_NULL)
1722 fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1725 if (gs_body != DE_NULL)
1727 gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1730 if (tc_body != DE_NULL)
1732 tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
1735 if (te_body != DE_NULL)
1737 te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
1740 if (vs_body != DE_NULL)
1742 vs_id = gl.createShader(GL_VERTEX_SHADER);
1745 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1747 /* Create a program object */
1748 m_po_id = gl.createProgram();
1750 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1752 /* Set source code of the shaders we've created */
1755 gl.shaderSource(cs_id, 1, /* count */
1756 &cs_body, DE_NULL); /* length */
1761 gl.shaderSource(fs_id, 1, /* count */
1762 &fs_body, DE_NULL); /* length */
1767 gl.shaderSource(gs_id, 1, /* count */
1768 &gs_body, DE_NULL); /* length */
1773 gl.shaderSource(tc_id, 1, /* count */
1774 &tc_body, DE_NULL); /* length */
1779 gl.shaderSource(te_id, 1, /* count */
1780 &te_body, DE_NULL); /* length */
1785 gl.shaderSource(vs_id, 1, /* count */
1786 &vs_body, DE_NULL); /* length */
1789 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
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]);
1795 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
1797 glw::GLint compile_status = GL_FALSE;
1798 glw::GLuint so_id = so_ids[n_so_id];
1802 gl.compileShader(so_id);
1803 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
1805 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
1806 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
1808 if (compile_status == GL_FALSE)
1810 TCU_FAIL("Shader compilation failed.");
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) */
1818 /* Link the program object */
1819 glw::GLint link_status = GL_FALSE;
1821 gl.linkProgram(m_po_id);
1822 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
1824 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
1825 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
1827 if (link_status == GL_FALSE)
1829 TCU_FAIL("Program linking failed.");
1832 /* Release the shader objects - we no longer need them */
1835 gl.deleteShader(cs_id);
1840 gl.deleteShader(fs_id);
1845 gl.deleteShader(gs_id);
1850 gl.deleteShader(tc_id);
1855 gl.deleteShader(te_id);
1860 gl.deleteShader(vs_id);
1863 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call(s) failed.");
1866 /** Deinitializes all GL objects that were created during test execution.
1867 * Also calls the inheriting object's deinitObjects() method.
1869 void PipelineStatisticsQueryTestFunctionalBase::deinit()
1871 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1873 if (m_bo_qo_id != 0)
1875 gl.deleteBuffers(1, &m_bo_qo_id);
1882 gl.deleteFramebuffers(1, &m_fbo_id);
1889 gl.deleteProgram(m_po_id);
1896 gl.deleteQueries(1, &m_qo_id);
1903 gl.deleteTextures(1, &m_to_id);
1910 gl.deleteVertexArrays(1, &m_vao_id);
1917 gl.deleteBuffers(1, &m_vbo_id);
1925 /** Dummy method that should be overloaded by inheriting methods.
1927 * The method can be thought as of a placeholder for code that deinitializes
1928 * test-specific GL objects.
1930 void PipelineStatisticsQueryTestFunctionalBase::deinitObjects()
1932 /* Left blank intentionally - this method should be overloaded by deriving
1937 /** Initializes a framebuffer object that can be used by inheriting tests
1938 * for holding rendered data.
1940 void PipelineStatisticsQueryTestFunctionalBase::initFBO()
1942 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1944 /* Set up a framebuffer object */
1945 gl.genFramebuffers(1, &m_fbo_id);
1946 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
1948 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
1949 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
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.");
1955 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
1956 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
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.");
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.");
1966 gl.viewport(0, 0, m_to_width, m_to_height);
1967 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
1970 /** A dummy method, which can be thought of as a placeholder to initialize
1971 * test-specific GL objects.
1973 void PipelineStatisticsQueryTestFunctionalBase::initObjects()
1975 /* Left blank intentionally - this method should be overloaded by deriving
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.
1986 * @param n_components_per_vertex As per description.
1988 void PipelineStatisticsQueryTestFunctionalBase::initVAO(unsigned int n_components_per_vertex)
1990 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1992 /* Release an VAO that's already been created */
1995 gl.deleteVertexArrays(1, &m_vao_id);
2000 /* Generate a new one */
2001 gl.genVertexArrays(1, &m_vao_id);
2002 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2004 gl.bindVertexArray(m_vao_id);
2005 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2008 gl.vertexAttribPointer(0, /* index */
2009 n_components_per_vertex, GL_FLOAT, GL_FALSE, /* normalized */
2011 (glw::GLvoid*)(deUintptr)m_vbo_vertex_data_offset);
2012 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
2014 gl.enableVertexAttribArray(0); /* index */
2015 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
2017 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo_id);
2018 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
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.
2024 * The following fields will be modified by the method:
2026 * m_vbo_n_indices: Will hold the number of indices stored in index
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
2035 * m_vbo_indirect_elements_argument_offset: Will hold the offset, from which
2036 * glDrawElementsIndirect() arguments will be
2038 * m_indirect_draw_call_firstindex_argument: Will be updated to point to the location, from
2039 * which index data starts.
2041 * @param raw_vertex_data Pointer to a buffer that holds vertex data
2042 * which should be used when constructing the VBO.
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.
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'
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'
2059 * @param indirect_draw_bo_basevertex_argument Argument to be used for indirect draw calls'
2060 * "basevertex" argument.
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)
2069 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2071 /* If we already have initialized a VBO, delete it before we continue */
2074 gl.deleteBuffers(1, &m_vbo_id);
2079 /* Our BO storage is formed as below:
2083 * [indirect glDrawArrays() call arguments]
2084 * [indirect glDrawElements() call arguments]
2086 * We store the relevant offsets in member fields, so that they can be used by actual test
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 */
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;
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);
2102 m_indirect_draw_call_firstindex_argument =
2103 static_cast<unsigned int>(m_vbo_index_data_offset / sizeof(unsigned int));
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
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;
2118 gl.genBuffers(1, &m_vbo_id);
2119 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
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.");
2126 gl.bufferData(GL_ARRAY_BUFFER, bo_data_size, DE_NULL, /* data */
2128 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
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.");
2139 /** Performs the actual test.
2141 * @return Always STOP.
2143 tcu::TestNode::IterateResult PipelineStatisticsQueryTestFunctionalBase::iterate()
2145 bool has_passed = true;
2146 glu::ContextType contextType = m_context.getRenderContext().getType();
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"))
2152 throw tcu::NotSupportedError("GL_ARB_pipeline_statistics_query extension is not supported");
2155 /* Initialize QO BO storage if GL_ARB_query_buffer_object is supported */
2156 if (m_context.getContextInfo().isExtensionSupported("GL_ARB_query_buffer_object"))
2160 DE_ASSERT(m_bo_qo_id != 0);
2163 /* Initialize other test-specific objects */
2166 /* Iterate through all pipeline statistics query object types */
2167 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2169 for (unsigned int n_query_target = 0; n_query_target < PipelineStatisticsQueryUtilities::n_query_targets;
2172 glw::GLenum current_query_target = PipelineStatisticsQueryUtilities::query_targets[n_query_target];
2174 if (shouldExecuteForQueryTarget(current_query_target))
2176 /* Initialize the query object */
2177 gl.genQueries(1, &m_qo_id);
2178 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries() call failed.");
2180 /* Execute the test for the particular query target. */
2181 has_passed &= executeTest(current_query_target);
2183 /* Delete the query object */
2184 gl.deleteQueries(1, &m_qo_id);
2185 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries() call failed.");
2189 } /* for (all query targets) */
2193 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2197 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2203 /** Initializes a query buffer object. */
2204 void PipelineStatisticsQueryTestFunctionalBase::initQOBO()
2206 const glw::Functions gl = m_context.getRenderContext().getFunctions();
2208 /* Set up the buffer object we will use for storage of query object results */
2209 unsigned char bo_data[PipelineStatisticsQueryUtilities::qo_bo_size];
2211 memset(bo_data, 0xFF, sizeof(bo_data));
2213 gl.genBuffers(1, &m_bo_qo_id);
2214 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2216 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_qo_id);
2217 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
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.");
2223 /** Executes a draw call, whose type is specified under pThis->m_current_draw_call_type.
2225 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctionalBase instance, which
2226 * should be used to extract the draw call type.
2228 * @return Always true.
2230 bool PipelineStatisticsQueryTestFunctionalBase::queryCallbackDrawCallHandler(void* pThis)
2232 PipelineStatisticsQueryTestFunctionalBase* pInstance = (PipelineStatisticsQueryTestFunctionalBase*)pThis;
2233 const glw::Functions& gl = pInstance->m_context.getRenderContext().getFunctions();
2235 /* Issue the draw call */
2236 glw::GLenum primitive_type =
2237 PipelineStatisticsQueryUtilities::getEnumForPrimitiveType(pInstance->m_current_primitive_type);
2239 switch (pInstance->m_current_draw_call_type)
2241 case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWARRAYS:
2243 gl.drawArrays(primitive_type, pInstance->m_indirect_draw_call_first_argument,
2244 pInstance->m_indirect_draw_call_count_argument);
2246 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
2251 case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWARRAYSINDIRECT:
2253 gl.drawArraysIndirect(primitive_type,
2254 (const glw::GLvoid*)(deUintptr)pInstance->m_vbo_indirect_arrays_argument_offset);
2256 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArraysIndirect() call failed.");
2261 case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCED:
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);
2267 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArraysInstanced() call failed.");
2272 case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWARRAYSINSTANCEDBASEINSTANCE:
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);
2282 case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTS:
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);
2287 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements() call failed.");
2292 case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSBASEVERTEX:
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);
2298 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsBaseVertex() call failed.");
2303 case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSINDIRECT:
2305 gl.drawElementsIndirect(primitive_type, GL_UNSIGNED_INT,
2306 (glw::GLvoid*)(deUintptr)pInstance->m_vbo_indirect_elements_argument_offset);
2308 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsIndirect() call failed.");
2313 case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCED:
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);
2319 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsInstanced() call failed.");
2324 case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEINSTANCE:
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);
2331 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsInstancedBaseInstance() call failed.");
2336 case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE:
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);
2344 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsInstancedBaseVertexBaseInstance() call failed.");
2349 case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWRANGEELEMENTS:
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);
2355 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawRangeElements() call failed.");
2360 case PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_GLDRAWRANGEELEMENTSBASEVERTEX:
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);
2368 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawRangeElementsBaseVertex() call failed.");
2375 TCU_FAIL("Unrecognized draw call type");
2377 } /* switch (m_current_draw_call_type) */
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.
2385 * @param query_target Query target to be used for the call.
2387 * @return Always true.
2389 bool PipelineStatisticsQueryTestFunctionalBase::shouldExecuteForQueryTarget(glw::GLenum query_target)
2397 * @param context Rendering context.
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.")
2404 /* Left blank intentionally */
2407 /** Executes a test iteration for user-specified query target.
2409 * @param current_query_target Pipeline statistics query target to execute the iteration
2412 * @return true if the test passed for the iteration, false otherwise.
2414 bool PipelineStatisticsQueryTestFunctional1::executeTest(glw::GLenum current_query_target)
2417 PipelineStatisticsQueryUtilities::_test_execution_result run_result;
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))
2424 m_testCtx.getLog() << tcu::TestLog::Message << "Could not retrieve test run results for query target "
2426 << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target) << "]"
2427 << tcu::TestLog::EndMessage;
2433 const glw::GLuint64 expected_value = 0;
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) */
2447 * @param context Rendering context
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"
2456 , m_to_draw_fbo_id(0)
2457 , m_to_read_fbo_id(0)
2461 /* Left blank intentionally */
2464 /** Deinitializes all GL objects that were created during test execution. */
2465 void PipelineStatisticsQueryTestFunctional2::deinitObjects()
2467 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2471 gl.deleteBuffers(1, &m_bo_id);
2476 if (m_fbo_draw_id != 0)
2478 gl.deleteFramebuffers(1, &m_fbo_draw_id);
2483 if (m_fbo_read_id != 0)
2485 gl.deleteFramebuffers(1, &m_fbo_read_id);
2490 if (m_to_draw_fbo_id != 0)
2492 gl.deleteTextures(1, &m_to_draw_fbo_id);
2494 m_to_draw_fbo_id = 0;
2497 if (m_to_read_fbo_id != 0)
2499 gl.deleteTextures(1, &m_to_read_fbo_id);
2501 m_to_read_fbo_id = 0;
2505 /** Callback handler which calls glBlitFramebuffer() API function and makes sure it
2506 * was executed successfully.
2508 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2511 * @return Always true.
2513 bool PipelineStatisticsQueryTestFunctional2::executeBlitFramebufferTest(void* pThis)
2515 PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2516 const glw::Functions& gl = data_ptr->m_context.getRenderContext().getFunctions();
2518 /* Framebuffer objects are bound to their FB targets at this point */
2519 gl.blitFramebuffer(0, /* srcX0 */
2521 data_ptr->m_to_width, /* srcX1 */
2522 data_ptr->m_to_height, /* srcY1 */
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 */
2530 GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() call failed.");
2535 /** Callback handler which calls glBufferSubData() API function and makes sure it
2536 * was executed successfully.
2538 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2541 * @return Always true.
2543 bool PipelineStatisticsQueryTestFunctional2::executeBufferSubDataTest(void* pThis)
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];
2550 memset(test_bo_data, 0xFF, test_data_size);
2552 gl.bindBuffer(GL_ARRAY_BUFFER, data_ptr->m_bo_id);
2553 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
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.");
2562 /** Callback handler which calls glClearBufferfv() API function and makes sure it
2563 * was executed successfully.
2565 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2568 * @return Always true.
2570 bool PipelineStatisticsQueryTestFunctional2::executeClearBufferfvColorBufferTest(void* pThis)
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();
2576 gl.clearBufferfv(GL_COLOR, 0, /* drawbuffer */
2578 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferfv() call failed.");
2583 /** Callback handler which calls glClearBufferfv() API function and makes sure it
2584 * was executed successfully.
2586 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2589 * @return Always true.
2591 bool PipelineStatisticsQueryTestFunctional2::executeClearBufferfvDepthBufferTest(void* pThis)
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();
2597 gl.clearBufferfv(GL_DEPTH, 0, /* drawbuffer */
2599 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferfv() call failed.");
2604 /** Callback handler which calls glClearBufferiv() API function and makes sure it
2605 * was executed successfully.
2607 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2610 * @return Always true.
2612 bool PipelineStatisticsQueryTestFunctional2::executeClearBufferivStencilBufferTest(void* pThis)
2614 const glw::GLint clear_stencil = 123;
2615 PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2616 const glw::Functions& gl = data_ptr->m_context.getRenderContext().getFunctions();
2618 gl.clearBufferiv(GL_STENCIL, 0, /* drawbuffer */
2620 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferfv() call failed.");
2625 /** Callback handler which calls glClearBufferSubData() API function and makes sure it
2626 * was executed successfully.
2628 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2631 * @return true if glClearBufferSubData() is available, false otherwise.
2633 bool PipelineStatisticsQueryTestFunctional2::executeClearBufferSubDataTest(void* pThis)
2635 PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2636 const glw::Functions& gl = data_ptr->m_context.getRenderContext().getFunctions();
2639 if (!glu::contextSupports(data_ptr->m_context.getRenderContext().getType(), glu::ApiType::core(4, 3)) &&
2640 gl.clearBufferSubData == NULL)
2642 /* API is unavailable */
2646 /* Execute the API call */
2647 const unsigned char value = 0xFF;
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.");
2657 /** Callback handler which calls glClear() API function configured to clear color
2658 * buffer and makes sure it was executed successfully.
2660 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2663 * @return Always true.
2665 bool PipelineStatisticsQueryTestFunctional2::executeClearColorBufferTest(void* pThis)
2667 PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2668 const glw::Functions& gl = data_ptr->m_context.getRenderContext().getFunctions();
2670 gl.clear(GL_COLOR_BUFFER_BIT);
2671 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
2676 /** Callback handler which calls glClear() API function configured to clear depth
2677 * buffer and makes sure it was executed successfully.
2679 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2682 * @return Always true.
2684 bool PipelineStatisticsQueryTestFunctional2::executeClearDepthBufferTest(void* pThis)
2686 PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2687 const glw::Functions& gl = data_ptr->m_context.getRenderContext().getFunctions();
2689 gl.clear(GL_DEPTH_BUFFER_BIT);
2690 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
2695 /** Callback handler which calls glClear() API function configured to clear stencil
2696 * buffer and makes sure it was executed successfully.
2698 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2701 * @return Always true.
2703 bool PipelineStatisticsQueryTestFunctional2::executeClearStencilBufferTest(void* pThis)
2705 PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2706 const glw::Functions& gl = data_ptr->m_context.getRenderContext().getFunctions();
2708 gl.clear(GL_STENCIL_BUFFER_BIT);
2709 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
2714 /** Callback handler which calls glClearTexSubImage() API function (if available).
2716 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2719 * @return true if the function is supported by the running GL implementation, false
2722 bool PipelineStatisticsQueryTestFunctional2::executeClearTexSubImageTest(void* pThis)
2724 PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2725 const glw::Functions& gl = data_ptr->m_context.getRenderContext().getFunctions();
2728 if (!glu::contextSupports(data_ptr->m_context.getRenderContext().getType(), glu::ApiType::core(4, 4)) &&
2729 gl.clearTexSubImage == NULL)
2731 /* API is unavailable */
2735 /* Execute the API call */
2736 const unsigned char test_value = 0xFF;
2738 gl.clearTexSubImage(data_ptr->m_to_draw_fbo_id, 0, /* level */
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.");
2750 /** Callback handler which calls glCopyImageSubData() API function (if available).
2752 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2755 * @return true if the function is supported by the running GL implementation, false
2758 bool PipelineStatisticsQueryTestFunctional2::executeCopyImageSubDataTest(void* pThis)
2760 PipelineStatisticsQueryTestFunctional2* data_ptr = (PipelineStatisticsQueryTestFunctional2*)pThis;
2761 const glw::Functions& gl = data_ptr->m_context.getRenderContext().getFunctions();
2764 if (!glu::contextSupports(data_ptr->m_context.getRenderContext().getType(), glu::ApiType::core(4, 3)) &&
2765 gl.copyImageSubData == NULL)
2767 /* API is unavailable */
2771 /* Execute the API call */
2772 gl.copyImageSubData(data_ptr->m_to_draw_fbo_id, GL_TEXTURE_2D, 0, /* srcLevel */
2776 data_ptr->m_to_read_fbo_id, GL_TEXTURE_2D, 0, /* dstLevel */
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.");
2787 /** Callback handler which calls glTexSubImage2D().
2789 * @param pThis Pointer to a PipelineStatisticsQueryTestFunctional2 instance. Must not
2792 * @return true Always true.
2794 bool PipelineStatisticsQueryTestFunctional2::executeTexSubImageTest(void* pThis)
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];
2801 memset(test_data, 0xFF, test_data_size);
2803 gl.texSubImage2D(GL_TEXTURE_2D, 0, /* level */
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.");
2812 /** Executes a test iteration for user-specified query target.
2814 * @param current_query_target Pipeline statistics query target to execute the iteration
2817 * @return true if the test passed for the iteration, false otherwise.
2819 bool PipelineStatisticsQueryTestFunctional2::executeTest(glw::GLenum current_query_target)
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,
2837 const unsigned int n_query_draw_handlers = sizeof(query_draw_handlers) / sizeof(query_draw_handlers[0]);
2839 for (unsigned int n = 0; n < n_query_draw_handlers; ++n)
2841 const PipelineStatisticsQueryUtilities::PFNQUERYDRAWHANDLERPROC& draw_handler_pfn = query_draw_handlers[n];
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.
2847 if (draw_handler_pfn(this))
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))
2854 m_testCtx.getLog() << tcu::TestLog::Message << "Query execution failed for query target "
2856 << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target) << "]"
2857 << tcu::TestLog::EndMessage;
2863 const glw::GLuint64 expected_value = 0;
2864 bool has_passed = true;
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);
2873 m_testCtx.getLog() << tcu::TestLog::Message << "Test failed for iteration index [" << n << "]."
2874 << tcu::TestLog::EndMessage;
2878 } /* if (run results were obtained successfully) */
2879 } /* if (draw handler executed successfully) */
2885 /* Initializes all GL objects used by the test */
2886 void PipelineStatisticsQueryTestFunctional2::initObjects()
2888 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
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.");
2894 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
2895 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
2897 gl.bufferData(GL_ARRAY_BUFFER, bo_size, DE_NULL, /* data */
2899 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
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");
2906 gl.bindTexture(GL_TEXTURE_2D, m_to_draw_fbo_id);
2907 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
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.");
2913 gl.bindTexture(GL_TEXTURE_2D, m_to_read_fbo_id);
2914 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
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.");
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.");
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.");
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.");
2936 * @param context Rendering context
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)
2946 /* Left blank intentionally */
2949 /** Deinitializes all GL objects that were created during test execution. */
2950 void PipelineStatisticsQueryTestFunctional3::deinitObjects()
2952 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2956 gl.deleteProgram(m_po_id);
2961 /* Disable "primitive restart" functionality */
2962 gl.disable(GL_PRIMITIVE_RESTART);
2963 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed.");
2966 /** Executes a test iteration for user-specified query target.
2968 * @param current_query_target Pipeline statistics query target to execute the iteration
2971 * @return true if the test passed for the iteration, false otherwise.
2973 bool PipelineStatisticsQueryTestFunctional3::executeTest(glw::GLenum current_query_target)
2975 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2977 PipelineStatisticsQueryUtilities::_test_execution_result run_result;
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);
2987 /* Set up VBO. We don't really care much about the visual outcome,
2988 * so any data will do.
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,
2996 const unsigned int n_indices = sizeof(index_data) / sizeof(index_data[0]);
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;
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);
3008 initVAO(n_vertex_components);
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]);
3015 for (unsigned int n_pr_status = 0; n_pr_status < n_pr_statuses; ++n_pr_status)
3017 m_is_primitive_restart_enabled = pr_statuses[n_pr_status];
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)
3027 /* Configure 'primitive restart' functionality */
3028 if (!m_is_primitive_restart_enabled)
3030 gl.disable(GL_PRIMITIVE_RESTART);
3031 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed.");
3035 gl.primitiveRestartIndex(0);
3036 GLU_EXPECT_NO_ERROR(gl.getError(), "glPrimitiveRestartIndex() call failed.");
3038 gl.enable(GL_PRIMITIVE_RESTART);
3039 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed.");
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)
3046 m_current_primitive_type = (PipelineStatisticsQueryUtilities::_primitive_type)n_primitive_type;
3048 /* Exclude patches from the test */
3049 if (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_PATCHES)
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 :
3058 n_draw_call_type < PipelineStatisticsQueryUtilities::DRAW_CALL_TYPE_COUNT; ++n_draw_call_type)
3060 m_current_draw_call_type = (PipelineStatisticsQueryUtilities::_draw_call_type)n_draw_call_type;
3062 /* Only continue if the draw call is supported by the context */
3063 if (!PipelineStatisticsQueryUtilities::isDrawCallSupported(m_current_draw_call_type, gl))
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))
3073 m_testCtx.getLog() << tcu::TestLog::Message
3074 << "Could not retrieve test run results for query target "
3076 << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target)
3077 << "]" << tcu::TestLog::EndMessage;
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;
3088 if (current_query_target == GL_CLIPPING_OUTPUT_PRIMITIVES_ARB)
3090 verification_type = PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_EQUAL_OR_GREATER;
3093 if (current_query_target == GL_VERTICES_SUBMITTED_ARB)
3095 getExpectedVerticesSubmittedQueryResult(m_current_primitive_type, &n_expected_values,
3100 getExpectedPrimitivesSubmittedQueryResult(m_current_primitive_type, &n_expected_values,
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);
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) */
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.
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
3126 * @param out_result1 Deref will be set to the first of the acceptable
3127 * result values, if @param out_result1_written was set
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
3132 * @param out_result2 Deref will be set to the second of the acceptable
3133 * result values, if @param out_result2_written was set
3137 void PipelineStatisticsQueryTestFunctional3::getExpectedPrimitivesSubmittedQueryResult(
3138 PipelineStatisticsQueryUtilities::_primitive_type current_primitive_type, unsigned int* out_results_written,
3139 glw::GLuint64 out_results[4])
3141 unsigned int n_input_vertices = m_indirect_draw_call_count_argument;
3143 *out_results_written = 0;
3146 DE_ASSERT(current_primitive_type != PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_PATCHES);
3149 if (m_is_primitive_restart_enabled)
3151 /* Primitive restart functionality in our test removes a single index.
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.
3160 switch (current_primitive_type)
3162 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_POINTS:
3164 out_results[(*out_results_written)++] = n_input_vertices;
3169 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINE_LOOP:
3171 if (n_input_vertices > 2)
3173 out_results[(*out_results_written)++] = n_input_vertices;
3175 else if (n_input_vertices > 1)
3177 out_results[(*out_results_written)++] = 1;
3181 out_results[(*out_results_written)++] = 0;
3185 } /* PRIMITIVE_TYPE_LINE_LOOP */
3187 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLE_FAN:
3189 if (n_input_vertices > 2)
3191 out_results[(*out_results_written)++] = n_input_vertices - 2;
3195 out_results[(*out_results_written)++] = 0;
3197 if (n_input_vertices >= 1)
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.
3202 out_results[(*out_results_written)++] = 1;
3209 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINE_STRIP:
3211 if (n_input_vertices > 1)
3213 out_results[(*out_results_written)++] = n_input_vertices - 1;
3217 out_results[(*out_results_written)++] = 0;
3219 if (n_input_vertices > 0)
3221 /* If the submitted line strip is incomplete, also include the case
3222 * where the incomplete line's vertices are counted as a primitive.
3224 out_results[(*out_results_written)++] = 1;
3231 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLE_STRIP:
3233 if (n_input_vertices > 2)
3235 out_results[(*out_results_written)++] = n_input_vertices - 2;
3239 out_results[(*out_results_written)++] = 0;
3241 if (n_input_vertices >= 1)
3243 /* If the submitted triangle strip is incomplete, also include the case
3244 * where the incomplete triangle's vertices are counted as a primitive.
3246 out_results[(*out_results_written)++] = 1;
3253 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES:
3255 out_results[(*out_results_written)++] = n_input_vertices / 2;
3257 /* If the submitted line is incomplete, also include the case where
3258 * the incomplete line's vertices are counted as a primitive.
3260 if (n_input_vertices > 0 && (n_input_vertices % 2) != 0)
3262 out_results[(*out_results_written)++] = n_input_vertices / 2 + 1;
3268 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES_ADJACENCY:
3270 out_results[(*out_results_written)++] = n_input_vertices / 4;
3272 /* If the submitted line is incomplete, also include the case where
3273 * the incomplete line's vertices are counted as a primitive.
3275 if (n_input_vertices > 0 && (n_input_vertices % 4) != 0)
3277 out_results[(*out_results_written)++] = n_input_vertices / 4 + 1;
3283 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES:
3285 out_results[(*out_results_written)++] = n_input_vertices / 3;
3287 /* If the submitted triangle is incomplete, also include the case
3288 * when the incomplete triangle's vertices are counted as a primitive.
3290 if (n_input_vertices > 0 && (n_input_vertices % 3) != 0)
3292 out_results[(*out_results_written)++] = n_input_vertices / 3 + 1;
3298 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES_ADJACENCY:
3300 out_results[(*out_results_written)++] = n_input_vertices / 6;
3302 /* If the submitted triangle is incomplete, also include the case
3303 * when the incomplete triangle's vertices are counted as a primitive.
3305 if (n_input_vertices > 0 && (n_input_vertices % 6) != 0)
3307 out_results[(*out_results_written)++] = n_input_vertices / 6 + 1;
3315 TCU_FAIL("Unrecognized primitive type");
3317 } /* switch (current_primitive_type) */
3319 if (PipelineStatisticsQueryUtilities::isInstancedDrawCall(m_current_draw_call_type))
3321 for (unsigned int i = 0; i < *out_results_written; ++i)
3323 out_results[i] *= m_indirect_draw_call_primcount_argument;
3325 } /* if (instanced draw call type) */
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.
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
3337 * @param out_result1 Deref will be set to the first of the acceptable
3338 * result values, if @param out_result1_written was set
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
3343 * @param out_result2 Deref will be set to the second of the acceptable
3344 * result values, if @param out_result2_written was set
3348 void PipelineStatisticsQueryTestFunctional3::getExpectedVerticesSubmittedQueryResult(
3349 PipelineStatisticsQueryUtilities::_primitive_type current_primitive_type, unsigned int* out_results_written,
3350 glw::GLuint64 out_results[4])
3352 unsigned int n_input_vertices = m_indirect_draw_call_count_argument;
3354 *out_results_written = 0;
3357 DE_ASSERT(current_primitive_type != PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_PATCHES);
3360 if (m_is_primitive_restart_enabled)
3362 /* Primitive restart functionality in our test removes a single index.
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.
3371 switch (current_primitive_type)
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:
3378 out_results[(*out_results_written)++] = n_input_vertices;
3383 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINE_LOOP:
3385 out_results[(*out_results_written)++] = n_input_vertices;
3387 /* Allow line loops to count the first vertex twice as that vertex
3388 * is part of both the first and the last primitives.
3390 out_results[(*out_results_written)++] = n_input_vertices + 1;
3394 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES:
3396 out_results[(*out_results_written)++] = n_input_vertices;
3398 /* If the submitted line is incomplete, also include the case where
3399 * the incomplete line's vertices are not counted.
3401 if (n_input_vertices > 0 && (n_input_vertices % 2) != 0)
3403 out_results[(*out_results_written)++] = n_input_vertices - 1;
3409 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES_ADJACENCY:
3411 /* Allow implementations to both include or exclude the adjacency
3414 out_results[(*out_results_written)++] = n_input_vertices;
3415 out_results[(*out_results_written)++] = n_input_vertices / 2;
3417 /* If the submitted line is incomplete, also include the case where
3418 * the incomplete line's vertices are not counted.
3420 if (n_input_vertices > 0 && (n_input_vertices % 4) != 0)
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;
3429 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES:
3431 out_results[(*out_results_written)++] = n_input_vertices;
3433 /* If the submitted triangle is incomplete, also include the case
3434 * when the incomplete triangle's vertices are not counted.
3436 if (n_input_vertices > 0 && (n_input_vertices % 3) != 0)
3438 out_results[(*out_results_written)++] = n_input_vertices - (n_input_vertices % 3);
3444 case PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES_ADJACENCY:
3446 /* Allow implementations to both include or exclude the adjacency
3449 out_results[(*out_results_written)++] = n_input_vertices;
3450 out_results[(*out_results_written)++] = n_input_vertices / 2;
3452 /* If the submitted triangle is incomplete, also include the case
3453 * when the incomplete triangle's vertices are not counted.
3455 if (n_input_vertices > 0 && (n_input_vertices % 6) != 0)
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;
3466 TCU_FAIL("Unrecognized primitive type");
3468 } /* switch (current_primitive_type) */
3470 if (PipelineStatisticsQueryUtilities::isInstancedDrawCall(m_current_draw_call_type))
3472 for (unsigned int i = 0; i < *out_results_written; ++i)
3474 out_results[i] *= m_indirect_draw_call_primcount_argument;
3476 } /* if (instanced draw call type) */
3479 /** Initializes GL objects used by the test */
3480 void PipelineStatisticsQueryTestFunctional3::initObjects()
3482 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
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);
3490 gl.useProgram(m_po_id);
3491 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3494 /** Tells whether the test instance should be executed for user-specified query target.
3496 * @param query_target Query target to be used for the call.
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.
3503 bool PipelineStatisticsQueryTestFunctional3::shouldExecuteForQueryTarget(glw::GLenum query_target)
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);
3511 * @param context Rendering context
3513 PipelineStatisticsQueryTestFunctional4::PipelineStatisticsQueryTestFunctional4(deqp::Context& context)
3514 : PipelineStatisticsQueryTestFunctionalBase(context, "functional_vertex_shader_invocations",
3515 "Verifies GL_VERTEX_SHADER_INVOCATIONS_ARB query works correctly")
3517 /* Left blank intentionally */
3520 /** Deinitializes all GL objects that were created during test execution. */
3521 void PipelineStatisticsQueryTestFunctional4::deinitObjects()
3523 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3527 gl.deleteProgram(m_po_id);
3533 /** Executes a test iteration for user-specified query target.
3535 * @param current_query_target Pipeline statistics query target to execute the iteration
3538 * @return true if the test passed for the iteration, false otherwise.
3540 bool PipelineStatisticsQueryTestFunctional4::executeTest(glw::GLenum current_query_target)
3542 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3544 PipelineStatisticsQueryUtilities::_test_execution_result run_result;
3546 /* Sanity check: This method should only be called for GL_VERTEX_SHADER_INVOCATIONS_ARB
3548 DE_ASSERT(current_query_target == GL_VERTEX_SHADER_INVOCATIONS_ARB);
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]);
3556 /* Issue the test for 1 to 5 indices */
3557 for (unsigned int n_indices = 1; n_indices < n_data_indices; ++n_indices)
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;
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);
3569 initVAO(n_vertex_components);
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)
3575 m_current_primitive_type = (PipelineStatisticsQueryUtilities::_primitive_type)n_primitive_type;
3577 /* Exclude patches from the test */
3578 if (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_PATCHES)
3583 /* Exclude the primitive types, for which the number of indices is insufficient to form
3586 if ((m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINE_LOOP &&
3588 (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINE_STRIP &&
3590 (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_LINES && n_indices < 2) ||
3591 (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLE_FAN &&
3593 (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLE_STRIP &&
3595 (m_current_primitive_type == PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_TRIANGLES &&
3598 /* Skip the iteration */
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)
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)
3613 m_current_draw_call_type = (PipelineStatisticsQueryUtilities::_draw_call_type)n_draw_call_type;
3615 /* Only continue if the draw call is supported by the context */
3616 if (!PipelineStatisticsQueryUtilities::isDrawCallSupported(m_current_draw_call_type, gl))
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))
3627 m_testCtx.getLog() << tcu::TestLog::Message
3628 << "Could not retrieve test run results for query target "
3630 << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target)
3631 << "]" << tcu::TestLog::EndMessage;
3637 static const glw::GLuint64 expected_value = 1;
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);
3646 } /* if (run results were obtained successfully) */
3647 } /* for (all draw call types) */
3648 } /* for (all primitive types) */
3649 } /* for (1 to 5 indices) */
3654 /** Initializes all GL objects used by the test */
3655 void PipelineStatisticsQueryTestFunctional4::initObjects()
3657 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
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);
3666 gl.useProgram(m_po_id);
3667 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3670 /** Tells whether the test instance should be executed for user-specified query target.
3672 * @param query_target Query target to be used for the call.
3674 * @return true if @param query_target is GL_VERTEX_SHADER_INVOCATIONS_ARB.
3677 bool PipelineStatisticsQueryTestFunctional4::shouldExecuteForQueryTarget(glw::GLenum query_target)
3679 return (query_target == GL_VERTEX_SHADER_INVOCATIONS_ARB);
3684 * @param context Rendering context
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 "
3692 /* Left blank intentionally */
3695 /** Deinitializes all GL objects that were created during test execution. */
3696 void PipelineStatisticsQueryTestFunctional5::deinitObjects()
3698 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3702 gl.deleteProgram(m_po_id);
3708 /** Executes a test iteration for user-specified query target.
3710 * @param current_query_target Pipeline statistics query target to execute the iteration
3713 * @return true if the test passed for the iteration, false otherwise.
3715 bool PipelineStatisticsQueryTestFunctional5::executeTest(glw::GLenum current_query_target)
3717 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3719 PipelineStatisticsQueryUtilities::_test_execution_result run_result;
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);
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,
3731 const unsigned int index_data[] = { 2, 1, 0 };
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;
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);
3743 initVAO(n_vertex_components);
3745 /* Set up the primitive type */
3746 m_current_primitive_type = PipelineStatisticsQueryUtilities::PRIMITIVE_TYPE_PATCHES;
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;
3752 m_current_draw_call_type = (PipelineStatisticsQueryUtilities::_draw_call_type)n_draw_call_type;
3754 /* Only continue if the draw call is supported by the context */
3755 if (!PipelineStatisticsQueryUtilities::isDrawCallSupported(m_current_draw_call_type, gl))
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))
3766 m_testCtx.getLog() << tcu::TestLog::Message << "Could not retrieve test run results for query target "
3768 << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target) << "]"
3769 << tcu::TestLog::EndMessage;
3775 static const glw::GLuint64 expected_value = 1; /* as per test spec */
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);
3784 } /* if (run results were obtained successfully) */
3785 } /* for (all draw call types) */
3790 /** Initializes all GL objects used by the test */
3791 void PipelineStatisticsQueryTestFunctional5::initObjects()
3793 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
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)))
3798 throw tcu::NotSupportedError("OpenGL 4.0+ is required to run this test.");
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);
3806 gl.useProgram(m_po_id);
3807 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3810 /** Tells whether the test instance should be executed for user-specified query target.
3812 * @param query_target Query target to be used for the call.
3814 * @return true if @param query_target is either GL_TESS_CONTROL_SHADER_PATCHES_ARB,
3815 * or GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB.
3818 bool PipelineStatisticsQueryTestFunctional5::shouldExecuteForQueryTarget(glw::GLenum query_target)
3820 return (query_target == GL_TESS_CONTROL_SHADER_PATCHES_ARB ||
3821 query_target == GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB);
3826 * @param context Rendering context
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 "
3833 , m_n_primitives_emitted_by_gs(3)
3834 , m_n_streams_emitted_by_gs(3)
3836 /* Left blank intentionally */
3839 /** Deinitializes all GL objects that were created during test execution. */
3840 void PipelineStatisticsQueryTestFunctional6::deinitObjects()
3842 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3846 gl.deleteProgram(m_po_id);
3852 /** Executes a test iteration for user-specified query target.
3854 * @param current_query_target Pipeline statistics query target to execute the iteration
3857 * @return true if the test passed for the iteration, false otherwise.
3859 bool PipelineStatisticsQueryTestFunctional6::executeTest(glw::GLenum current_query_target)
3861 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3863 PipelineStatisticsQueryUtilities::_test_execution_result run_result;
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);
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,
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;
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);
3887 initVAO(n_vertex_components);
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)
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);
3898 /* Update the VBO contents */
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);
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.");
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);
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.
3918 * For GL_GEOMETRY_SHADER_INVOCATIONS, we only need a single iteration.
3920 const unsigned int n_internal_iterations =
3921 (current_query_target == GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB) ? 2 : 1;
3923 for (unsigned int n_internal_iteration = 0; n_internal_iteration < n_internal_iterations;
3924 ++n_internal_iteration)
3926 /* Build the test program. */
3927 std::string gs_body;
3929 if (n_internal_iteration == 1)
3931 /* This path will only be entered for GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB query.
3933 * OpenGL does not support multiple vertex streams for output primitive types other than
3936 if (gs_output != PipelineStatisticsQueryUtilities::GEOMETRY_SHADER_OUTPUT_POINTS)
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);
3947 gs_body = PipelineStatisticsQueryUtilities::buildGeometryShaderBody(
3948 gs_input, gs_output, m_n_primitives_emitted_by_gs, 1); /* n_streams */
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);
3956 gl.useProgram(m_po_id);
3957 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3959 /* Set up the primitive type */
3960 m_current_primitive_type = PipelineStatisticsQueryUtilities::getPrimitiveTypeFromGSInput(gs_input);
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)
3966 m_current_draw_call_type = (PipelineStatisticsQueryUtilities::_draw_call_type)n_draw_call_type;
3968 /* Only continue if the draw call is supported by the context */
3969 if (!PipelineStatisticsQueryUtilities::isDrawCallSupported(m_current_draw_call_type, gl))
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))
3981 << tcu::TestLog::Message << "Could not retrieve test run results for query target "
3983 << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target) << "]"
3984 << tcu::TestLog::EndMessage;
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;
3995 if (current_query_target == GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB)
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;
4002 if (n_internal_iteration == 1)
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)
4007 expected_values[1] += (m_n_primitives_emitted_by_gs + n_stream);
4008 } /* for (non-default streams) */
4011 if (PipelineStatisticsQueryUtilities::isInstancedDrawCall(m_current_draw_call_type))
4013 expected_values[0] *= m_indirect_draw_call_primcount_argument;
4014 expected_values[1] *= m_indirect_draw_call_primcount_argument;
4019 n_expected_values = 1;
4020 expected_values[0] = 1; /* as per test spec */
4021 verification_type = PipelineStatisticsQueryUtilities::VERIFICATION_TYPE_EQUAL_OR_GREATER;
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);
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) */
4040 /** Initializes all GL objects used by the test */
4041 void PipelineStatisticsQueryTestFunctional6::initObjects()
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)))
4046 throw tcu::NotSupportedError("OpenGL 3.2+ is required to run this test.");
4050 /** Tells whether the test instance should be executed for user-specified query target.
4052 * @param query_target Query target to be used for the call.
4054 * @return true if @param query_target is either GL_GEOMETRY_SHADER_INVOCATIONS, or
4055 * GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB.
4058 bool PipelineStatisticsQueryTestFunctional6::shouldExecuteForQueryTarget(glw::GLenum query_target)
4060 return (query_target == GL_GEOMETRY_SHADER_INVOCATIONS ||
4061 query_target == GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB);
4066 * @param context Rendering context
4068 PipelineStatisticsQueryTestFunctional7::PipelineStatisticsQueryTestFunctional7(deqp::Context& context)
4069 : PipelineStatisticsQueryTestFunctionalBase(context, "functional_fragment_shader_invocations",
4070 "Verifies GL_FRAGMENT_SHADER_INVOCATIONS_ARB queries "
4073 /* Left blank intentionally */
4076 /** Deinitializes all GL objects that were created during test execution. */
4077 void PipelineStatisticsQueryTestFunctional7::deinitObjects()
4079 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4083 gl.deleteProgram(m_po_id);
4089 /** Executes a test iteration for user-specified query target.
4091 * @param current_query_target Pipeline statistics query target to execute the iteration
4094 * @return true if the test passed for the iteration, false otherwise.
4096 bool PipelineStatisticsQueryTestFunctional7::executeTest(glw::GLenum current_query_target)
4098 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4100 PipelineStatisticsQueryUtilities::_test_execution_result run_result;
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);
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 };
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;
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);
4123 initVAO(n_vertex_components);
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)
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)
4138 m_current_primitive_type = current_primitive_type;
4140 /* Update 'count' argument so that we only use as many vertices as needed for current
4143 unsigned int count_argument_value =
4144 PipelineStatisticsQueryUtilities::getNumberOfVerticesForPrimitiveType(m_current_primitive_type);
4146 m_indirect_draw_call_count_argument = count_argument_value;
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);
4153 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
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)
4159 m_current_draw_call_type = (PipelineStatisticsQueryUtilities::_draw_call_type)n_draw_call_type;
4161 /* Only continue if the draw call is supported by the context */
4162 if (!PipelineStatisticsQueryUtilities::isDrawCallSupported(m_current_draw_call_type, gl))
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.");
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))
4177 m_testCtx.getLog() << tcu::TestLog::Message << "Could not retrieve test run results for query target "
4179 << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target) << "]"
4180 << tcu::TestLog::EndMessage;
4186 static const glw::GLuint64 expected_value = 1; /* as per test spec */
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);
4195 } /* if (run results were obtained successfully) */
4196 } /* for (all draw call types) */
4197 } /* for (all primitive types) */
4202 /** Initializes all GL objects used by the test */
4203 void PipelineStatisticsQueryTestFunctional7::initObjects()
4205 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
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);
4213 gl.useProgram(m_po_id);
4214 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
4217 /** Tells whether the test instance should be executed for user-specified query target.
4219 * @param query_target Query target to be used for the call.
4221 * @return true if @param query_target is GL_FRAGMENT_SHADER_INVOCATIONS_ARB.
4224 bool PipelineStatisticsQueryTestFunctional7::shouldExecuteForQueryTarget(glw::GLenum query_target)
4226 return (query_target == GL_FRAGMENT_SHADER_INVOCATIONS_ARB);
4231 * @param context Rendering context
4233 PipelineStatisticsQueryTestFunctional8::PipelineStatisticsQueryTestFunctional8(deqp::Context& context)
4234 : PipelineStatisticsQueryTestFunctionalBase(context, "functional_compute_shader_invocations",
4235 "Verifies that GL_COMPUTE_SHADER_INVOCATIONS_ARB queries "
4237 , m_bo_dispatch_compute_indirect_args_offset(0)
4239 , m_current_iteration(0)
4241 /* Left blank intentionally */
4244 /** Deinitializes all GL objects that were created during test execution. */
4245 void PipelineStatisticsQueryTestFunctional8::deinitObjects()
4247 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4251 gl.deleteBuffers(1, &m_bo_id);
4257 /** Executes a test iteration for user-specified query target.
4259 * @param current_query_target Pipeline statistics query target to execute the iteration
4262 * @return true if the test passed for the iteration, false otherwise.
4264 bool PipelineStatisticsQueryTestFunctional8::executeTest(glw::GLenum current_query_target)
4267 PipelineStatisticsQueryUtilities::_test_execution_result run_result;
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);
4273 /* This test needs to be run in two iterations:
4275 * 1. glDispatchCompute() should be called.
4276 * 2. glDispatchComputeIndirect() should be called.
4279 for (m_current_iteration = 0; m_current_iteration < 2; /* as per description */
4280 ++m_current_iteration)
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))
4287 m_testCtx.getLog() << tcu::TestLog::Message << "Could not retrieve test run results for query target "
4289 << PipelineStatisticsQueryUtilities::getStringForEnum(current_query_target) << "]"
4290 << tcu::TestLog::EndMessage;
4296 static const glw::GLuint64 expected_value = 1; /* as per test spec */
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) */
4309 /** Initializes all GL objects used by the test */
4310 void PipelineStatisticsQueryTestFunctional8::initObjects()
4312 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
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 */
4320 gl.useProgram(m_po_id);
4321 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
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 */);
4328 const unsigned int drawcall_args[] = {
4329 1, /* num_groups_x */
4330 1, /* num_groups_y */
4331 1 /* num_groups_z */
4334 gl.genBuffers(1, &m_bo_id);
4335 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
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.");
4341 gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, /* index */
4343 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
4345 gl.bufferData(GL_ARRAY_BUFFER, bo_size, DE_NULL, GL_STATIC_DRAW);
4346 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
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.");
4354 /* Store rthe offset, at which the draw call args start */
4355 m_bo_dispatch_compute_indirect_args_offset = sizeof(unsigned int);
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.
4363 * @param pInstance Pointer to a PipelineStatisticsQueryTestFunctional8 instance.
4365 bool PipelineStatisticsQueryTestFunctional8::queryCallbackDispatchCallHandler(void* pInstance)
4367 glw::GLenum error_code = GL_NO_ERROR;
4368 PipelineStatisticsQueryTestFunctional8* pThis = (PipelineStatisticsQueryTestFunctional8*)pInstance;
4370 const glw::Functions& gl = pThis->m_context.getRenderContext().getFunctions();
4372 if (pThis->m_current_iteration == 0)
4374 gl.dispatchCompute(1, /* num_groups_x */
4375 1, /* num_groups_y */
4376 1); /* num_groups_z */
4380 gl.dispatchComputeIndirect(pThis->m_bo_dispatch_compute_indirect_args_offset);
4383 error_code = gl.getError();
4384 if (error_code != GL_NO_ERROR)
4386 pThis->m_testCtx.getLog() << tcu::TestLog::Message
4387 << ((pThis->m_current_iteration == 0) ? "glDispatchCompute()" :
4388 "glDispatchComputeIndirect()")
4389 << " call failed with error code "
4391 << error_code << "]." << tcu::TestLog::EndMessage;
4399 /** Tells whether the test instance should be executed for user-specified query target.
4401 * @param query_target Query target to be used for the call.
4403 * @return true if @param query_target is GL_COMPUT_SHADER_INVOCATIONS_ARB.
4406 bool PipelineStatisticsQueryTestFunctional8::shouldExecuteForQueryTarget(glw::GLenum query_target)
4408 return (query_target == GL_COMPUTE_SHADER_INVOCATIONS_ARB);
4413 * @param context Rendering context.
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.")
4420 /* Left blank intentionally */
4423 /** Initializes the test group contents. */
4424 void PipelineStatisticsQueryTests::init()
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));
4437 } /* glcts namespace */