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