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 * \file gl3cTransformFeedbackOverflowQueryTests.cpp 26 * \brief Implements conformance tests for "Transform Feedback Overflow 27 * Query" functionality. 28 */ /*-------------------------------------------------------------------*/ 29 30 #include "gl3cTransformFeedbackOverflowQueryTests.hpp" 31 32 #include "deMath.h" 33 #include "deSharedPtr.hpp" 34 35 #include "gluContextInfo.hpp" 36 #include "gluDefs.hpp" 37 #include "gluPixelTransfer.hpp" 38 #include "gluShaderProgram.hpp" 39 40 #include "tcuFuzzyImageCompare.hpp" 41 #include "tcuImageCompare.hpp" 42 #include "tcuRenderTarget.hpp" 43 #include "tcuSurface.hpp" 44 #include "tcuTestLog.hpp" 45 46 #include "glw.h" 47 #include "glwFunctions.hpp" 48 49 namespace gl3cts 50 { 51 52 /* 53 Base class of all test cases of the feature. Enforces the requirements below: 54 55 * Check that the extension string is available. 56 */ 57 class TransformFeedbackOverflowQueryBaseTest : public deqp::TestCase 58 { 59 protected: 60 TransformFeedbackOverflowQueryBaseTest(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api, 61 const char* name, const char* description) 62 : TestCase(context, name, description), m_api(api), m_max_vertex_streams(0) 63 { 64 } 65 66 /* Checks whether the feature is supported. */ 67 bool featureSupported() 68 { 69 if (m_api == TransformFeedbackOverflowQueryTests::API_GL_ARB_transform_feedback_overflow_query) 70 { 71 glu::ContextType contextType = m_context.getRenderContext().getType(); 72 if (m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_overflow_query") || 73 glu::contextSupports(contextType, glu::ApiType::core(4, 6))) 74 { 75 return true; 76 } 77 } 78 return false; 79 } 80 81 /* Checks whether transform_feedback2 is supported. */ 82 bool supportsTransformFeedback2() 83 { 84 return (m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2") || 85 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType(4, 0, glu::PROFILE_CORE))); 86 } 87 88 /* Checks whether transform_feedback3 is supported. */ 89 bool supportsTransformFeedback3() 90 { 91 return (m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3") || 92 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType(4, 0, glu::PROFILE_CORE))); 93 } 94 95 /* Checks whether gpu_shader5 is supported. */ 96 bool supportsGpuShader5() 97 { 98 return (m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5") || 99 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType(4, 0, glu::PROFILE_CORE))); 100 } 101 102 /* Checks whether conditional_render_inverted is supported. */ 103 bool supportsConditionalRenderInverted() 104 { 105 return (m_context.getContextInfo().isExtensionSupported("GL_ARB_conditional_render_inverted") || 106 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType(4, 5, glu::PROFILE_CORE))); 107 } 108 109 /* Checks whether query_buffer_object are supported. */ 110 bool supportsQueryBufferObject() 111 { 112 return (m_context.getContextInfo().isExtensionSupported("GL_ARB_query_buffer_object") || 113 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType(4, 4, glu::PROFILE_CORE))); 114 } 115 116 /* Returns the maximum number of vertex streams. */ 117 GLuint getMaxVertexStreams() const 118 { 119 return m_max_vertex_streams; 120 } 121 122 /* Basic test init, child classes must call it. */ 123 virtual void init() 124 { 125 if (!featureSupported()) 126 { 127 throw tcu::NotSupportedError("Required transform_feedback_overflow_query extension is not supported"); 128 } 129 130 if (supportsTransformFeedback3()) 131 { 132 m_max_vertex_streams = (GLuint)m_context.getContextInfo().getInt(GL_MAX_VERTEX_STREAMS); 133 } 134 } 135 136 protected: 137 const TransformFeedbackOverflowQueryTests::API m_api; 138 139 private: 140 GLuint m_max_vertex_streams; 141 }; 142 143 /* 144 API Implementation Dependent State Test 145 146 * Check that calling GetQueryiv with target TRANSFORM_FEEDBACK_OVERFLOW 147 and pname QUERY_COUNTER_BITS returns a non-negative value without error. 148 149 * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling 150 GetQueryiv with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW and pname 151 QUERY_COUNTER_BITS returns a non-negative value without error. 152 */ 153 class TransformFeedbackOverflowQueryImplDepState : public TransformFeedbackOverflowQueryBaseTest 154 { 155 public: 156 TransformFeedbackOverflowQueryImplDepState(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api, 157 const char* name) 158 : TransformFeedbackOverflowQueryBaseTest( 159 context, api, name, 160 "Tests whether the implementation dependent state defined by the feature matches the requirements.") 161 { 162 } 163 164 /* Test case iterate function. Contains the actual test case logic. */ 165 IterateResult iterate() 166 { 167 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 168 GLint counterBits; 169 170 gl.getQueryiv(GL_TRANSFORM_FEEDBACK_OVERFLOW, GL_QUERY_COUNTER_BITS, &counterBits); 171 if (counterBits < 0) 172 { 173 TCU_FAIL("Value of QUERY_COUNTER_BITS for query target TRANSFORM_FEEDBACK_OVERFLOW is invalid"); 174 } 175 176 if (supportsTransformFeedback3()) 177 { 178 gl.getQueryiv(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, GL_QUERY_COUNTER_BITS, &counterBits); 179 if (counterBits < 0) 180 { 181 TCU_FAIL("Value of QUERY_COUNTER_BITS for query target TRANSFORM_FEEDBACK_STREAM_OVERFLOW is invalid"); 182 } 183 } 184 185 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 186 187 return STOP; 188 } 189 }; 190 191 /* 192 Base class for all test cases of the feature that verify newly introduced context state. 193 */ 194 class TransformFeedbackOverflowQueryContextStateBase : public TransformFeedbackOverflowQueryBaseTest 195 { 196 protected: 197 TransformFeedbackOverflowQueryContextStateBase(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api, 198 const char* name, const char* description) 199 : TransformFeedbackOverflowQueryBaseTest(context, api, name, description) 200 { 201 } 202 203 /* Returns whether CURRENT_QUERY state for the specified target and index matches the given value. */ 204 bool verifyCurrentQueryState(GLenum target, GLuint index, GLuint value) 205 { 206 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 207 GLint expected = (GLint)value; 208 GLint actual; 209 210 // Use GetQueryIndexediv by default 211 gl.getQueryIndexediv(target, index, GL_CURRENT_QUERY, &actual); 212 if (actual != expected) 213 { 214 return false; 215 } 216 217 if (index == 0) 218 { 219 // If index is zero then GetQueryiv should also return the expected value 220 gl.getQueryiv(target, GL_CURRENT_QUERY, &actual); 221 if (actual != expected) 222 { 223 return false; 224 } 225 } 226 227 return true; 228 } 229 }; 230 231 /* 232 API Default Context State Test 233 234 * Check that calling GetQueryiv with target TRANSFORM_FEEDBACK_OVERFLOW 235 and pname CURRENT_QUERY returns zero by default. 236 237 * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling 238 GetQueryIndexediv with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW and 239 pname CURRENT_QUERY returns zero for any index between zero and MAX_- 240 VERTEX_STREAMS. 241 */ 242 class TransformFeedbackOverflowQueryDefaultState : public TransformFeedbackOverflowQueryContextStateBase 243 { 244 public: 245 TransformFeedbackOverflowQueryDefaultState(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api, 246 const char* name) 247 : TransformFeedbackOverflowQueryContextStateBase( 248 context, api, name, 249 "Tests whether the new context state defined by the feature has the expected default values.") 250 { 251 } 252 253 /* Test case iterate function. Contains the actual test case logic. */ 254 IterateResult iterate() 255 { 256 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_OVERFLOW, 0, 0)) 257 { 258 TCU_FAIL("Default value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_OVERFLOW is non-zero"); 259 } 260 261 if (supportsTransformFeedback3()) 262 { 263 for (GLuint i = 0; i < getMaxVertexStreams(); ++i) 264 { 265 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, 0, 0)) 266 { 267 TCU_FAIL("Default value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_STREAM_OVERFLOW " 268 "is non-zero"); 269 } 270 } 271 } 272 273 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 274 275 return STOP; 276 } 277 }; 278 279 /* 280 API Context State Update Test 281 282 * Check that after a successful call to BeginQuery with target TRANSFORM_- 283 FEEDBACK_OVERFLOW_ARB calling GetQueryiv with the same target and with 284 pname CURRENT_QUERY returns the name of the query previously passed to 285 BeginQuery. Also check that after calling EndQuery with the same target 286 GetQueryiv returns zero for the same parameters. 287 288 * If GL 4.0 or ARB_transform_feedback3 is supported, check that after a 289 successful call to BeginQueryIndexed with target TRANSFORM_FEEDBACK_- 290 STREAM_OVERFLOW_ARB calling GetQueryIndexediv with the same target and 291 with pname CURRENT_QUERY returns the name of the query previously passed 292 to BeginQueryIndexed if the index parameters match and otherwise it 293 returns zero. Also check that after calling EndQueryIndexed with the 294 same target and index GetQueryIndexediv returns zero for the same 295 parameters for all indices. Indices used should be between zero and 296 MAX_VERTEX_STREAMS. 297 */ 298 class TransformFeedbackOverflowQueryStateUpdate : public TransformFeedbackOverflowQueryContextStateBase 299 { 300 public: 301 TransformFeedbackOverflowQueryStateUpdate(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api, 302 const char* name) 303 : TransformFeedbackOverflowQueryContextStateBase( 304 context, api, name, 305 "Tests whether the new context state defined by the feature is correctly updated after a successful " 306 "call to {Begin|End}Query[Indexed] if the target of the query is one of the newly introduced ones.") 307 , m_overflow_query(0) 308 , m_stream_overflow_query(0) 309 { 310 } 311 312 /* Test case init. */ 313 virtual void init() 314 { 315 TransformFeedbackOverflowQueryContextStateBase::init(); 316 317 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 318 319 gl.genQueries(1, &m_overflow_query); 320 gl.genQueries(1, &m_stream_overflow_query); 321 } 322 323 /* Test case deinit */ 324 virtual void deinit() 325 { 326 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 327 328 gl.deleteQueries(1, &m_overflow_query); 329 gl.deleteQueries(1, &m_stream_overflow_query); 330 331 TransformFeedbackOverflowQueryContextStateBase::deinit(); 332 } 333 334 /* Test case iterate function. Contains the actual test case logic. */ 335 IterateResult iterate() 336 { 337 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 338 339 // Call BeginQuery 340 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW, m_overflow_query); 341 342 // Verify that CURRENT_QUERY is set to the name of the query 343 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_OVERFLOW, 0, m_overflow_query)) 344 { 345 TCU_FAIL("Value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_OVERFLOW is not updated properly " 346 "after a call to BeginQuery"); 347 } 348 349 // Call EndQuery 350 gl.endQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW); 351 352 // Verify that CURRENT_QUERY is reset to zero 353 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_OVERFLOW, 0, 0)) 354 { 355 TCU_FAIL("Value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_OVERFLOW is not reset properly " 356 "after a call to EndQuery"); 357 } 358 359 if (supportsTransformFeedback3()) 360 { 361 for (GLuint i = 0; i < getMaxVertexStreams(); ++i) 362 { 363 // Call BeginQueryIndexed with specified index 364 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, i, m_stream_overflow_query); 365 366 // Verify that CURRENT_QUERY is set to the name of the query for the specified index, but remains zero for other indices 367 for (GLuint j = 0; j < getMaxVertexStreams(); ++j) 368 { 369 if (i == j) 370 { 371 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, j, m_stream_overflow_query)) 372 { 373 TCU_FAIL("Value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_STREAM_OVERFLOW " 374 "is not updated properly after a call to BeginQueryIndexed"); 375 } 376 } 377 else 378 { 379 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, j, 0)) 380 { 381 TCU_FAIL("Value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_STREAM_OVERFLOW " 382 "is incorrectly updated for an unrelated vertex stream" 383 "index after a call to BeginQueryIndexed"); 384 } 385 } 386 } 387 388 // Call EndQueryIndexed with specified index 389 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, i); 390 391 // Verify that CURRENT_QUERY is reset to zero for the specified index and still remains zero for other indices 392 for (GLuint j = 0; j < getMaxVertexStreams(); ++j) 393 { 394 if (i == j) 395 { 396 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, j, 0)) 397 { 398 TCU_FAIL("Value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_STREAM_OVERFLOW " 399 "is not reset properly after a call to EndQueryIndexed"); 400 } 401 } 402 else 403 { 404 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, j, 0)) 405 { 406 TCU_FAIL("Value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_STREAM_OVERFLOW " 407 "is incorrectly updated for an unrelated vertex stream" 408 "index after a call to EndQueryIndexed"); 409 } 410 } 411 } 412 } 413 } 414 415 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 416 417 return STOP; 418 } 419 420 protected: 421 GLuint m_overflow_query; 422 GLuint m_stream_overflow_query; 423 }; 424 425 /* 426 Base class for all test cases of the feature that verify various error scenarios. 427 */ 428 class TransformFeedbackOverflowQueryErrorBase : public TransformFeedbackOverflowQueryBaseTest 429 { 430 protected: 431 TransformFeedbackOverflowQueryErrorBase(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api, 432 const char* name, const char* description) 433 : TransformFeedbackOverflowQueryBaseTest(context, api, name, description), m_case_name(0) 434 { 435 } 436 437 /* Starts a new error scenario sub-test with the given name. The name is used in error messages if the sub-test fails. */ 438 void startTest(const char* caseName) 439 { 440 m_case_name = caseName; 441 } 442 443 /* Verifies whether the actually generated error matches that of the expected one. If not then it triggers the failure 444 of the test case with the sub-case name used as the failure message. */ 445 void verifyError(GLenum expectedError) 446 { 447 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 448 449 GLenum actualError = gl.getError(); 450 451 if (actualError != expectedError) 452 { 453 TCU_FAIL(m_case_name); 454 } 455 } 456 457 private: 458 const char* m_case_name; 459 }; 460 461 /* 462 API Invalid Index Error Test 463 464 * Check that calling GetQueryIndexediv with target TRANSFORM_FEEDBACK_- 465 OVERFLOW_ARB and a non-zero index generates an INVALID_VALUE error. 466 467 * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling 468 GetQueryIndexediv with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW 469 and an index greater than or equal to MAX_VERTEX_STREAMS generates an 470 INVALID_VALUE error. 471 472 * Check that calling BeginQueryIndexed with target TRANSFORM_FEEDBACK_- 473 OVERFLOW_ARB and a non-zero index generates an INVALID_VALUE error. 474 475 * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling 476 BeginQueryIndexed with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW 477 and an index greater than or equal to MAX_VERTEX_STREAMS generates an 478 INVALID_VALUE error. 479 */ 480 class TransformFeedbackOverflowQueryErrorInvalidIndex : public TransformFeedbackOverflowQueryErrorBase 481 { 482 public: 483 TransformFeedbackOverflowQueryErrorInvalidIndex(deqp::Context& context, 484 TransformFeedbackOverflowQueryTests::API api, const char* name) 485 : TransformFeedbackOverflowQueryErrorBase( 486 context, api, name, "Verifies whether an INVALID_VALUE error is properly generated if GetQueryIndexediv " 487 "or BeginQueryIndexed is called " 488 "with an invalid index when using the new targets introduced by the feature.") 489 , m_query(0) 490 { 491 } 492 493 /* Test case init. */ 494 virtual void init() 495 { 496 TransformFeedbackOverflowQueryErrorBase::init(); 497 498 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 499 500 gl.genQueries(1, &m_query); 501 } 502 503 /* Test case deinit */ 504 virtual void deinit() 505 { 506 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 507 508 gl.deleteQueries(1, &m_query); 509 510 TransformFeedbackOverflowQueryErrorBase::deinit(); 511 } 512 513 /* Test case iterate function. Contains the actual test case logic. */ 514 IterateResult iterate() 515 { 516 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 517 GLint value; 518 519 startTest("GetQueryIndexediv must generate INVALID_VALUE if <target> is " 520 "TRANSFORM_FEEDBACK_OVERFLOW and <index> is non-zero."); 521 522 for (GLuint i = 1; i < getMaxVertexStreams(); ++i) 523 { 524 gl.getQueryIndexediv(GL_TRANSFORM_FEEDBACK_OVERFLOW, i, GL_CURRENT_QUERY, &value); 525 verifyError(GL_INVALID_VALUE); 526 } 527 528 if (supportsTransformFeedback3()) 529 { 530 startTest("GetQueryIndexediv must generate INVALID_VALUE if <target> is " 531 "TRANSFORM_FEEDBACK_STREAM_OVERFLOW and <index> is greater " 532 "than or equal to MAX_VERTEX_STREAMS."); 533 534 for (GLuint i = getMaxVertexStreams(); i < getMaxVertexStreams() + 4; ++i) 535 { 536 gl.getQueryIndexediv(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, i, GL_CURRENT_QUERY, &value); 537 verifyError(GL_INVALID_VALUE); 538 } 539 } 540 541 startTest("BeginQueryIndexed must generate INVALID_VALUE if <target> is " 542 "TRANSFORM_FEEDBACK_OVERFLOW and <index> is non-zero."); 543 544 for (GLuint i = 1; i < getMaxVertexStreams(); ++i) 545 { 546 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_OVERFLOW, i, m_query); 547 verifyError(GL_INVALID_VALUE); 548 } 549 550 if (supportsTransformFeedback3()) 551 { 552 startTest("BeginQueryIndexed must generate INVALID_VALUE if <target> is " 553 "TRANSFORM_FEEDBACK_STREAM_OVERFLOW and <index> is greater " 554 "than or equal to MAX_VERTEX_STREAMS."); 555 556 for (GLuint i = getMaxVertexStreams(); i < getMaxVertexStreams() + 4; ++i) 557 { 558 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, i, m_query); 559 verifyError(GL_INVALID_VALUE); 560 } 561 } 562 563 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 564 565 return STOP; 566 } 567 568 protected: 569 GLuint m_query; 570 }; 571 572 /* 573 API Already Active Error Test 574 575 * Check that calling BeginQuery with target TRANSFORM_FEEDBACK_OVERFLOW 576 generates an INVALID_OPERATION error if there is already an active 577 query for TRANSFORM_FEEDBACK_OVERFLOW. 578 579 * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling 580 BeginQueryIndexed with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW 581 generates an INVALID_OPERATION error if there is already an active 582 query for TRANSFORM_FEEDBACK_STREAM_OVERFLOW for the specified 583 index. 584 585 * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling 586 BeginQueryIndexed with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW 587 generates an INVALID_OPERATION error if the specified query is already 588 active on another TRANSFORM_FEEDBACK_STREAM_OVERFLOW target with 589 a different index. 590 */ 591 class TransformFeedbackOverflowQueryErrorAlreadyActive : public TransformFeedbackOverflowQueryErrorBase 592 { 593 public: 594 TransformFeedbackOverflowQueryErrorAlreadyActive(deqp::Context& context, 595 TransformFeedbackOverflowQueryTests::API api, const char* name) 596 : TransformFeedbackOverflowQueryErrorBase(context, api, name, 597 "Verifies whether an INVALID_OPERATION error is properly generated " 598 "if BeginQuery[Indexed] is used to try to start " 599 "a query on an index that has already a query active, or the query " 600 "object itself is active on another index.") 601 , m_query(0) 602 , m_active_overflow_query(0) 603 , m_active_stream_overflow_query(0) 604 , m_active_query_stream_index(0) 605 { 606 } 607 608 /* Test case init. */ 609 virtual void init() 610 { 611 TransformFeedbackOverflowQueryErrorBase::init(); 612 613 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 614 615 gl.genQueries(1, &m_query); 616 617 gl.genQueries(1, &m_active_overflow_query); 618 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW, m_active_overflow_query); 619 620 if (supportsTransformFeedback3()) 621 { 622 gl.genQueries(1, &m_active_stream_overflow_query); 623 m_active_query_stream_index = 2; 624 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, m_active_query_stream_index, 625 m_active_stream_overflow_query); 626 } 627 } 628 629 /* Test case deinit */ 630 virtual void deinit() 631 { 632 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 633 634 if (supportsTransformFeedback3()) 635 { 636 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, m_active_query_stream_index); 637 gl.deleteQueries(1, &m_active_stream_overflow_query); 638 } 639 640 gl.endQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW); 641 gl.deleteQueries(1, &m_active_overflow_query); 642 643 gl.deleteQueries(1, &m_query); 644 645 TransformFeedbackOverflowQueryErrorBase::deinit(); 646 } 647 648 /* Test case iterate function. Contains the actual test case logic. */ 649 IterateResult iterate() 650 { 651 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 652 653 startTest("BeginQuery[Indexed] must generate INVALID_OPERATION if <target> is " 654 "TRANSFORM_FEEDBACK_OVERFLOW and there is already an active " 655 "query for TRANSFORM_FEEDBACK_ARB."); 656 657 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW, m_query); 658 verifyError(GL_INVALID_OPERATION); 659 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_OVERFLOW, 0, m_query); 660 verifyError(GL_INVALID_OPERATION); 661 662 if (supportsTransformFeedback3()) 663 { 664 startTest("BeginQueryIndexed must generate INVALID_OPERATION if <target> is " 665 "TRANSFORM_FEEDBACK_STREAM_OVERFLOW and there is already an active " 666 "query for TRANSFORM_FEEDBACK_STREAM_OVERFLOW for the specified index."); 667 668 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, m_active_query_stream_index, m_query); 669 verifyError(GL_INVALID_OPERATION); 670 671 startTest("BeginQuery[Indexed] must generate INVALID_OPERATION if <target> is " 672 "TRANSFORM_FEEDBACK_STREAM_OVERFLOW and the specified query is " 673 "already active on another TRANSFORM_FEEDBACK_STREAM_OVERFLOW " 674 "target with a different index."); 675 676 for (GLuint i = 0; i < getMaxVertexStreams(); ++i) 677 { 678 if (i != m_active_query_stream_index) 679 { 680 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, i, m_active_stream_overflow_query); 681 verifyError(GL_INVALID_OPERATION); 682 683 if (i == 0) 684 { 685 gl.beginQuery(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, m_active_stream_overflow_query); 686 verifyError(GL_INVALID_OPERATION); 687 } 688 } 689 } 690 } 691 692 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 693 694 return STOP; 695 } 696 697 protected: 698 GLuint m_query; 699 GLuint m_active_overflow_query; 700 GLuint m_active_stream_overflow_query; 701 GLuint m_active_query_stream_index; 702 }; 703 704 /* 705 API Incompatible Target Error Test 706 707 * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling 708 BeginQueryIndexed with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW 709 generates an INVALID_OPERATION error if the specified query was 710 previously used as a TRANSFORM_FEEDBACK_OVERFLOW query. Also check 711 the other way around. 712 */ 713 class TransformFeedbackOverflowQueryErrorIncompatibleTarget : public TransformFeedbackOverflowQueryErrorBase 714 { 715 public: 716 TransformFeedbackOverflowQueryErrorIncompatibleTarget(deqp::Context& context, 717 TransformFeedbackOverflowQueryTests::API api, 718 const char* name) 719 : TransformFeedbackOverflowQueryErrorBase(context, api, name, 720 "Verifies whether an INVALID_OPERATION error is properly generated " 721 "if BeginQuery[Indexed] is called with one of " 722 "the newly introduced query targets but one that is different than " 723 "that used earlier on the same query object.") 724 , m_overflow_query(0) 725 , m_stream_overflow_query(0) 726 , m_incompatible_query(0) 727 { 728 } 729 730 /* Test case init. */ 731 virtual void init() 732 { 733 TransformFeedbackOverflowQueryErrorBase::init(); 734 735 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 736 737 gl.genQueries(1, &m_incompatible_query); 738 gl.beginQuery(GL_SAMPLES_PASSED, m_incompatible_query); 739 gl.endQuery(GL_SAMPLES_PASSED); 740 741 gl.genQueries(1, &m_overflow_query); 742 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW, m_overflow_query); 743 gl.endQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW); 744 745 if (supportsTransformFeedback3()) 746 { 747 gl.genQueries(1, &m_stream_overflow_query); 748 gl.beginQuery(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, m_stream_overflow_query); 749 gl.endQuery(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW); 750 } 751 } 752 753 /* Test case deinit */ 754 virtual void deinit() 755 { 756 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 757 758 gl.deleteQueries(1, &m_incompatible_query); 759 760 gl.deleteQueries(1, &m_overflow_query); 761 762 if (supportsTransformFeedback3()) 763 { 764 gl.deleteQueries(1, &m_stream_overflow_query); 765 } 766 767 TransformFeedbackOverflowQueryErrorBase::deinit(); 768 } 769 770 /* Test case iterate function. Contains the actual test case logic. */ 771 IterateResult iterate() 772 { 773 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 774 775 startTest("BeginQuery[Indexed] must generate INVALID_OPERATION if <target> is " 776 "TRANSFORM_FEEDBACK_OVERFLOW and the specified query was " 777 "previously used with another target."); 778 779 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW, m_incompatible_query); 780 verifyError(GL_INVALID_OPERATION); 781 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_OVERFLOW, 0, m_incompatible_query); 782 verifyError(GL_INVALID_OPERATION); 783 784 if (supportsTransformFeedback3()) 785 { 786 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW, m_stream_overflow_query); 787 verifyError(GL_INVALID_OPERATION); 788 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_OVERFLOW, 0, m_stream_overflow_query); 789 verifyError(GL_INVALID_OPERATION); 790 791 startTest("BeginQuery[Indexed] must generate INVALID_OPERATION if <target> is " 792 "TRANSFORM_FEEDBACK_STREAM_OVERFLOW and the specified query " 793 "was previously used with another target."); 794 795 gl.beginQuery(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, m_incompatible_query); 796 verifyError(GL_INVALID_OPERATION); 797 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, 2, m_incompatible_query); 798 verifyError(GL_INVALID_OPERATION); 799 800 gl.beginQuery(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, m_overflow_query); 801 verifyError(GL_INVALID_OPERATION); 802 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, 2, m_overflow_query); 803 verifyError(GL_INVALID_OPERATION); 804 } 805 806 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 807 808 return STOP; 809 } 810 811 protected: 812 GLuint m_overflow_query; 813 GLuint m_stream_overflow_query; 814 GLuint m_incompatible_query; 815 }; 816 817 /* 818 API No Query Active Error Test 819 820 * Check that calling EndQuery with target TRANSFORM_FEEDBACK_OVERFLOW 821 generates an INVALID_OPERATION error if no query is active for 822 TRANSFORM_FEEDBACK_OVERFLOW. 823 824 * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling 825 EndQueryIndexed with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW 826 generates an INVALID_OPERATION error if no query is active for 827 TRANSFORM_FEEDBACK_STREAM_OVERFLOW for the specified index, even 828 if there is an active query for another index. 829 */ 830 class TransformFeedbackOverflowQueryErrorNoActiveQuery : public TransformFeedbackOverflowQueryErrorBase 831 { 832 public: 833 TransformFeedbackOverflowQueryErrorNoActiveQuery(deqp::Context& context, 834 TransformFeedbackOverflowQueryTests::API api, const char* name) 835 : TransformFeedbackOverflowQueryErrorBase(context, api, name, 836 "Verifies whether an INVALID_OPERATION error is properly generated " 837 "if EndQuery[Indexed] is called with a target " 838 "(and index) for which there isn't a currently active query.") 839 , m_active_stream_overflow_query(0) 840 , m_active_query_stream_index(0) 841 { 842 } 843 844 /* Test case init. */ 845 virtual void init() 846 { 847 TransformFeedbackOverflowQueryErrorBase::init(); 848 849 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 850 851 if (supportsTransformFeedback3()) 852 { 853 gl.genQueries(1, &m_active_stream_overflow_query); 854 m_active_query_stream_index = 2; 855 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, m_active_query_stream_index, 856 m_active_stream_overflow_query); 857 } 858 } 859 860 /* Test case deinit */ 861 virtual void deinit() 862 { 863 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 864 865 if (supportsTransformFeedback3()) 866 { 867 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, m_active_query_stream_index); 868 gl.deleteQueries(1, &m_active_stream_overflow_query); 869 } 870 871 TransformFeedbackOverflowQueryErrorBase::deinit(); 872 } 873 874 /* Test case iterate function. Contains the actual test case logic. */ 875 IterateResult iterate() 876 { 877 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 878 879 startTest("EndQuery[Indexed] must generate INVALID_OPERATION if <target> is " 880 "TRANSFORM_FEEDBACK_OVERFLOW and there is no query active " 881 "for TRANSFORM_FEEDBACK_OVERFLOW."); 882 883 gl.endQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW); 884 verifyError(GL_INVALID_OPERATION); 885 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_OVERFLOW, 0); 886 verifyError(GL_INVALID_OPERATION); 887 888 if (supportsTransformFeedback3()) 889 { 890 startTest("EndQuery[Indexed] must generate INVALID_OPERATION if <target> is " 891 "TRANSFORM_FEEDBACK_STREAM_OVERFLOW and there is no query active " 892 "for TRANSFORM_FEEDBACK_STREAM_OVERFLOW for the given index."); 893 894 for (GLuint i = 0; i < getMaxVertexStreams(); ++i) 895 { 896 if (i != m_active_query_stream_index) 897 { 898 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, i); 899 verifyError(GL_INVALID_OPERATION); 900 901 if (i == 0) 902 { 903 gl.endQuery(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW); 904 verifyError(GL_INVALID_OPERATION); 905 } 906 } 907 } 908 } 909 910 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 911 912 return STOP; 913 } 914 915 protected: 916 GLuint m_active_stream_overflow_query; 917 GLuint m_active_query_stream_index; 918 }; 919 920 /* 921 Base class of all functionality tests. Helps enforce the following requirements: 922 923 * Ensuring that QUERY_COUNTER_BITS is at least one for the TRANSFORM_FEEDBACK_OVERFLOW query 924 target before running any test that uses such a query's result. 925 926 * Ensuring that GL 4.0 or ARB_transform_feedback3 is supported and QUERY_COUNTER_BITS is at least 927 one for the TRANSFORM_FEEDBACK_STREAM_OVERFLOW query target before running any test that 928 uses such a query's result. 929 */ 930 class TransformFeedbackOverflowQueryFunctionalBase : public TransformFeedbackOverflowQueryBaseTest 931 { 932 protected: 933 TransformFeedbackOverflowQueryFunctionalBase(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api, 934 const char* name, const char* description) 935 : TransformFeedbackOverflowQueryBaseTest(context, api, name, description) 936 , m_overflow_query(0) 937 , m_stream_overflow_query(NULL) 938 , m_query_buffer(0) 939 , m_tf_buffer_count(0) 940 , m_tf_buffer(NULL) 941 , m_vao(0) 942 , m_program(0) 943 , m_checker_program(NULL) 944 { 945 } 946 947 /* Tells whether functional tests using TRANSFORM_FEEDBACK_OVERFLOW are runnable */ 948 bool canTestOverflow() 949 { 950 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 951 GLint counterBits; 952 953 gl.getQueryiv(GL_TRANSFORM_FEEDBACK_OVERFLOW, GL_QUERY_COUNTER_BITS, &counterBits); 954 955 return counterBits > 0; 956 } 957 958 /* Tells whether functional tests using TRANSFORM_FEEDBACK_STREAM_OVERFLOW are runnable */ 959 bool canTestStreamOverflow() 960 { 961 if (supportsTransformFeedback3()) 962 { 963 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 964 GLint counterBits; 965 966 gl.getQueryiv(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, GL_QUERY_COUNTER_BITS, &counterBits); 967 968 return counterBits > 0; 969 } 970 else 971 { 972 return false; 973 } 974 } 975 976 /* Dummy vertex shader. */ 977 const char* dummyVsh() 978 { 979 return "#version 150 core\n" 980 "void main() {\n" 981 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" 982 "}\n"; 983 } 984 985 /* Dummy fragment shader */ 986 const char* dummyFsh() 987 { 988 return "#version 150 core\n" 989 "void main() {}\n"; 990 } 991 992 /* Functional test init. Creates necessary query objects. */ 993 virtual void init() 994 { 995 TransformFeedbackOverflowQueryBaseTest::init(); 996 997 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 998 999 if (canTestOverflow()) 1000 { 1001 // Setup vertex array 1002 gl.genVertexArrays(1, &m_vao); 1003 gl.bindVertexArray(m_vao); 1004 1005 // Setup queries 1006 gl.genQueries(1, &m_overflow_query); 1007 1008 if (canTestStreamOverflow()) 1009 { 1010 m_stream_overflow_query = new GLuint[getMaxVertexStreams()]; 1011 1012 gl.genQueries(getMaxVertexStreams(), m_stream_overflow_query); 1013 } 1014 1015 // Setup checker program 1016 m_checker_program = 1017 new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(dummyVsh(), dummyFsh())); 1018 if (!m_checker_program->isOk()) 1019 { 1020 TCU_FAIL("Checker program compilation failed"); 1021 } 1022 1023 // Setup transform feedback shader and buffers 1024 buildTransformFeedbackProgram(); 1025 setupTransformFeedbackBuffers(); 1026 } 1027 else 1028 { 1029 throw tcu::NotSupportedError( 1030 "QUERY_COUNTER_BITS for TRANSFORM_FEEDBACK_OVERFLOW queries is zero, skipping test"); 1031 } 1032 } 1033 1034 /* Functional test deinit. Deletes created query objects */ 1035 virtual void deinit() 1036 { 1037 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1038 1039 gl.deleteVertexArrays(1, &m_vao); 1040 1041 gl.deleteQueries(1, &m_overflow_query); 1042 1043 if (canTestStreamOverflow()) 1044 { 1045 if (m_stream_overflow_query != NULL) 1046 { 1047 gl.deleteQueries(getMaxVertexStreams(), m_stream_overflow_query); 1048 1049 delete[] m_stream_overflow_query; 1050 } 1051 } 1052 1053 if (m_checker_program != NULL) 1054 { 1055 delete m_checker_program; 1056 } 1057 1058 gl.useProgram(0); 1059 gl.deleteProgram(m_program); 1060 1061 if (m_tf_buffer != NULL) 1062 { 1063 gl.deleteBuffers(m_tf_buffer_count, m_tf_buffer); 1064 1065 delete[] m_tf_buffer; 1066 } 1067 1068 TransformFeedbackOverflowQueryBaseTest::deinit(); 1069 } 1070 1071 /* 1072 Basic Checking Mechanism 1073 1074 * Call BeginConditionalRender with mode QUERY_WAIT and with the given 1075 query object as parameters. Draw something, then call EndConditional- 1076 Render. If the expected result for the query is FALSE, expect 1077 conditional render to discard the previous draw command. 1078 1079 * If GL 4.5 or ARB_conditional_render_inverted is supported, call Begin- 1080 ConditionalRender with mode QUERY_WAIT_INVERTED and with the given query 1081 object as parameters. Draw something, then call EndConditionalRender. If 1082 the expected result for the query is TRUE, expect conditional render to 1083 discard the previous draw command. 1084 1085 * Finally, check using GetQueryObjectiv with QUERY_RESULT that the result 1086 of the query matches the expected result. 1087 1088 * If GL 4.4 or ARB_query_buffer_object is supported then check the result 1089 of the query against the expected result also by having a query buffer 1090 bound at the time of calling GetQueryObjectiv. 1091 */ 1092 bool verifyQueryResult(GLuint query, GLboolean expected) 1093 { 1094 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1095 bool result = true; 1096 GLuint actual; 1097 1098 GLuint current_program = m_context.getContextInfo().getInt(GL_CURRENT_PROGRAM); 1099 GLuint checker_query, check_result; 1100 1101 // We'll use a PRIMITIVES_GENERATED query to test whether conditional 1102 // rendering actually executed the draw command or not. If the draw command 1103 // was discarded then the PRIMITIVES_GENERATED query should have a result 1104 // of zero. 1105 gl.genQueries(1, &checker_query); 1106 1107 gl.useProgram(m_checker_program->getProgram()); 1108 1109 // Verify that conditional render discards the rendering if the expected 1110 // result is FALSE and renders otherwise. 1111 gl.beginConditionalRender(query, GL_QUERY_WAIT); 1112 gl.beginQuery(GL_PRIMITIVES_GENERATED, checker_query); 1113 gl.drawArrays(GL_POINTS, 0, 1); 1114 gl.endQuery(GL_PRIMITIVES_GENERATED); 1115 gl.endConditionalRender(); 1116 gl.getQueryObjectuiv(checker_query, GL_QUERY_RESULT, &check_result); 1117 if (check_result != (GLuint)expected) 1118 { 1119 result = false; 1120 } 1121 1122 // Verify that an inverted conditional render discards the rendering if 1123 // the expected result is TRUE and renders otherwise. 1124 if (supportsConditionalRenderInverted()) 1125 { 1126 gl.beginConditionalRender(query, GL_QUERY_WAIT_INVERTED); 1127 gl.beginQuery(GL_PRIMITIVES_GENERATED, checker_query); 1128 gl.drawArrays(GL_POINTS, 0, 1); 1129 gl.endQuery(GL_PRIMITIVES_GENERATED); 1130 gl.endConditionalRender(); 1131 gl.getQueryObjectuiv(checker_query, GL_QUERY_RESULT, &check_result); 1132 if (check_result == (GLuint)expected) 1133 { 1134 result = false; 1135 } 1136 } 1137 1138 gl.useProgram(current_program); 1139 1140 // Verify that the result of the query matches the expected result. 1141 gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &actual); 1142 if ((GLboolean)actual != expected) 1143 { 1144 result = false; 1145 } 1146 1147 // Verify that the result of the query matches the expected result even 1148 // when using a query buffer. 1149 if (supportsQueryBufferObject()) 1150 { 1151 const GLuint initValue = 0xDEADBEEF; 1152 1153 gl.genBuffers(1, &m_query_buffer); 1154 gl.bindBuffer(GL_QUERY_BUFFER, m_query_buffer); 1155 gl.bufferData(GL_QUERY_BUFFER, sizeof(initValue), &initValue, GL_STREAM_READ); 1156 gl.getQueryObjectuiv(query, GL_QUERY_RESULT, NULL); 1157 gl.getBufferSubData(GL_QUERY_BUFFER, 0, sizeof(actual), &actual); 1158 gl.deleteBuffers(1, &m_query_buffer); 1159 1160 if ((GLboolean)actual != expected) 1161 { 1162 result = false; 1163 } 1164 } 1165 1166 gl.deleteQueries(1, &checker_query); 1167 1168 return result; 1169 } 1170 1171 /* Verifies the result of all queries. There can only be up to 5 non-FALSE result queries as none of 1172 the tests use more than 4 vertex streams so the rest is assumed to always have a FALSE result. */ 1173 void verifyQueryResults(GLboolean any, GLboolean stream0, GLboolean stream1, GLboolean stream2 = GL_FALSE, 1174 GLboolean stream3 = GL_FALSE) 1175 { 1176 bool result = true; 1177 1178 // Verify the result of the TRANSFORM_FEEDBACK_OVERFLOW query. 1179 result &= verifyQueryResult(m_overflow_query, any); 1180 1181 if (supportsTransformFeedback3()) 1182 { 1183 // Verify the result of the TRANSFORM_FEEDBACK_STREAM_OVERFLOW queries 1184 // corresponding to the first 4 vertex streams. 1185 result &= verifyQueryResult(m_stream_overflow_query[0], stream0); 1186 result &= verifyQueryResult(m_stream_overflow_query[1], stream1); 1187 result &= verifyQueryResult(m_stream_overflow_query[2], stream2); 1188 result &= verifyQueryResult(m_stream_overflow_query[3], stream3); 1189 1190 // Expect the rest of the TRANSFORM_FEEDBACK_STREAM_OVERFLOW queries 1191 // to have a FALSE result. 1192 for (GLuint i = 4; i < getMaxVertexStreams(); ++i) 1193 { 1194 result &= verifyQueryResult(m_stream_overflow_query[i], GL_FALSE); 1195 } 1196 } 1197 1198 if (!result) 1199 { 1200 TCU_FAIL("Failed to validate the results of the queries"); 1201 } 1202 } 1203 1204 /* Single stream version of verifyQueryResults */ 1205 void verifyQueryResults(GLboolean result) 1206 { 1207 verifyQueryResults(result, result, GL_FALSE, GL_FALSE, GL_FALSE); 1208 } 1209 1210 /* Compiles and links transform feedback program. */ 1211 void buildTransformFeedbackProgram() 1212 { 1213 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1214 1215 GLint status; 1216 1217 m_program = gl.createProgram(); 1218 1219 const char* vsSource = transformFeedbackVertexShader(); 1220 1221 GLuint vShader = gl.createShader(GL_VERTEX_SHADER); 1222 gl.shaderSource(vShader, 1, (const char**)&vsSource, NULL); 1223 gl.compileShader(vShader); 1224 gl.getShaderiv(vShader, GL_COMPILE_STATUS, &status); 1225 if (status == GL_FALSE) 1226 { 1227 GLint infoLogLength = 0; 1228 gl.getShaderiv(vShader, GL_INFO_LOG_LENGTH, &infoLogLength); 1229 1230 std::vector<char> infoLogBuf(infoLogLength + 1); 1231 gl.getShaderInfoLog(vShader, (GLsizei)infoLogBuf.size(), NULL, &infoLogBuf[0]); 1232 1233 std::string infoLog = &infoLogBuf[0]; 1234 m_testCtx.getLog().writeShader(QP_SHADER_TYPE_VERTEX, vsSource, false, infoLog.c_str()); 1235 1236 gl.deleteShader(vShader); 1237 1238 TCU_FAIL("Failed to compile transform feedback vertex shader"); 1239 } 1240 gl.attachShader(m_program, vShader); 1241 gl.deleteShader(vShader); 1242 1243 const char* gsSource = transformFeedbackGeometryShader(); 1244 1245 if (gsSource) 1246 { 1247 GLuint gShader = gl.createShader(GL_GEOMETRY_SHADER); 1248 gl.shaderSource(gShader, 1, (const char**)&gsSource, NULL); 1249 gl.compileShader(gShader); 1250 gl.getShaderiv(gShader, GL_COMPILE_STATUS, &status); 1251 if (status == GL_FALSE) 1252 { 1253 GLint infoLogLength = 0; 1254 gl.getShaderiv(gShader, GL_INFO_LOG_LENGTH, &infoLogLength); 1255 1256 std::vector<char> infoLogBuf(infoLogLength + 1); 1257 gl.getShaderInfoLog(gShader, (GLsizei)infoLogBuf.size(), NULL, &infoLogBuf[0]); 1258 1259 std::string infoLog = &infoLogBuf[0]; 1260 m_testCtx.getLog().writeShader(QP_SHADER_TYPE_GEOMETRY, gsSource, false, infoLog.c_str()); 1261 1262 gl.deleteShader(gShader); 1263 1264 TCU_FAIL("Failed to compile transform feedback geometry shader"); 1265 } 1266 gl.attachShader(m_program, gShader); 1267 gl.deleteShader(gShader); 1268 } 1269 1270 gl.transformFeedbackVaryings(m_program, varyingsCount(), varyings(), bufferMode()); 1271 gl.linkProgram(m_program); 1272 gl.getProgramiv(m_program, GL_LINK_STATUS, &status); 1273 if (status == GL_FALSE) 1274 { 1275 GLint infoLogLength = 0; 1276 gl.getProgramiv(m_program, GL_INFO_LOG_LENGTH, &infoLogLength); 1277 1278 std::vector<char> infoLogBuf(infoLogLength + 1); 1279 gl.getProgramInfoLog(m_program, (GLsizei)infoLogBuf.size(), NULL, &infoLogBuf[0]); 1280 1281 std::string infoLog = &infoLogBuf[0]; 1282 m_testCtx.getLog().writeShader(QP_SHADER_TYPE_VERTEX, vsSource, true, infoLog.c_str()); 1283 1284 TCU_FAIL("Failed to link transform feedback program"); 1285 } 1286 1287 gl.useProgram(m_program); 1288 } 1289 1290 /* Generates a number of transform feedback buffers and binds them. */ 1291 void setupTransformFeedbackBuffers() 1292 { 1293 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1294 1295 m_tf_buffer_count = bufferCount(); 1296 1297 m_tf_buffer = new GLuint[m_tf_buffer_count]; 1298 1299 gl.genBuffers(m_tf_buffer_count, m_tf_buffer); 1300 1301 for (GLint i = 0; i < m_tf_buffer_count; ++i) 1302 { 1303 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_tf_buffer[i]); 1304 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bufferSize(i), NULL, GL_DYNAMIC_COPY); 1305 } 1306 } 1307 1308 /* Starts all overflow queries. */ 1309 void beginQueries() 1310 { 1311 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1312 1313 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW, m_overflow_query); 1314 1315 if (supportsTransformFeedback3()) 1316 { 1317 for (GLuint i = 0; i < getMaxVertexStreams(); ++i) 1318 { 1319 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, i, m_stream_overflow_query[i]); 1320 } 1321 } 1322 } 1323 1324 /* Stops all overflow queries. */ 1325 void endQueries() 1326 { 1327 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1328 1329 gl.endQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW); 1330 1331 if (supportsTransformFeedback3()) 1332 { 1333 for (GLuint i = 0; i < getMaxVertexStreams(); ++i) 1334 { 1335 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW, i); 1336 } 1337 } 1338 } 1339 1340 /* Draws a set of points to vertex stream #0 while having the overflow queries active. */ 1341 void drawPoints(GLsizei count) 1342 { 1343 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1344 1345 beginQueries(); 1346 gl.drawArrays(GL_POINTS, 0, count); 1347 endQueries(); 1348 } 1349 1350 /* Draws a set of triangles to vertex stream #0 while having the overflow queries active. */ 1351 void drawTriangles(GLsizei count) 1352 { 1353 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1354 1355 beginQueries(); 1356 gl.drawArrays(GL_TRIANGLES, 0, count * 3); 1357 endQueries(); 1358 } 1359 1360 /* Vertex shader to use for transform feedback. */ 1361 virtual const char* transformFeedbackVertexShader() = 0; 1362 1363 /* Geometry shader to use for transform feedback. */ 1364 virtual const char* transformFeedbackGeometryShader() = 0; 1365 1366 /* Returns the number of transform feedback varyings. */ 1367 virtual GLsizei varyingsCount() = 0; 1368 1369 /* Returns the array of transform feedback varying names. */ 1370 virtual const char** varyings() = 0; 1371 1372 /* Returns the transform feedback buffer mode. */ 1373 virtual GLenum bufferMode() = 0; 1374 1375 /* Returns the number of transform feedback buffers. */ 1376 virtual GLsizei bufferCount() = 0; 1377 1378 /* Returns the size of the specified transform feedback buffer. */ 1379 virtual GLsizei bufferSize(GLint index) = 0; 1380 1381 protected: 1382 GLuint m_overflow_query; 1383 GLuint* m_stream_overflow_query; 1384 GLuint m_query_buffer; 1385 GLsizei m_tf_buffer_count; 1386 GLuint* m_tf_buffer; 1387 GLuint m_vao; 1388 GLuint m_program; 1389 glu::ShaderProgram* m_checker_program; 1390 }; 1391 1392 /* 1393 Base class for all single stream test cases. 1394 */ 1395 class TransformFeedbackOverflowQuerySingleStreamBase : public TransformFeedbackOverflowQueryFunctionalBase 1396 { 1397 protected: 1398 TransformFeedbackOverflowQuerySingleStreamBase(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api, 1399 const char* name, const char* description) 1400 : TransformFeedbackOverflowQueryFunctionalBase(context, api, name, description) 1401 { 1402 } 1403 1404 /* Vertex shader to use for transform feedback. */ 1405 virtual const char* transformFeedbackVertexShader() 1406 { 1407 return "#version 150 core\n" 1408 "out float output1;\n" 1409 "out float output2;\n" 1410 "out float output3;\n" 1411 "out float output4;\n" 1412 "void main() {\n" 1413 " output1 = 1.0;\n" 1414 " output2 = 2.0;\n" 1415 " output3 = 3.0;\n" 1416 " output4 = 4.0;\n" 1417 "}"; 1418 } 1419 1420 /* No geometry shader for single stream test cases. */ 1421 virtual const char* transformFeedbackGeometryShader() 1422 { 1423 return NULL; 1424 } 1425 1426 /* There are a total of 4 varyings. */ 1427 virtual GLsizei varyingsCount() 1428 { 1429 return 4; 1430 } 1431 1432 /* The varying name list contains all outputs in order. */ 1433 virtual const char** varyings() 1434 { 1435 static const char* vars[] = { "output1", "output2", "output3", "output4" }; 1436 return vars; 1437 } 1438 }; 1439 1440 /* 1441 Test case #1 - Basic single stream, interleaved attributes. 1442 */ 1443 class TransformFeedbackOverflowQueryBasicSingleStreamInterleavedAttribs 1444 : public TransformFeedbackOverflowQuerySingleStreamBase 1445 { 1446 public: 1447 TransformFeedbackOverflowQueryBasicSingleStreamInterleavedAttribs(deqp::Context& context, 1448 TransformFeedbackOverflowQueryTests::API api, 1449 const char* name) 1450 : TransformFeedbackOverflowQuerySingleStreamBase(context, api, name, 1451 "Basic single stream, interleaved attributes.") 1452 { 1453 } 1454 1455 /* Use interleaved attributes. */ 1456 virtual GLenum bufferMode() 1457 { 1458 return GL_INTERLEAVED_ATTRIBS; 1459 } 1460 1461 /* A single transform feedback buffer is enough. */ 1462 virtual GLsizei bufferCount() 1463 { 1464 return 1; 1465 } 1466 1467 /* The transform feedback buffer should be able to capture exactly 10 vertices. */ 1468 virtual GLsizei bufferSize(GLint index) 1469 { 1470 (void)index; 1471 return static_cast<GLsizei>(10 * sizeof(GLfloat) * varyingsCount()); 1472 } 1473 1474 /* Test case iterate function. Contains the actual test case logic. */ 1475 IterateResult iterate() 1476 { 1477 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1478 1479 // Call BeginTransformFeedback with mode POINTS. 1480 gl.beginTransformFeedback(GL_POINTS); 1481 1482 // Start the query, submit draw that results in feeding back exactly 10 1483 // points, then stop the query. 1484 drawPoints(10); 1485 1486 // Call EndTransformFeedback. 1487 gl.endTransformFeedback(); 1488 1489 // Use the basic checking mechanism to validate that the result of the 1490 // query is FALSE. 1491 verifyQueryResults(GL_FALSE); 1492 1493 // Repeat the above steps, but this time feed back more than 10 vertices 1494 // and expect the result of the query to be TRUE. 1495 gl.beginTransformFeedback(GL_POINTS); 1496 drawPoints(11); 1497 gl.endTransformFeedback(); 1498 verifyQueryResults(GL_TRUE); 1499 1500 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1501 1502 return STOP; 1503 } 1504 }; 1505 1506 /* 1507 Test case #2 - Basic single stream, separate attributes. 1508 */ 1509 class TransformFeedbackOverflowQueryBasicSingleStreamSeparateAttribs 1510 : public TransformFeedbackOverflowQuerySingleStreamBase 1511 { 1512 public: 1513 TransformFeedbackOverflowQueryBasicSingleStreamSeparateAttribs(deqp::Context& context, 1514 TransformFeedbackOverflowQueryTests::API api, 1515 const char* name) 1516 : TransformFeedbackOverflowQuerySingleStreamBase(context, api, name, 1517 "Basic single stream, separate attributes.") 1518 { 1519 } 1520 1521 /* Use separate attributes. */ 1522 virtual GLenum bufferMode() 1523 { 1524 return GL_SEPARATE_ATTRIBS; 1525 } 1526 1527 /* We need a separate buffer for each varying. */ 1528 virtual GLsizei bufferCount() 1529 { 1530 return varyingsCount(); 1531 } 1532 1533 /* One of the transform feedback buffers should be able to capture exactly 12 vertices, 1534 the others should be able to capture at least 15 vertices. */ 1535 virtual GLsizei bufferSize(GLint index) 1536 { 1537 if (index == 1) 1538 { 1539 return 12 * sizeof(GLfloat); 1540 } 1541 else 1542 { 1543 return 15 * sizeof(GLfloat); 1544 } 1545 } 1546 1547 /* Test case iterate function. Contains the actual test case logic. */ 1548 IterateResult iterate() 1549 { 1550 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1551 1552 // Call BeginTransformFeedback with mode TRIANGLES. 1553 gl.beginTransformFeedback(GL_TRIANGLES); 1554 1555 // Start the query, submit draw that results in feeding back exactly 4 1556 // triangles, then stop the query. 1557 drawTriangles(4); 1558 1559 // Call EndTransformFeedback. 1560 gl.endTransformFeedback(); 1561 1562 // Use the basic checking mechanism to validate that the result of the 1563 // query is FALSE. 1564 verifyQueryResults(GL_FALSE); 1565 1566 // Repeat the above steps, but this time feed back exactly 5 triangles 1567 // and expect the result of the query to be TRUE. 1568 gl.beginTransformFeedback(GL_TRIANGLES); 1569 drawTriangles(5); 1570 gl.endTransformFeedback(); 1571 verifyQueryResults(GL_TRUE); 1572 1573 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1574 1575 return STOP; 1576 } 1577 }; 1578 1579 /* 1580 Test case #3 - Advanced single stream, interleaved attributes. 1581 */ 1582 class TransformFeedbackOverflowQueryAdvancedSingleStreamInterleavedAttribs 1583 : public TransformFeedbackOverflowQuerySingleStreamBase 1584 { 1585 public: 1586 TransformFeedbackOverflowQueryAdvancedSingleStreamInterleavedAttribs(deqp::Context& context, 1587 TransformFeedbackOverflowQueryTests::API api, 1588 const char* name) 1589 : TransformFeedbackOverflowQuerySingleStreamBase(context, api, name, 1590 "Advanced single stream, interleaved attributes.") 1591 { 1592 } 1593 1594 /* Use interleaved attributes. */ 1595 virtual GLenum bufferMode() 1596 { 1597 return GL_INTERLEAVED_ATTRIBS; 1598 } 1599 1600 /* A single transform feedback buffer is enough. */ 1601 virtual GLsizei bufferCount() 1602 { 1603 return 1; 1604 } 1605 1606 /* The transform feedback buffer should be able to capture exactly 10 vertices. */ 1607 virtual GLsizei bufferSize(GLint index) 1608 { 1609 (void)index; 1610 return static_cast<GLsizei>(10 * sizeof(GLfloat) * varyingsCount()); 1611 } 1612 1613 /* Test case iterate function. Contains the actual test case logic. */ 1614 IterateResult iterate() 1615 { 1616 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1617 1618 // If GL 4.0 and ARB_transform_feedback2 are not supported then skip this 1619 // test case. 1620 if (!supportsTransformFeedback2()) 1621 { 1622 throw tcu::NotSupportedError("Required transform_feedback2 extension is not supported"); 1623 } 1624 1625 // Call BeginTransformFeedback with mode POINTS. 1626 gl.beginTransformFeedback(GL_POINTS); 1627 1628 // Start the query, submit draw that results in feeding back exactly 8 1629 // triangles, then stop the query. 1630 drawPoints(8); 1631 1632 // Call PauseTransformFeedback. 1633 gl.pauseTransformFeedback(); 1634 1635 // Use the basic checking mechanism to validate that the result of the 1636 // query is FALSE. 1637 verifyQueryResults(GL_FALSE); 1638 1639 // Start the query, submit draw that would result in feeding back more than 1640 // 10 points if transform feedback wasn't paused, then stop the query. 1641 drawPoints(11); 1642 1643 // Use the basic checking mechanism to validate that the result of the 1644 // query is FALSE. 1645 verifyQueryResults(GL_FALSE); 1646 1647 // Call ResumeTransformFeedback. 1648 gl.resumeTransformFeedback(); 1649 1650 // Start the query, submit draw that results in feeding back exactly 1 1651 // point, then stop the query. 1652 drawPoints(1); 1653 1654 // Call PauseTransformFeedback. 1655 gl.pauseTransformFeedback(); 1656 1657 // Use the basic checking mechanism to validate that the result of the 1658 // query is FALSE. 1659 verifyQueryResults(GL_FALSE); 1660 1661 // Call ResumeTransformFeedback. 1662 gl.resumeTransformFeedback(); 1663 1664 // Start the query, submit draw that results in feeding back exactly 2 1665 // point, then stop the query. 1666 drawPoints(2); 1667 1668 // Call EndTransformFeedback. 1669 gl.endTransformFeedback(); 1670 1671 // Use the basic checking mechanism to validate that the result of the 1672 // query is TRUE. 1673 verifyQueryResults(GL_TRUE); 1674 1675 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1676 1677 return STOP; 1678 } 1679 }; 1680 1681 /* 1682 Test case #4 - Advanced single stream, separate attributes. 1683 */ 1684 class TransformFeedbackOverflowQueryAdvancedSingleStreamSeparateAttribs 1685 : public TransformFeedbackOverflowQuerySingleStreamBase 1686 { 1687 public: 1688 TransformFeedbackOverflowQueryAdvancedSingleStreamSeparateAttribs(deqp::Context& context, 1689 TransformFeedbackOverflowQueryTests::API api, 1690 const char* name) 1691 : TransformFeedbackOverflowQuerySingleStreamBase(context, api, name, 1692 "Advanced single stream, separate attributes.") 1693 { 1694 } 1695 1696 /* Use separate attributes. */ 1697 virtual GLenum bufferMode() 1698 { 1699 return GL_SEPARATE_ATTRIBS; 1700 } 1701 1702 /* We need a separate buffer for each varying. */ 1703 virtual GLsizei bufferCount() 1704 { 1705 return varyingsCount(); 1706 } 1707 1708 /* One of the transform feedback buffers should be able to capture exactly 12 vertices, 1709 the others should be able to capture at least 15 vertices. */ 1710 virtual GLsizei bufferSize(GLint index) 1711 { 1712 if (index == 2) 1713 { 1714 return 12 * sizeof(GLfloat); 1715 } 1716 else 1717 { 1718 return 15 * sizeof(GLfloat); 1719 } 1720 } 1721 1722 /* Test case iterate function. Contains the actual test case logic. */ 1723 IterateResult iterate() 1724 { 1725 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1726 1727 // If GL 4.0 and ARB_transform_feedback2 are not supported then skip this 1728 // test case. 1729 if (!supportsTransformFeedback2()) 1730 { 1731 throw tcu::NotSupportedError("Required transform_feedback2 extension is not supported"); 1732 } 1733 1734 // Call BeginTransformFeedback with mode TRIANGLES. 1735 gl.beginTransformFeedback(GL_TRIANGLES); 1736 1737 // Start the query, submit draw that results in feeding back exactly 2 1738 // triangles, then stop the query. 1739 drawTriangles(2); 1740 1741 // Call PauseTransformFeedback. 1742 gl.pauseTransformFeedback(); 1743 1744 // Use the basic checking mechanism to validate that the result of the 1745 // query is FALSE. 1746 verifyQueryResults(GL_FALSE); 1747 1748 // Start the query, submit draw that would result in feeding back more than 1749 // 4 triangles if transform feedback wasn't paused, then stop the query. 1750 drawTriangles(4); 1751 1752 // Use the basic checking mechanism to validate that the result of the 1753 // query is FALSE. 1754 verifyQueryResults(GL_FALSE); 1755 1756 // Call ResumeTransformFeedback. 1757 gl.resumeTransformFeedback(); 1758 1759 // Start the query, submit draw that results in feeding back exactly 2 1760 // triangles, then stop the query. 1761 drawTriangles(2); 1762 1763 // Call PauseTransformFeedback. 1764 gl.pauseTransformFeedback(); 1765 1766 // Use the basic checking mechanism to validate that the result of the 1767 // query is FALSE. 1768 verifyQueryResults(GL_FALSE); 1769 1770 // Call ResumeTransformFeedback. 1771 gl.resumeTransformFeedback(); 1772 1773 // Start the query, submit draw that results in feeding back exactly 1 1774 // triangles, then stop the query. 1775 drawTriangles(1); 1776 1777 // Call EndTransformFeedback. 1778 gl.endTransformFeedback(); 1779 1780 // Use the basic checking mechanism to validate that the result of the 1781 // query is TRUE. 1782 verifyQueryResults(GL_TRUE); 1783 1784 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1785 1786 return STOP; 1787 } 1788 }; 1789 1790 /* 1791 Base class for all multiple stream test cases. 1792 */ 1793 class TransformFeedbackOverflowQueryMultipleStreamsBase : public TransformFeedbackOverflowQueryFunctionalBase 1794 { 1795 protected: 1796 TransformFeedbackOverflowQueryMultipleStreamsBase(deqp::Context& context, 1797 TransformFeedbackOverflowQueryTests::API api, const char* name, 1798 const char* description) 1799 : TransformFeedbackOverflowQueryFunctionalBase(context, api, name, description) 1800 { 1801 } 1802 1803 /* Vertex shader to use for transform feedback. */ 1804 virtual const char* transformFeedbackVertexShader() 1805 { 1806 return "#version 150 core\n" 1807 "void main() {\n" 1808 "}"; 1809 } 1810 1811 /* Use interleaved attributes. */ 1812 virtual GLenum bufferMode() 1813 { 1814 return GL_INTERLEAVED_ATTRIBS; 1815 } 1816 1817 /* Always use 4 transform feedback buffers. */ 1818 virtual GLsizei bufferCount() 1819 { 1820 return 4; 1821 } 1822 1823 /* Draws a set of points to each vertex stream while having the overflow queries active. */ 1824 void drawStreams(GLsizei count0, GLsizei count1 = 0, GLsizei count2 = 0, GLsizei count3 = 0) 1825 { 1826 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1827 1828 GLint streamLoc = gl.getUniformLocation(m_program, "stream"); 1829 1830 beginQueries(); 1831 1832 gl.uniform1ui(streamLoc, 0); 1833 gl.drawArrays(GL_POINTS, 0, count0); 1834 1835 gl.uniform1ui(streamLoc, 1); 1836 gl.drawArrays(GL_POINTS, 0, count1); 1837 1838 gl.uniform1ui(streamLoc, 2); 1839 gl.drawArrays(GL_POINTS, 0, count2); 1840 1841 gl.uniform1ui(streamLoc, 3); 1842 gl.drawArrays(GL_POINTS, 0, count3); 1843 1844 endQueries(); 1845 } 1846 }; 1847 1848 /* 1849 Test case #5 - Advanced multiple streams, one buffer per stream. 1850 */ 1851 class TransformFeedbackOverflowQueryMultipleStreamsOneBufferPerStream 1852 : public TransformFeedbackOverflowQueryMultipleStreamsBase 1853 { 1854 public: 1855 TransformFeedbackOverflowQueryMultipleStreamsOneBufferPerStream(deqp::Context& context, 1856 TransformFeedbackOverflowQueryTests::API api, 1857 const char* name) 1858 : TransformFeedbackOverflowQueryMultipleStreamsBase(context, api, name, 1859 "Advanced multiple streams, one buffer per stream.") 1860 { 1861 } 1862 1863 /* Geometry shader to use for transform feedback. */ 1864 virtual const char* transformFeedbackGeometryShader() 1865 { 1866 return "#version 150 core\n" 1867 "#extension GL_ARB_gpu_shader5 : require\n" 1868 "layout(points) in;\n" 1869 "layout(points, max_vertices = 1) out;\n" 1870 "layout(stream=0) out float output1;\n" 1871 "layout(stream=1) out float output2;\n" 1872 "layout(stream=2) out float output3;\n" 1873 "layout(stream=3) out float output4;\n" 1874 "uniform uint stream;\n" 1875 "void main() {\n" 1876 " if (stream == 0) {\n" 1877 " output1 = 1.0;\n" 1878 " EmitStreamVertex(0);\n" 1879 " EndStreamPrimitive(0);\n" 1880 " }\n" 1881 " if (stream == 1) {\n" 1882 " output2 = 2.0;\n" 1883 " EmitStreamVertex(1);\n" 1884 " EndStreamPrimitive(1);\n" 1885 " }\n" 1886 " if (stream == 2) {\n" 1887 " output3 = 3.0;\n" 1888 " EmitStreamVertex(2);\n" 1889 " EndStreamPrimitive(2);\n" 1890 " }\n" 1891 " if (stream == 3) {\n" 1892 " output4 = 4.0;\n" 1893 " EmitStreamVertex(3);\n" 1894 " EndStreamPrimitive(3);\n" 1895 " }\n" 1896 "}"; 1897 } 1898 1899 /* Together with the separators there are a total of 7 varyings. */ 1900 virtual GLsizei varyingsCount() 1901 { 1902 return 7; 1903 } 1904 1905 /* Each output goes to different buffer. The mapping between vertex stream outputs and transform feedback buffers is non-identity. */ 1906 virtual const char** varyings() 1907 { 1908 static const char* vars[] = { "output4", "gl_NextBuffer", "output3", "gl_NextBuffer", 1909 "output2", "gl_NextBuffer", "output1" }; 1910 return vars; 1911 } 1912 1913 /* The size of the transform feedback buffers should be enough to be able to capture exactly 10 vertices for each vertex stream. */ 1914 virtual GLsizei bufferSize(GLint index) 1915 { 1916 (void)index; 1917 return 10 * sizeof(GLfloat); 1918 } 1919 1920 /* Test case iterate function. Contains the actual test case logic. */ 1921 IterateResult iterate() 1922 { 1923 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1924 1925 // If GL 4.0 and ARB_transform_feedback3 are not supported then skip this 1926 // test case. 1927 if (!supportsTransformFeedback3()) 1928 { 1929 throw tcu::NotSupportedError("Required transform_feedback3 extension is not supported"); 1930 } 1931 1932 // If GL 4.0 and ARB_gpu_shader5 are not supported then skip this 1933 // test case. 1934 if (!supportsGpuShader5()) 1935 { 1936 throw tcu::NotSupportedError("Required gpu_shader5 extension is not supported"); 1937 } 1938 1939 // Call BeginTransformFeedback with mode POINTS. 1940 gl.beginTransformFeedback(GL_POINTS); 1941 1942 // Start all queries, submit draw that results in feeding back exactly 8 1943 // points for all four vertex streams, then stop the queries. 1944 drawStreams(8, 8, 8, 8); 1945 1946 // Call PauseTransformFeedback. 1947 gl.pauseTransformFeedback(); 1948 1949 // Use the basic checking mechanism to validate that the result of the 1950 // queries are all FALSE. 1951 verifyQueryResults(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 1952 1953 // Start the queries, submit draw that would result in feeding back more 1954 // than 10 points for all four vertex streams if transform feedback wasn't 1955 // paused, then stop the queries. 1956 drawStreams(11, 11, 11, 11); 1957 1958 // Use the basic checking mechanism to validate that the result of the 1959 // queries are all FALSE. 1960 verifyQueryResults(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 1961 1962 // Call ResumeTransformFeedback. 1963 gl.resumeTransformFeedback(); 1964 1965 // Start the queries, submit draw that results in feeding back exactly 3 1966 // points only for vertex streams #1 and #3, then stop the queries. 1967 drawStreams(0, 3, 0, 3); 1968 1969 // Call PauseTransformFeedback. 1970 gl.pauseTransformFeedback(); 1971 1972 // Use the basic checking mechanism to validate that the result of the 1973 // queries are all FALSE, except for the TRANSFORM_FEEDBACK_OVERFLOW 1974 // query, and the TRANSFORM_FEEDBACK_STREAM_OVERFLOW queries for 1975 // vertex streams #1 and #3, which should have a TRUE result. 1976 verifyQueryResults(GL_TRUE, GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE); 1977 1978 // Call ResumeTransformFeedback. 1979 gl.resumeTransformFeedback(); 1980 1981 // Start the queries, submit draw that results in feeding back exactly 2 1982 // points only for vertex streams #0 and #2, then stop the queries. 1983 drawStreams(2, 0, 2, 0); 1984 1985 // Call PauseTransformFeedback. 1986 gl.pauseTransformFeedback(); 1987 1988 // Use the basic checking mechanism to validate that the result of the 1989 // queries are all FALSE. 1990 verifyQueryResults(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 1991 1992 // Call ResumeTransformFeedback. 1993 gl.resumeTransformFeedback(); 1994 1995 // Start the queries, submit draw that results in feeding back exactly 1 1996 // point for vertex streams #2 and #3, then stop the queries. 1997 drawStreams(0, 0, 1, 1); 1998 1999 // Call EndTransformFeedback. 2000 gl.endTransformFeedback(); 2001 2002 // Use the basic checking mechanism to validate that the result of the 2003 // queries are all FALSE, except for the TRANSFORM_FEEDBACK_OVERFLOW 2004 // query, and the TRANSFORM_FEEDBACK_STREAM_OVERFLOW queries for 2005 // vertex streams #2 and #3, which should have a TRUE result. 2006 verifyQueryResults(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE); 2007 2008 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2009 2010 return STOP; 2011 } 2012 }; 2013 2014 /* 2015 Test case #6 - Advanced multiple streams, multiple buffers per stream. 2016 */ 2017 class TransformFeedbackOverflowQueryMultipleStreamsMultipleBufferPerStream 2018 : public TransformFeedbackOverflowQueryMultipleStreamsBase 2019 { 2020 public: 2021 TransformFeedbackOverflowQueryMultipleStreamsMultipleBufferPerStream(deqp::Context& context, 2022 TransformFeedbackOverflowQueryTests::API api, 2023 const char* name) 2024 : TransformFeedbackOverflowQueryMultipleStreamsBase(context, api, name, 2025 "Advanced multiple streams, multiple buffers per stream.") 2026 { 2027 } 2028 2029 /* Geometry shader to use for transform feedback. */ 2030 virtual const char* transformFeedbackGeometryShader() 2031 { 2032 return "#version 150 core\n" 2033 "#extension GL_ARB_gpu_shader5 : require\n" 2034 "layout(points) in;\n" 2035 "layout(points, max_vertices = 1) out;\n" 2036 "layout(stream=0) out float output1;\n" 2037 "layout(stream=0) out float output2;\n" 2038 "layout(stream=1) out float output3;\n" 2039 "layout(stream=1) out float output4;\n" 2040 "uniform uint stream;\n" 2041 "void main() {\n" 2042 " if (stream == 0) {\n" 2043 " output1 = 1.0;\n" 2044 " output2 = 2.0;\n" 2045 " EmitStreamVertex(0);\n" 2046 " EndStreamPrimitive(0);\n" 2047 " }\n" 2048 " if (stream == 1) {\n" 2049 " output3 = 3.0;\n" 2050 " output4 = 4.0;\n" 2051 " EmitStreamVertex(1);\n" 2052 " EndStreamPrimitive(1);\n" 2053 " }\n" 2054 "}"; 2055 } 2056 2057 /* Together with the separators there are a total of 7 varyings. */ 2058 virtual GLsizei varyingsCount() 2059 { 2060 return 7; 2061 } 2062 2063 /* Vertex stream #0 is captured by transform feedback buffers #1 and #2, while 2064 vertex stream #1 is captured by transform feedback buffers #3 and #0. */ 2065 virtual const char** varyings() 2066 { 2067 static const char* vars[] = { "output4", "gl_NextBuffer", "output1", "gl_NextBuffer", 2068 "output2", "gl_NextBuffer", "output3" }; 2069 return vars; 2070 } 2071 2072 /* Transform feedback buffers #0 and #1 should be able to capture exactly 10 vertices, while 2073 transform feedback buffers #2 and #3 should be able to capture exactly 20 vertices. */ 2074 virtual GLsizei bufferSize(GLint index) 2075 { 2076 if (index < 2) 2077 { 2078 return 10 * sizeof(GLfloat); 2079 } 2080 else 2081 { 2082 return 20 * sizeof(GLfloat); 2083 } 2084 } 2085 2086 /* Test case iterate function. Contains the actual test case logic. */ 2087 IterateResult iterate() 2088 { 2089 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2090 2091 // If GL 4.0 and ARB_transform_feedback3 are not supported then skip this 2092 // test case. 2093 if (!supportsTransformFeedback3()) 2094 { 2095 throw tcu::NotSupportedError("Required transform_feedback3 extension is not supported"); 2096 } 2097 2098 // If GL 4.0 and ARB_gpu_shader5 are not supported then skip this 2099 // test case. 2100 if (!supportsGpuShader5()) 2101 { 2102 throw tcu::NotSupportedError("Required gpu_shader5 extension is not supported"); 2103 } 2104 2105 // Call BeginTransformFeedback with mode POINTS. 2106 gl.beginTransformFeedback(GL_POINTS); 2107 2108 // Start all queries, submit draw that results in feeding back exactly 8 2109 // points to both vertex streams, then stop the queries. 2110 drawStreams(8, 8); 2111 2112 // Call PauseTransformFeedback. 2113 gl.pauseTransformFeedback(); 2114 2115 // Use the basic checking mechanism to validate that the result of the 2116 // queries are all FALSE. 2117 verifyQueryResults(GL_FALSE, GL_FALSE, GL_FALSE); 2118 2119 // Start the queries, submit draw that would result in feeding back more 2120 // than 10 points for both vertex streams if transform feedback wasn't 2121 // paused, then stop the queries. 2122 drawStreams(11, 11); 2123 2124 // Use the basic checking mechanism to validate that the result of the 2125 // queries are all FALSE. 2126 verifyQueryResults(GL_FALSE, GL_FALSE, GL_FALSE); 2127 2128 // Call ResumeTransformFeedback. 2129 gl.resumeTransformFeedback(); 2130 2131 // Start the queries, submit draw that results in feeding back exactly 1 2132 // point for vertex stream #0 and exactly 3 points for vertex stream #1, 2133 // then stop the queries. 2134 drawStreams(1, 3); 2135 2136 // Call PauseTransformFeedback. 2137 gl.pauseTransformFeedback(); 2138 2139 // Use the basic checking mechanism to validate that the result of the 2140 // queries are all FALSE, except for the TRANSFORM_FEEDBACK_OVERFLOW 2141 // query, and the TRANSFORM_FEEDBACK_STREAM_OVERFLOW query for vertex 2142 // stream #1, which should have a TRUE result. 2143 verifyQueryResults(GL_TRUE, GL_FALSE, GL_TRUE); 2144 2145 // Call ResumeTransformFeedback. 2146 gl.resumeTransformFeedback(); 2147 2148 // Start the queries, submit draw that results in feeding back exactly 1 2149 // point only for vertex stream #0, then stop the queries. 2150 drawStreams(1, 0); 2151 2152 // Call PauseTransformFeedback. 2153 gl.pauseTransformFeedback(); 2154 2155 // Use the basic checking mechanism to validate that the result of the 2156 // queries are all FALSE. 2157 verifyQueryResults(GL_FALSE, GL_FALSE, GL_FALSE); 2158 2159 // Call ResumeTransformFeedback. 2160 gl.resumeTransformFeedback(); 2161 2162 // Start the queries, submit draw that results in feeding back exactly 1 2163 // point for vertex streams #0 and #1, then stop the queries. 2164 drawStreams(1, 1); 2165 2166 // Call EndTransformFeedback. 2167 gl.endTransformFeedback(); 2168 2169 // Use the basic checking mechanism to validate that the result of the 2170 // queries are all FALSE, except for the TRANSFORM_FEEDBACK_OVERFLOW 2171 // query, and the TRANSFORM_FEEDBACK_STREAM_OVERFLOW queries for 2172 // vertex streams #0 and #1, which should have a TRUE result. 2173 verifyQueryResults(GL_TRUE, GL_TRUE, GL_TRUE); 2174 2175 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2176 2177 return STOP; 2178 } 2179 }; 2180 2181 const char* apiToTestName(TransformFeedbackOverflowQueryTests::API api) 2182 { 2183 switch (api) 2184 { 2185 case TransformFeedbackOverflowQueryTests::API_GL_ARB_transform_feedback_overflow_query: 2186 return "transform_feedback_overflow_query_ARB"; 2187 } 2188 DE_ASSERT(0); 2189 return ""; 2190 } 2191 2192 /** Constructor. 2193 * 2194 * @param context Rendering context. 2195 * @param api API to test (core vs ARB extension) 2196 **/ 2197 TransformFeedbackOverflowQueryTests::TransformFeedbackOverflowQueryTests(deqp::Context& context, API api) 2198 : TestCaseGroup(context, apiToTestName(api), "Verifies \"transform_feedback_overflow_query\" functionality") 2199 , m_api(api) 2200 { 2201 /* Left blank on purpose */ 2202 } 2203 2204 /** Destructor. 2205 * 2206 **/ 2207 TransformFeedbackOverflowQueryTests::~TransformFeedbackOverflowQueryTests() 2208 { 2209 } 2210 2211 /** Initializes the texture_barrier test group. 2212 * 2213 **/ 2214 void TransformFeedbackOverflowQueryTests::init(void) 2215 { 2216 addChild(new TransformFeedbackOverflowQueryImplDepState(m_context, m_api, "implementation-dependent-state")); 2217 addChild(new TransformFeedbackOverflowQueryDefaultState(m_context, m_api, "default-context-state")); 2218 addChild(new TransformFeedbackOverflowQueryStateUpdate(m_context, m_api, "context-state-update")); 2219 addChild(new TransformFeedbackOverflowQueryErrorInvalidIndex(m_context, m_api, "error-invalid-index")); 2220 addChild(new TransformFeedbackOverflowQueryErrorAlreadyActive(m_context, m_api, "error-already-active")); 2221 addChild(new TransformFeedbackOverflowQueryErrorIncompatibleTarget(m_context, m_api, "error-incompatible-target")); 2222 addChild(new TransformFeedbackOverflowQueryErrorNoActiveQuery(m_context, m_api, "error-no-active-query")); 2223 addChild(new TransformFeedbackOverflowQueryBasicSingleStreamInterleavedAttribs( 2224 m_context, m_api, "basic-single-stream-interleaved-attribs")); 2225 addChild(new TransformFeedbackOverflowQueryBasicSingleStreamSeparateAttribs( 2226 m_context, m_api, "basic-single-stream-separate-attribs")); 2227 addChild(new TransformFeedbackOverflowQueryAdvancedSingleStreamInterleavedAttribs( 2228 m_context, m_api, "advanced-single-stream-interleaved-attribs")); 2229 addChild(new TransformFeedbackOverflowQueryAdvancedSingleStreamSeparateAttribs( 2230 m_context, m_api, "advanced-single-stream-separate-attribs")); 2231 addChild(new TransformFeedbackOverflowQueryMultipleStreamsOneBufferPerStream( 2232 m_context, m_api, "multiple-streams-one-buffer-per-stream")); 2233 addChild(new TransformFeedbackOverflowQueryMultipleStreamsMultipleBufferPerStream( 2234 m_context, m_api, "multiple-streams-multiple-buffers-per-stream")); 2235 } 2236 } /* glcts namespace */ 2237