1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2015-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 gl3cTransformFeedback.cpp 27 * \brief Transform Feedback Test Suite Implementation 28 */ /*-------------------------------------------------------------------*/ 29 30 /* Includes. */ 31 #include "gl3cTransformFeedbackTests.hpp" 32 #include "gluContextInfo.hpp" 33 #include "gluDefs.hpp" 34 #include "gluRenderContext.hpp" 35 #include "gluStrUtil.hpp" 36 #include "tcuTestLog.hpp" 37 38 #include <algorithm> 39 #include <climits> 40 #include <cmath> 41 #include <cstdlib> 42 #include <sstream> 43 44 /* Stringify macro. */ 45 #define _STR(s) STR(s) 46 #define STR(s) #s 47 48 /* Unused attribute / variable MACRO. 49 Some methods of clesses' heirs do not need all function parameters. 50 This triggers warnings on GCC platform. This macro will silence them. 51 */ 52 #ifdef __GNUC__ 53 #define UNUSED __attribute__((__unused__)) 54 #else 55 #define UNUSED 56 #endif 57 58 gl3cts::TransformFeedback::Tests::Tests(deqp::Context& context) 59 : TestCaseGroup(context, "transform_feedback", "Transform Feedback Test Suite") 60 { 61 addChild(new TransformFeedback::APIErrors(m_context)); 62 addChild(new TransformFeedback::LinkingErrors(m_context)); 63 addChild(new TransformFeedback::Limits(m_context)); 64 addChild(new TransformFeedback::CaptureVertexInterleaved(m_context, "capture_vertex_interleaved_test", 65 "Transform Feedback Capture Vertex Interleaved Test")); 66 addChild(new TransformFeedback::CaptureGeometryInterleaved(m_context, "capture_geometry_interleaved_test", 67 "Transform Feedback Capture Geometry Interleaved Test")); 68 addChild(new TransformFeedback::CaptureVertexSeparate(m_context, "capture_vertex_separate_test", 69 "Transform Feedback Capture Vertex Separate Test")); 70 addChild(new TransformFeedback::CaptureGeometrySeparate(m_context, "capture_geometry_separate_test", 71 "Transform Feedback Capture Geometry Separate Test")); 72 addChild(new TransformFeedback::CheckGetXFBVarying(m_context, "get_xfb_varying", 73 "Transform Feedback Varying Getters Test")); 74 addChild(new TransformFeedback::QueryVertexInterleaved(m_context, "query_vertex_interleaved_test", 75 "Transform Feedback Query Vertex Interleaved Test")); 76 addChild(new TransformFeedback::QueryGeometryInterleaved(m_context, "query_geometry_interleaved_test", 77 "Transform Feedback Query Geometry Interleaved Test")); 78 addChild(new TransformFeedback::QueryVertexSeparate(m_context, "query_vertex_separate_test", 79 "Transform Feedback Query Vertex Separate Test")); 80 addChild(new TransformFeedback::QueryGeometrySeparate(m_context, "query_geometry_separate_test", 81 "Transform Feedback Query Geometry Separate Test")); 82 addChild(new TransformFeedback::DiscardVertex(m_context, "discard_vertex_test", 83 "Transform Feedback Discard Vertex Test")); 84 addChild(new TransformFeedback::DiscardGeometry(m_context, "discard_geometry_test", 85 "Transform Feedback Discard Geometry Test")); 86 addChild(new TransformFeedback::DrawXFB(m_context, "draw_xfb_test", "Transform Feedback Draw Test")); 87 addChild(new TransformFeedback::DrawXFBFeedback(m_context, "draw_xfb_feedbackk_test", 88 "Transform Feedback Draw Feedback Test")); 89 addChild( 90 new TransformFeedback::DrawXFBStream(m_context, "draw_xfb_stream_test", "Transform Feedback Draw Stream Test")); 91 addChild(new TransformFeedback::CaptureSpecialInterleaved(m_context, "capture_special_interleaved_test", 92 "Transform Feedback Capture Special Test")); 93 addChild(new TransformFeedback::DrawXFBInstanced(m_context, "draw_xfb_instanced_test", 94 "Transform Feedback Draw Instanced Test")); 95 addChild(new TransformFeedback::DrawXFBStreamInstanced(m_context, "draw_xfb_stream_instanced_test", 96 "Transform Feedback Draw Stream Instanced Test")); 97 } 98 99 gl3cts::TransformFeedback::Tests::~Tests(void) 100 { 101 } 102 103 void gl3cts::TransformFeedback::Tests::init(void) 104 { 105 } 106 107 gl3cts::TransformFeedback::APIErrors::APIErrors(deqp::Context& context) 108 : deqp::TestCase(context, "api_errors_test", "Transform Feedback API Errors Test") 109 , m_context(context) 110 , m_buffer_0(0) 111 , m_buffer_1(0) 112 , m_vertex_array_object(0) 113 , m_transform_feedback_object_0(0) 114 , m_transform_feedback_object_1(0) 115 , m_query_object(0) 116 , m_program_id_with_input_output(0) 117 , m_program_id_with_output(0) 118 , m_program_id_without_output(0) 119 , m_program_id_with_geometry_shader(0) 120 , m_program_id_with_tessellation_shaders(0) 121 , m_glBindBufferOffsetEXT(DE_NULL) 122 , m_glGetIntegerIndexedvEXT(DE_NULL) 123 , m_glGetBooleanIndexedvEXT(DE_NULL) 124 { 125 } 126 127 gl3cts::TransformFeedback::APIErrors::~APIErrors(void) 128 { 129 } 130 131 tcu::TestNode::IterateResult gl3cts::TransformFeedback::APIErrors::iterate(void) 132 { 133 /* Functions handler */ 134 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 135 136 /* Initializations. */ 137 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0))); 138 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 139 bool is_at_least_gl_42 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2))); 140 141 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback"); 142 bool is_arb_tf_2 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2"); 143 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3"); 144 bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced"); 145 146 if (is_ext_tf_1) 147 { 148 /* Extension query. */ 149 m_glBindBufferOffsetEXT = 150 (BindBufferOffsetEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glBindBufferOffsetEXT"); 151 m_glGetIntegerIndexedvEXT = 152 (GetIntegerIndexedvEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glGetIntegerIndexedvEXT"); 153 m_glGetBooleanIndexedvEXT = 154 (GetBooleanIndexedvEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glGetBooleanIndexedvEXT"); 155 } 156 157 if (is_at_least_gl_40 || is_arb_tf_2) 158 { 159 /* Create transform feedback objects. */ 160 gl.genTransformFeedbacks(1, &m_transform_feedback_object_0); 161 162 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 163 } 164 165 if (is_at_least_gl_40 || is_arb_tf_3) 166 { 167 /* Create query object. */ 168 gl.genQueries(1, &m_query_object); 169 170 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed."); 171 } 172 173 if (is_at_least_gl_42 || is_arb_tf_instanced) 174 { 175 /* Create transform feedback objects. */ 176 gl.genTransformFeedbacks(1, &m_transform_feedback_object_1); 177 178 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 179 } 180 181 /* Default result. */ 182 bool is_ok = true; 183 bool test_error = false; 184 185 /* Entities setup. */ 186 try 187 { 188 /* VAO setup. */ 189 gl.genVertexArrays(1, &m_vertex_array_object); 190 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 191 192 gl.bindVertexArray(m_vertex_array_object); 193 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 194 195 /* Buffer setup. */ 196 gl.genBuffers(1, &m_buffer_0); 197 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 198 199 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_0); 200 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 201 202 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 16, NULL, GL_STATIC_DRAW); 203 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 204 205 gl.genBuffers(1, &m_buffer_1); 206 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 207 208 gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_1); 209 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 210 211 gl.bufferData(GL_ARRAY_BUFFER, m_buffer_1_size, m_buffer_1_data, GL_STATIC_DRAW); 212 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 213 214 /* Programs setup. */ 215 216 m_program_id_with_input_output = gl3cts::TransformFeedback::Utilities::buildProgram( 217 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_with_input_output, 218 s_fragment_shader, &m_varying_name, 1, GL_INTERLEAVED_ATTRIBS); 219 220 m_program_id_with_output = gl3cts::TransformFeedback::Utilities::buildProgram( 221 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_with_output, s_fragment_shader, 222 &m_varying_name, 1, GL_INTERLEAVED_ATTRIBS, true); 223 224 m_program_id_without_output = gl3cts::TransformFeedback::Utilities::buildProgram( 225 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_without_output, 226 s_fragment_shader, NULL, 0, GL_SEPARATE_ATTRIBS); 227 228 m_program_id_with_geometry_shader = gl3cts::TransformFeedback::Utilities::buildProgram( 229 gl, m_context.getTestContext().getLog(), m_geometry_shader, NULL, NULL, s_vertex_shader_without_output, 230 s_fragment_shader, &m_varying_name, 1, GL_INTERLEAVED_ATTRIBS); 231 232 m_program_id_with_tessellation_shaders = gl3cts::TransformFeedback::Utilities::buildProgram( 233 gl, m_context.getTestContext().getLog(), NULL, m_tessellation_control_shader, 234 m_tessellation_evaluation_shader, s_vertex_shader_without_output, s_fragment_shader, &m_varying_name, 1, 235 GL_INTERLEAVED_ATTRIBS); 236 237 is_ok = is_ok && m_program_id_with_input_output && m_program_id_with_output && m_program_id_without_output && 238 m_program_id_with_geometry_shader && m_program_id_with_tessellation_shaders; 239 } 240 catch (...) 241 { 242 is_ok = false; 243 test_error = true; 244 } 245 246 /* Iterating tests. */ 247 try 248 { 249 if (is_at_least_gl_30 || is_ext_tf_1) 250 { 251 is_ok = is_ok && testExtension1(); 252 } 253 254 if (is_at_least_gl_40 || is_arb_tf_2) 255 { 256 is_ok = is_ok && testExtension2(); 257 } 258 259 if (is_at_least_gl_40 || is_arb_tf_3) 260 { 261 is_ok = is_ok && testExtension3(); 262 } 263 264 if (is_at_least_gl_42 || is_arb_tf_instanced) 265 { 266 is_ok = is_ok && testInstanced(); 267 } 268 } 269 catch (...) 270 { 271 is_ok = false; 272 test_error = true; 273 } 274 275 /* Deinitialization. */ 276 if (m_vertex_array_object) 277 { 278 gl.deleteVertexArrays(1, &m_vertex_array_object); 279 280 m_vertex_array_object = 0; 281 } 282 283 if (m_buffer_0) 284 { 285 gl.deleteBuffers(1, &m_buffer_0); // silently unbinds 286 287 m_buffer_0 = 0; 288 } 289 290 if (m_buffer_1) 291 { 292 gl.deleteBuffers(1, &m_buffer_1); // silently unbinds 293 294 m_buffer_1 = 0; 295 } 296 297 if (m_transform_feedback_object_0) 298 { 299 gl.deleteTransformFeedbacks(1, &m_transform_feedback_object_0); 300 301 m_transform_feedback_object_0 = 0; 302 } 303 304 if (m_transform_feedback_object_1) 305 { 306 gl.deleteTransformFeedbacks(1, &m_transform_feedback_object_1); 307 308 m_transform_feedback_object_1 = 0; 309 } 310 311 if (m_query_object) 312 { 313 gl.deleteQueries(1, &m_query_object); 314 315 m_query_object = 0; 316 } 317 318 if (m_program_id_with_input_output) 319 { 320 gl.deleteProgram(m_program_id_with_input_output); 321 322 m_program_id_with_input_output = 0; 323 } 324 325 if (m_program_id_with_output) 326 { 327 gl.deleteProgram(m_program_id_with_output); 328 329 m_program_id_with_output = 0; 330 } 331 332 if (m_program_id_without_output) 333 { 334 gl.deleteProgram(m_program_id_without_output); 335 336 m_program_id_without_output = 0; 337 } 338 339 if (m_program_id_with_geometry_shader) 340 { 341 gl.deleteProgram(m_program_id_with_geometry_shader); 342 343 m_program_id_with_geometry_shader = 0; 344 } 345 346 if (m_program_id_with_tessellation_shaders) 347 { 348 gl.deleteProgram(m_program_id_with_tessellation_shaders); 349 350 m_program_id_with_tessellation_shaders = 0; 351 } 352 353 /* Result's setup. */ 354 if (is_ok) 355 { 356 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 357 } 358 else 359 { 360 if (test_error) 361 { 362 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 363 } 364 else 365 { 366 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 367 } 368 } 369 370 return STOP; 371 } 372 373 bool gl3cts::TransformFeedback::APIErrors::testExtension1(void) 374 { 375 /* Functions handler */ 376 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 377 378 /* INVALID_VALUE is generated by BindBufferRange, BindBufferOffset and 379 BindBufferBase when <index> is greater or equal to 380 MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS; */ 381 382 glw::GLint index_count = 0; 383 384 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &index_count); 385 386 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 387 388 if (index_count == 0) 389 { 390 m_context.getTestContext().getLog() << tcu::TestLog::Message << "glGetIntegerv did not returned any value." 391 << tcu::TestLog::EndMessage; 392 throw 0; 393 } 394 395 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0, 16); 396 397 if (GL_INVALID_VALUE != gl.getError()) 398 { 399 m_context.getTestContext().getLog() << tcu::TestLog::Message 400 << "INVALID_VALUE was not generated by BindBufferRange " 401 "when <index> was greater or equal to " 402 "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS." 403 << tcu::TestLog::EndMessage; 404 return false; 405 } 406 407 if (DE_NULL != m_glBindBufferOffsetEXT) 408 { 409 m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0); 410 411 if (GL_INVALID_VALUE != gl.getError()) 412 { 413 m_context.getTestContext().getLog() << tcu::TestLog::Message 414 << "INVALID_VALUE was not generated by BindBufferOffset " 415 "when <index> was greater or equal to " 416 "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS." 417 << tcu::TestLog::EndMessage; 418 return false; 419 } 420 } 421 422 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0); 423 424 if (GL_INVALID_VALUE != gl.getError()) 425 { 426 m_context.getTestContext().getLog() << tcu::TestLog::Message 427 << "INVALID_VALUE was not generated by " 428 "BindBufferBase when <index> was greater or equal to " 429 "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS." 430 << tcu::TestLog::EndMessage; 431 return false; 432 } 433 434 /* INVALID_VALUE is generated by BindBufferRange when <size> is less or equal to zero; */ 435 436 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0, 0); 437 438 if (GL_INVALID_VALUE != gl.getError()) 439 { 440 m_context.getTestContext().getLog() 441 << tcu::TestLog::Message 442 << "INVALID_VALUE was not generated by BindBufferRange when <size> was less or equal to zero." 443 << tcu::TestLog::EndMessage; 444 return false; 445 } 446 447 /* INVALID_VALUE is generated by BindBufferRange and BindBufferOffset 448 when <offset> is not word-aligned; */ 449 450 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 3, 4); 451 452 if (GL_INVALID_VALUE != gl.getError()) 453 { 454 m_context.getTestContext().getLog() 455 << tcu::TestLog::Message 456 << "INVALID_VALUE was not generated by BindBufferRange when <offset> was not word-aligned." 457 << tcu::TestLog::EndMessage; 458 return false; 459 } 460 461 if (DE_NULL != m_glBindBufferOffsetEXT) 462 { 463 m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 3); 464 465 if (GL_INVALID_VALUE != gl.getError()) 466 { 467 m_context.getTestContext().getLog() 468 << tcu::TestLog::Message 469 << "INVALID_VALUE was not generated by BindBufferOffset when <offset> was not word-aligned." 470 << tcu::TestLog::EndMessage; 471 return false; 472 } 473 } 474 475 /* INVALID_VALUE is generated by BindBufferRange when <size> is not word-aligned; */ 476 477 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0, 3); 478 479 if (GL_INVALID_VALUE != gl.getError()) 480 { 481 m_context.getTestContext().getLog() 482 << tcu::TestLog::Message 483 << "INVALID_VALUE was not generated by BindBufferRange when <size> was not word-aligned." 484 << tcu::TestLog::EndMessage; 485 return false; 486 } 487 488 /* INVALID_OPERATION is generated by BindBufferRange, BindBufferOffset and 489 BindBufferBase when <target> is TRANSFORM_FEEDBACK_BUFFER and transform 490 feedback is active; */ 491 492 gl.useProgram(m_program_id_with_output); 493 494 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 495 496 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0); 497 498 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 499 500 gl.beginTransformFeedback(GL_POINTS); 501 502 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 503 504 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0, 0, 16); 505 506 if (GL_INVALID_OPERATION != gl.getError()) 507 { 508 m_context.getTestContext().getLog() << tcu::TestLog::Message 509 << "INVALID_OPERATION was not generated by BindBufferRange " 510 "when <target> was TRANSFORM_FEEDBACK_BUFFER and transform " 511 "feedback was active." 512 << tcu::TestLog::EndMessage; 513 514 gl.endTransformFeedback(); 515 516 return false; 517 } 518 519 if (DE_NULL != m_glBindBufferOffsetEXT) 520 { 521 m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0, 0); 522 523 if (GL_INVALID_OPERATION != gl.getError()) 524 { 525 m_context.getTestContext().getLog() << tcu::TestLog::Message 526 << "INVALID_OPERATION was not generated by BindBufferOffset " 527 "when <target> was TRANSFORM_FEEDBACK_BUFFER and transform " 528 "feedback was active." 529 << tcu::TestLog::EndMessage; 530 531 gl.endTransformFeedback(); 532 533 return false; 534 } 535 } 536 537 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0); 538 539 if (GL_INVALID_OPERATION != gl.getError()) 540 { 541 m_context.getTestContext().getLog() 542 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by " 543 "BindBufferBase when <target> was TRANSFORM_FEEDBACK_BUFFER and transform " 544 "feedback was active." 545 << tcu::TestLog::EndMessage; 546 547 gl.endTransformFeedback(); 548 549 return false; 550 } 551 552 gl.endTransformFeedback(); 553 554 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 555 556 /* INVALID_OPERATION is generated by UseProgram when transform feedback is 557 active; */ 558 559 gl.beginTransformFeedback(GL_POINTS); 560 561 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 562 563 gl.useProgram(0); 564 565 if (GL_INVALID_OPERATION != gl.getError()) 566 { 567 m_context.getTestContext().getLog() 568 << tcu::TestLog::Message 569 << "INVALID_OPERATION was not generated by UseProgram when transform feedback was active." 570 << tcu::TestLog::EndMessage; 571 572 gl.endTransformFeedback(); 573 574 return false; 575 } 576 577 gl.endTransformFeedback(); 578 579 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 580 581 /* INVALID_OPERATION is generated by LinkProgram when <program> is currently 582 active and transform feedback is active; */ 583 584 gl.useProgram(m_program_id_with_output); 585 586 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 587 588 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0); 589 590 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 591 592 gl.beginTransformFeedback(GL_POINTS); 593 594 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 595 596 gl.linkProgram(m_program_id_with_output); 597 598 if (GL_INVALID_OPERATION != gl.getError()) 599 { 600 m_context.getTestContext().getLog() << tcu::TestLog::Message 601 << "INVALID_OPERATION was not generated by LinkProgram when <program> was " 602 "currently active and transform feedback was active." 603 << tcu::TestLog::EndMessage; 604 605 gl.endTransformFeedback(); 606 607 return false; 608 } 609 610 gl.endTransformFeedback(); 611 612 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 613 614 /* INVALID_OPERATION is generated by BeginTransformFeedback when transform 615 feedback is active; */ 616 617 gl.useProgram(m_program_id_with_output); 618 619 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 620 621 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0); 622 623 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 624 625 gl.beginTransformFeedback(GL_POINTS); 626 627 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 628 629 gl.beginTransformFeedback(GL_POINTS); 630 631 if (GL_INVALID_OPERATION != gl.getError()) 632 { 633 m_context.getTestContext().getLog() 634 << tcu::TestLog::Message 635 << "INVALID_OPERATION was not generated by BeginTransformFeedback when transform feedback was active." 636 << tcu::TestLog::EndMessage; 637 638 gl.endTransformFeedback(); 639 640 return false; 641 } 642 643 gl.endTransformFeedback(); 644 645 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 646 647 /* INVALID_OPERATION is generated by EndTransformFeedback when transform 648 feedback is inactive; */ 649 650 gl.endTransformFeedback(); 651 652 if (GL_INVALID_OPERATION != gl.getError()) 653 { 654 m_context.getTestContext().getLog() 655 << tcu::TestLog::Message 656 << "INVALID_OPERATION was not generated by EndTransformFeedback when transform feedback was inactive." 657 << tcu::TestLog::EndMessage; 658 659 return false; 660 } 661 662 /* INVALID_OPERATION is generated by draw command when generated primitives 663 type does not match <primitiveMode>; */ 664 665 gl.useProgram(m_program_id_with_output); 666 667 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 668 669 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0); 670 671 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 672 673 gl.beginTransformFeedback(GL_POINTS); 674 675 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 676 677 gl.drawArrays(GL_LINES, 0, 2); 678 679 if (GL_INVALID_OPERATION != gl.getError()) 680 { 681 m_context.getTestContext().getLog() << tcu::TestLog::Message 682 << "INVALID_OPERATION was not generated by draw command when generated " 683 "primitives type does not match <primitiveMode>." 684 << tcu::TestLog::EndMessage; 685 686 gl.endTransformFeedback(); 687 688 return false; 689 } 690 691 gl.endTransformFeedback(); 692 693 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 694 695 /* INVALID_OPERATION is generated by BeginTransformFeedback when any binding 696 point used by XFB does not have buffer bound; */ 697 698 gl.useProgram(m_program_id_with_output); 699 700 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 701 702 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0); 703 704 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 705 706 gl.beginTransformFeedback(GL_POINTS); 707 708 if (GL_INVALID_OPERATION != gl.getError()) 709 { 710 m_context.getTestContext().getLog() << tcu::TestLog::Message 711 << "INVALID_OPERATION was not generated by BeginTransformFeedback when any " 712 "binding point used by XFB does not have buffer bound." 713 << tcu::TestLog::EndMessage; 714 715 return false; 716 } 717 718 /* INVALID_OPERATION is generated by BeginTransformFeedback when no program 719 is active; */ 720 721 gl.useProgram(0); 722 723 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 724 725 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0); 726 727 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 728 729 gl.beginTransformFeedback(GL_POINTS); 730 731 if (GL_INVALID_OPERATION != gl.getError()) 732 { 733 m_context.getTestContext().getLog() 734 << tcu::TestLog::Message 735 << "INVALID_OPERATION was not generated by BeginTransformFeedback when no program was active." 736 << tcu::TestLog::EndMessage; 737 738 gl.endTransformFeedback(); 739 740 return false; 741 } 742 743 /* INVALID_OPERATION is generated by BeginTransformFeedback when no variable 744 are specified to be captured in the active program; */ 745 746 gl.useProgram(m_program_id_without_output); 747 748 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 749 750 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0); 751 752 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 753 754 gl.beginTransformFeedback(GL_POINTS); 755 756 if (GL_INVALID_OPERATION != gl.getError()) 757 { 758 m_context.getTestContext().getLog() 759 << tcu::TestLog::Message 760 << "INVALID_OPERATION was not generated by BeginTransformFeedback when no variable " 761 "are specified to be captured in the active program." 762 << tcu::TestLog::EndMessage; 763 764 gl.endTransformFeedback(); 765 766 return false; 767 } 768 769 /* INVALID_VALUE is generated by TransformFeedbackVaryings when <program> is 770 not id of the program object; */ 771 772 unsigned short int invalid_name = 1; 773 774 while (gl.isProgram(invalid_name) || gl.isShader(invalid_name)) 775 { 776 ++invalid_name; 777 778 /* Make sure that this loop ends someday, bad day. */ 779 if (invalid_name == USHRT_MAX) 780 { 781 m_context.getTestContext().getLog() 782 << tcu::TestLog::Message << "Cannot find unused trnasform feedback object." << tcu::TestLog::EndMessage; 783 throw 0; 784 } 785 } 786 787 gl.transformFeedbackVaryings((glw::GLuint)invalid_name, 1, &m_varying_name, GL_INTERLEAVED_ATTRIBS); 788 789 if (GL_INVALID_VALUE != gl.getError()) 790 { 791 m_context.getTestContext().getLog() << tcu::TestLog::Message 792 << "INVALID_VALUE was not generated by TransformFeedbackVaryings when " 793 "<program> was not id of the program object." 794 << tcu::TestLog::EndMessage; 795 return false; 796 } 797 798 /* INVALID_VALUE is generated by TransformFeedbackVaryings when <bufferMode> 799 is SEPARATE_ATTRIBS and <count> is exceeds limits; */ 800 801 glw::GLint max_separate_attribs = 0; 802 803 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_separate_attribs); 804 805 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 806 807 if (max_separate_attribs == 0) 808 { 809 m_context.getTestContext().getLog() 810 << tcu::TestLog::Message << "INVALID_VALUE was not generated by TransformFeedbackVaryings when <bufferMode>" 811 " was SEPARATE_ATTRIBS and <count> was exceeds limits." 812 << tcu::TestLog::EndMessage; 813 throw 0; 814 } 815 816 glw::GLint more_than_max_separate_attribs = max_separate_attribs + 1; 817 818 glw::GLchar** attrib = new glw::GLchar*[more_than_max_separate_attribs]; 819 820 for (glw::GLint i = 0; i < more_than_max_separate_attribs; ++i) 821 { 822 std::string new_attrib = "a" + gl3cts::TransformFeedback::Utilities::itoa(i); 823 824 size_t new_attrib_size = new_attrib.size(); 825 826 attrib[i] = new glw::GLchar[new_attrib_size + 1]; 827 828 memset(attrib[i], 0, new_attrib_size + 1); 829 830 memcpy(attrib[i], new_attrib.c_str(), new_attrib_size); 831 } 832 833 gl.transformFeedbackVaryings(m_program_id_with_output, more_than_max_separate_attribs, attrib, GL_SEPARATE_ATTRIBS); 834 835 for (glw::GLint i = 0; i < more_than_max_separate_attribs; ++i) 836 { 837 delete attrib[i]; 838 } 839 840 delete[] attrib; 841 842 if (GL_INVALID_VALUE != gl.getError()) 843 { 844 m_context.getTestContext().getLog() << tcu::TestLog::Message 845 << "INVALID_VALUE was not generated by TransformFeedbackVaryings when " 846 "<bufferMode> was SEPARATE_ATTRIBS and <count> exceeded limits." 847 << tcu::TestLog::EndMessage; 848 return false; 849 } 850 851 /* INVALID_VALUE is generated by GetTransformFeedbackVarying when <index> is 852 greater than or equal to TRANSFORM_FEEDBACK_VARYINGS; */ 853 854 glw::GLint transform_feedback_varyings = 0; 855 856 gl.getProgramiv(m_program_id_with_output, GL_TRANSFORM_FEEDBACK_VARYINGS, &transform_feedback_varyings); 857 858 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed."); 859 860 if (transform_feedback_varyings == 0) 861 { 862 m_context.getTestContext().getLog() << tcu::TestLog::Message 863 << "glGetProgramiv failed to return GL_TRANSFORM_FEEDBACK_VARYINGS." 864 << tcu::TestLog::EndMessage; 865 throw 0; 866 } 867 868 glw::GLchar tmp_buffer[256]; 869 870 glw::GLsizei tmp_size = 0; 871 872 glw::GLenum tmp_type = GL_NONE; 873 874 gl.getTransformFeedbackVarying(m_program_id_with_output, transform_feedback_varyings, sizeof(tmp_buffer), NULL, 875 &tmp_size, &tmp_type, tmp_buffer); 876 877 if (GL_INVALID_VALUE != gl.getError()) 878 { 879 m_context.getTestContext().getLog() << tcu::TestLog::Message 880 << "INVALID_VALUE was not generated by GetTransformFeedbackVarying when " 881 "<index> was greater than or equal to TRANSFORM_FEEDBACK_VARYINGS." 882 << tcu::TestLog::EndMessage; 883 return false; 884 } 885 886 /* INVALID_VALUE is generated by GetIntegerIndexdv when <index> exceeds the 887 limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> is one of the 888 following: 889 * TRANSFORM_FEEDBACK_BUFFER_BINDING, 890 * TRANSFORM_FEEDBACK_BUFFER_START, 891 * TRANSFORM_FEEDBACK_BUFFER_SIZE; */ 892 893 if (DE_NULL != m_glGetIntegerIndexedvEXT) 894 { 895 glw::GLint tmp_int_value; 896 897 m_glGetIntegerIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, more_than_max_separate_attribs, &tmp_int_value); 898 899 if (GL_INVALID_VALUE != gl.getError()) 900 { 901 m_context.getTestContext().getLog() 902 << tcu::TestLog::Message 903 << "INVALID_VALUE was not generated by GetIntegerIndexdv when <index> exceeds the " 904 "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was " 905 "TRANSFORM_FEEDBACK_BUFFER_BINDING." 906 << tcu::TestLog::EndMessage; 907 return false; 908 } 909 910 m_glGetIntegerIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_START, more_than_max_separate_attribs, &tmp_int_value); 911 912 if (GL_INVALID_VALUE != gl.getError()) 913 { 914 m_context.getTestContext().getLog() 915 << tcu::TestLog::Message 916 << "INVALID_VALUE was not generated by GetIntegerIndexdv when <index> exceeds the " 917 "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was " 918 "GL_TRANSFORM_FEEDBACK_BUFFER_START." 919 << tcu::TestLog::EndMessage; 920 return false; 921 } 922 923 m_glGetIntegerIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, more_than_max_separate_attribs, &tmp_int_value); 924 925 if (GL_INVALID_VALUE != gl.getError()) 926 { 927 m_context.getTestContext().getLog() 928 << tcu::TestLog::Message 929 << "INVALID_VALUE was not generated by GetIntegerIndexdv when <index> exceeds the " 930 "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was " 931 "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE." 932 << tcu::TestLog::EndMessage; 933 return false; 934 } 935 } 936 937 /* INVALID_VALUE is generated by GetBooleanIndexedv when <index> exceeds the 938 limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> is 939 TRANSFORM_FEEDBACK_BUFFER_BINDING. */ 940 941 if (DE_NULL != m_glGetBooleanIndexedvEXT) 942 { 943 glw::GLboolean tmp_bool_value; 944 945 m_glGetBooleanIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, more_than_max_separate_attribs, 946 &tmp_bool_value); 947 948 if (GL_INVALID_VALUE != gl.getError()) 949 { 950 m_context.getTestContext().getLog() 951 << tcu::TestLog::Message 952 << "INVALID_VALUE was not generated by GetBooleanIndexedv when <index> exceeds the " 953 "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was " 954 "TRANSFORM_FEEDBACK_BUFFER_BINDING." 955 << tcu::TestLog::EndMessage; 956 return false; 957 } 958 } 959 960 return true; 961 } 962 963 bool gl3cts::TransformFeedback::APIErrors::testExtension2(void) 964 { 965 /* Functions handler */ 966 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 967 968 /* Bind Transform Feedback Object */ 969 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0); 970 971 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed."); 972 973 /* INVALID_OPERATION is generated by PauseTransformFeedback if current 974 transform feedback is not active or paused; */ 975 976 gl.pauseTransformFeedback(); 977 978 if (GL_INVALID_OPERATION != gl.getError()) 979 { 980 m_context.getTestContext().getLog() << tcu::TestLog::Message 981 << "INVALID_OPERATION is not generated by PauseTransformFeedback if " 982 "current transform feedback is not active or paused." 983 << tcu::TestLog::EndMessage; 984 985 return false; 986 } 987 988 /* INVALID_OPERATION is generated by ResumeTransformFeedback if current 989 transform feedback is not active; */ 990 991 gl.resumeTransformFeedback(); 992 993 if (GL_INVALID_OPERATION != gl.getError()) 994 { 995 m_context.getTestContext().getLog() << tcu::TestLog::Message 996 << "INVALID_OPERATION is not generated by ResumeTransformFeedback if " 997 "current transform feedback is not active." 998 << tcu::TestLog::EndMessage; 999 1000 return false; 1001 } 1002 1003 /* Prepare program and buffer. */ 1004 gl.useProgram(m_program_id_with_output); 1005 1006 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 1007 1008 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0); 1009 1010 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 1011 1012 /* INVALID_OPERATION is generated by DrawTransformFeedback when 1013 EndTransformFeedback was never called for the object named <id>. */ 1014 gl.drawTransformFeedback(GL_POINTS, m_transform_feedback_object_0); 1015 1016 if (GL_INVALID_OPERATION != gl.getError()) 1017 { 1018 m_context.getTestContext().getLog() << tcu::TestLog::Message 1019 << "INVALID_OPERATION is not generated by DrawTransformFeedback when " 1020 "EndTransformFeedback was never called for the object named <id>." 1021 << tcu::TestLog::EndMessage; 1022 1023 return false; 1024 } 1025 1026 /* Make Transform Feedback Active */ 1027 gl.beginTransformFeedback(GL_POINTS); 1028 1029 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 1030 1031 /* INVALID_OPERATION is generated by BindTransformFeedback if current 1032 transform feedback is active and not paused; */ 1033 1034 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0); 1035 1036 if (GL_INVALID_OPERATION != gl.getError()) 1037 { 1038 gl.endTransformFeedback(); 1039 1040 m_context.getTestContext().getLog() << tcu::TestLog::Message 1041 << "INVALID_OPERATION is not generated by BindTransformFeedback if current " 1042 "transform feedback is active and not paused." 1043 << tcu::TestLog::EndMessage; 1044 1045 return false; 1046 } 1047 1048 /* INVALID_OPERATION is generated by DeleteTransformFeedbacks if any of <ids> 1049 is active; */ 1050 1051 gl.deleteTransformFeedbacks(1, &m_transform_feedback_object_0); 1052 1053 if (GL_INVALID_OPERATION != gl.getError()) 1054 { 1055 gl.endTransformFeedback(); 1056 1057 m_context.getTestContext().getLog() 1058 << tcu::TestLog::Message 1059 << "INVALID_OPERATION is not generated by DeleteTransformFeedbacks if any of <ids> is active." 1060 << tcu::TestLog::EndMessage; 1061 1062 return false; 1063 } 1064 1065 /* INVALID_OPERATION is generated by ResumeTransformFeedback if current 1066 transform feedback is not not paused; */ 1067 1068 gl.resumeTransformFeedback(); 1069 1070 if (GL_INVALID_OPERATION != gl.getError()) 1071 { 1072 gl.endTransformFeedback(); 1073 1074 m_context.getTestContext().getLog() << tcu::TestLog::Message 1075 << "INVALID_OPERATION is not generated by ResumeTransformFeedback if " 1076 "current transform feedback is not not paused." 1077 << tcu::TestLog::EndMessage; 1078 1079 return false; 1080 } 1081 1082 /* pause transform feedback */ 1083 1084 gl.pauseTransformFeedback(); 1085 1086 GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed."); 1087 1088 /* No error is generated by draw command when transform feedback is paused 1089 and primitive modes do not match; */ 1090 1091 gl.drawArrays(GL_LINES, 0, 2); 1092 1093 if (GL_NO_ERROR != gl.getError()) 1094 { 1095 gl.endTransformFeedback(); 1096 1097 m_context.getTestContext().getLog() << tcu::TestLog::Message 1098 << "No error is not generated by draw command when transform feedback is " 1099 "paused and primitive modes do not match." 1100 << tcu::TestLog::EndMessage; 1101 1102 return false; 1103 } 1104 1105 /* INVALID_OPERATION is generated by LinkProgram when <program> is used by 1106 some transform feedback object that is currently not active; */ 1107 1108 gl.linkProgram(m_program_id_with_output); 1109 1110 if (GL_INVALID_OPERATION != gl.getError()) 1111 { 1112 m_context.getTestContext().getLog() << tcu::TestLog::Message 1113 << "INVALID_OPERATION was not generated by LinkProgram when <program> was " 1114 "used by some transform feedback object that is currently not active." 1115 << tcu::TestLog::EndMessage; 1116 1117 gl.endTransformFeedback(); 1118 1119 return false; 1120 } 1121 1122 /* No error is generated by UseProgram when transform feedback is paused; */ 1123 1124 gl.useProgram(0); 1125 1126 if (GL_NO_ERROR != gl.getError()) 1127 { 1128 gl.endTransformFeedback(); 1129 1130 m_context.getTestContext().getLog() << tcu::TestLog::Message 1131 << "glUseProgram unexpectedly failed when transform feedback is paused." 1132 << tcu::TestLog::EndMessage; 1133 1134 return false; 1135 } 1136 1137 gl.useProgram(m_program_id_with_output); 1138 1139 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 1140 1141 /* End Transform Feedback and make draw. */ 1142 1143 gl.endTransformFeedback(); 1144 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 1145 1146 /* INVALID_VALUE is generated by DrawTransformFeedback if <id> is not name of 1147 transform feedback object; */ 1148 1149 unsigned short int invalid_name = 1; 1150 1151 while (gl.isTransformFeedback(invalid_name)) 1152 { 1153 ++invalid_name; 1154 1155 /* Make sure that this loop ends someday, bad day. */ 1156 if (invalid_name == USHRT_MAX) 1157 { 1158 m_context.getTestContext().getLog() 1159 << tcu::TestLog::Message << "Cannot find unused trnasform feedback object." << tcu::TestLog::EndMessage; 1160 throw 0; 1161 } 1162 } 1163 1164 gl.drawTransformFeedback(GL_POINTS, (glw::GLuint)invalid_name); 1165 1166 if (GL_INVALID_VALUE != gl.getError()) 1167 { 1168 gl.endTransformFeedback(); 1169 1170 m_context.getTestContext().getLog() << tcu::TestLog::Message 1171 << "glUseProgram unexpectedly failed when transform feedback is paused." 1172 << tcu::TestLog::EndMessage; 1173 1174 return false; 1175 } 1176 1177 return true; 1178 } 1179 1180 bool gl3cts::TransformFeedback::APIErrors::testExtension3(void) 1181 { 1182 /* Functions handler */ 1183 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1184 1185 /* INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed and 1186 GetQueryIndexediv when <target> is TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN and 1187 <index> exceeds limits of MAX_VERTEX_STREAMS 1188 1189 INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed and 1190 GetQueryIndexediv when <target> is PRIMITIVES_GENERATED and <index> exceeds 1191 limits of MAX_VERTEX_STREAMS */ 1192 1193 glw::GLint max_vertex_streams = 0; 1194 1195 gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams); 1196 1197 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 1198 1199 if (max_vertex_streams == 0) 1200 { 1201 /* Nothing returned. */ 1202 throw 0; 1203 } 1204 1205 ++max_vertex_streams; 1206 1207 static const glw::GLenum target[] = { GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_PRIMITIVES_GENERATED }; 1208 static const glw::GLchar* target_str[] = { STR(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN), 1209 STR(GL_PRIMITIVES_GENERATED) }; 1210 static const glw::GLuint target_count = sizeof(target) / sizeof(target[0]); 1211 1212 for (glw::GLuint i = 0; i < target_count; ++i) 1213 { 1214 gl.beginQueryIndexed(target[i], max_vertex_streams, m_query_object); 1215 1216 if (GL_INVALID_VALUE != gl.getError()) 1217 { 1218 m_context.getTestContext().getLog() 1219 << tcu::TestLog::Message << "INVALID_VALUE was not generated by BeginQueryIndexed, EndQueryIndexed and" 1220 "GetQueryIndexediv when <target> was " 1221 << target_str[i] << " and " 1222 "<index> exceeded limits of MAX_VERTEX_STREAMS." 1223 << tcu::TestLog::EndMessage; 1224 return false; 1225 } 1226 1227 gl.endQueryIndexed(target[i], max_vertex_streams); 1228 1229 if (GL_INVALID_VALUE != gl.getError()) 1230 { 1231 m_context.getTestContext().getLog() << tcu::TestLog::Message 1232 << "INVALID_VALUE was not generated by EndQueryIndexed " 1233 "when <target> was " 1234 << target_str[i] << " and " 1235 "<index> exceeded limits of MAX_VERTEX_STREAMS." 1236 << tcu::TestLog::EndMessage; 1237 return false; 1238 } 1239 1240 glw::GLint param = 0; 1241 1242 gl.getQueryIndexediv(target[i], max_vertex_streams, GL_QUERY_COUNTER_BITS, ¶m); 1243 1244 if (GL_INVALID_VALUE != gl.getError()) 1245 { 1246 m_context.getTestContext().getLog() << tcu::TestLog::Message << "INVALID_VALUE was not generated by " 1247 "GetQueryIndexediv when <target> was " 1248 << target_str[i] << " and " 1249 "<index> exceeded limits of MAX_VERTEX_STREAMS." 1250 << tcu::TestLog::EndMessage; 1251 return false; 1252 } 1253 } 1254 1255 /* INVALID_OPERATION is generated by EndQueryIndexed when name of active 1256 query at <index> of <target> is zero */ 1257 1258 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0); 1259 1260 if (GL_INVALID_OPERATION != gl.getError()) 1261 { 1262 m_context.getTestContext().getLog() 1263 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by EndQueryIndexed when name of active " 1264 "query at <index> of <target> is zero" 1265 << tcu::TestLog::EndMessage; 1266 return false; 1267 } 1268 1269 /* INVALID_VALUE is generated by DrawTransformFeedbackStream when <stream> 1270 exceeds limits of MAX_VERTEX_STREAMS */ 1271 1272 gl.drawTransformFeedbackStream(GL_POINTS, m_transform_feedback_object_0, max_vertex_streams); 1273 1274 if (GL_INVALID_VALUE != gl.getError()) 1275 { 1276 m_context.getTestContext().getLog() 1277 << tcu::TestLog::Message << "INVALID_VALUE was not generated by DrawTransformFeedbackStream when <stream> " 1278 "exceeded limits of MAX_VERTEX_STREAMS" 1279 << tcu::TestLog::EndMessage; 1280 return false; 1281 } 1282 1283 /* INVALID_OPERATION is generated by TransformFeedbackVaryings when 1284 <varyings> contains any of the special names while <bufferMode> is not 1285 INTERLEAVED_ATTRIBS */ 1286 1287 static const glw::GLchar* tf_varying_names[] = { "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2", 1288 "gl_SkipComponents3", "gl_SkipComponents4" }; 1289 static const glw::GLuint tf_varying_names_count = sizeof(tf_varying_names) / sizeof(tf_varying_names[0]); 1290 1291 for (glw::GLuint i = 0; i < tf_varying_names_count; ++i) 1292 { 1293 gl.transformFeedbackVaryings(m_program_id_with_output, 1, &tf_varying_names[i], GL_SEPARATE_ATTRIBS); 1294 1295 if (GL_INVALID_OPERATION != gl.getError()) 1296 { 1297 m_context.getTestContext().getLog() 1298 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by TransformFeedbackVaryings when " 1299 "<varyings> contained any of the special names while <bufferMode> was " 1300 "GL_SEPARATE_ATTRIBS." 1301 << tcu::TestLog::EndMessage; 1302 return false; 1303 } 1304 } 1305 1306 /* INVALID_OPERATION is generated by TransformFeedbackVaryings when 1307 <varyings> contains more "gl_NextBuffer" entries than allowed limit of 1308 MAX_TRANSFORM_FEEDBACK_BUFFERS */ 1309 1310 glw::GLint max_transform_feedback_buffers = 0; 1311 1312 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers); 1313 1314 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 1315 1316 if (max_transform_feedback_buffers == 0) 1317 { 1318 /* Nothing returned. */ 1319 throw 0; 1320 } 1321 1322 glw::GLint more_than_max_transform_feedback_buffers = max_transform_feedback_buffers + 1; 1323 1324 const glw::GLchar** tf_next_buffer_varying_names = new const glw::GLchar*[more_than_max_transform_feedback_buffers]; 1325 1326 if (DE_NULL == tf_next_buffer_varying_names) 1327 { 1328 /* Allocation error. */ 1329 throw 0; 1330 } 1331 1332 for (glw::GLint i = 0; i < more_than_max_transform_feedback_buffers; ++i) 1333 { 1334 tf_next_buffer_varying_names[i] = tf_varying_names[0]; 1335 } 1336 1337 gl.transformFeedbackVaryings(m_program_id_with_output, more_than_max_transform_feedback_buffers, 1338 tf_next_buffer_varying_names, GL_INTERLEAVED_ATTRIBS); 1339 1340 delete[] tf_next_buffer_varying_names; 1341 1342 if (GL_INVALID_OPERATION != gl.getError()) 1343 { 1344 m_context.getTestContext().getLog() 1345 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by TransformFeedbackVaryings when " 1346 "<varyings> contained more \"gl_NextBuffer\" entries than allowed limit of " 1347 "MAX_TRANSFORM_FEEDBACK_BUFFER." 1348 << tcu::TestLog::EndMessage; 1349 return false; 1350 } 1351 1352 return true; 1353 } 1354 1355 bool gl3cts::TransformFeedback::APIErrors::testInstanced(void) 1356 { 1357 /* Functions handler */ 1358 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1359 1360 /* INVALID_ENUM is generated by DrawTransformFeedbackInstanced and 1361 DrawTransformFeedbackStreamInstanced if <mode> is invalid */ 1362 1363 glw::GLenum _supported_mode[] = { GL_POINTS, 1364 GL_LINE_STRIP, 1365 GL_LINE_LOOP, 1366 GL_LINES, 1367 GL_LINE_STRIP_ADJACENCY, 1368 GL_LINES_ADJACENCY, 1369 GL_TRIANGLE_STRIP, 1370 GL_TRIANGLE_FAN, 1371 GL_TRIANGLES, 1372 GL_TRIANGLE_STRIP_ADJACENCY, 1373 GL_TRIANGLES_ADJACENCY, 1374 GL_PATCHES }; 1375 1376 std::set<glw::GLenum> supported_mode(_supported_mode, 1377 _supported_mode + sizeof(_supported_mode) / sizeof(_supported_mode[0])); 1378 1379 int mode = 0; 1380 1381 while (supported_mode.find(mode) != supported_mode.end()) 1382 { 1383 mode++; 1384 } 1385 1386 gl.drawTransformFeedbackInstanced(mode, m_transform_feedback_object_0, 1); 1387 1388 if (GL_INVALID_ENUM != gl.getError()) 1389 { 1390 m_context.getTestContext().getLog() << tcu::TestLog::Message 1391 << "INVALID_ENUM was not generated by DrawTransformFeedbackInstanced and " 1392 "DrawTransformFeedbackStreamInstanced when <mode> was invalid." 1393 << tcu::TestLog::EndMessage; 1394 return false; 1395 } 1396 1397 gl.drawTransformFeedbackStreamInstanced(mode, m_transform_feedback_object_0, 0, 1); 1398 1399 if (GL_INVALID_ENUM != gl.getError()) 1400 { 1401 m_context.getTestContext().getLog() << tcu::TestLog::Message 1402 << "INVALID_ENUM was not generated by DrawTransformFeedbackInstanced and " 1403 "DrawTransformFeedbackStreamInstanced when <mode> was invalid." 1404 << tcu::TestLog::EndMessage; 1405 return false; 1406 } 1407 1408 /* INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and 1409 DrawTransformFeedbackStreamInstanced if <mode> does not match geometry 1410 shader */ 1411 1412 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0); 1413 1414 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed."); 1415 1416 gl.useProgram(m_program_id_with_geometry_shader); 1417 1418 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 1419 1420 gl.bindVertexArray(m_vertex_array_object); 1421 1422 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 1423 1424 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0); 1425 1426 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 1427 1428 gl.beginTransformFeedback(GL_POINTS); 1429 1430 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 1431 1432 gl.drawArrays(GL_POINTS, 0, 1); 1433 1434 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 1435 1436 gl.endTransformFeedback(); 1437 1438 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 1439 1440 gl.drawTransformFeedbackInstanced(GL_LINES, m_transform_feedback_object_0, 1); 1441 1442 if (GL_INVALID_OPERATION != gl.getError()) 1443 { 1444 m_context.getTestContext().getLog() 1445 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and " 1446 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader." 1447 << tcu::TestLog::EndMessage; 1448 return false; 1449 } 1450 1451 gl.drawTransformFeedbackStreamInstanced(GL_LINES, m_transform_feedback_object_0, 0, 1); 1452 1453 if (GL_INVALID_OPERATION != gl.getError()) 1454 { 1455 m_context.getTestContext().getLog() 1456 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and " 1457 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader." 1458 << tcu::TestLog::EndMessage; 1459 return false; 1460 } 1461 1462 /* INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and 1463 DrawTransformFeedbackStreamInstanced if <mode> does not match tessellation */ 1464 1465 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0); 1466 1467 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed."); 1468 1469 gl.useProgram(m_program_id_with_tessellation_shaders); 1470 1471 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 1472 1473 gl.bindVertexArray(m_vertex_array_object); 1474 1475 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 1476 1477 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0); 1478 1479 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 1480 1481 gl.beginTransformFeedback(GL_LINES); 1482 1483 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 1484 1485 gl.drawArrays(GL_PATCHES, 0, 2); 1486 1487 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 1488 1489 gl.endTransformFeedback(); 1490 1491 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 1492 1493 gl.drawTransformFeedbackInstanced(GL_POINTS, m_transform_feedback_object_0, 1); 1494 1495 if (GL_INVALID_OPERATION != gl.getError()) 1496 { 1497 m_context.getTestContext().getLog() 1498 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and " 1499 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader." 1500 << tcu::TestLog::EndMessage; 1501 return false; 1502 } 1503 1504 gl.drawTransformFeedbackStreamInstanced(GL_POINTS, m_transform_feedback_object_0, 0, 1); 1505 1506 if (GL_INVALID_OPERATION != gl.getError()) 1507 { 1508 m_context.getTestContext().getLog() 1509 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and " 1510 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader." 1511 << tcu::TestLog::EndMessage; 1512 return false; 1513 } 1514 1515 /* INVALID_VALUE is generated by DrawTransformFeedbackStreamInstanced if 1516 <stream> is greater than or equal to MAX_VERTEX_STREAMS */ 1517 1518 glw::GLint max_vertex_streams = 0; 1519 1520 gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams); 1521 1522 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 1523 1524 if (max_vertex_streams == 0) 1525 { 1526 /* Failed to query GL_MAX_VERTEX_STREAMS. */ 1527 throw 0; 1528 } 1529 1530 glw::GLint more_than_max_vertex_streams = max_vertex_streams + 1; 1531 1532 gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, m_transform_feedback_object_0, more_than_max_vertex_streams, 1); 1533 1534 if (GL_INVALID_VALUE != gl.getError()) 1535 { 1536 m_context.getTestContext().getLog() 1537 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and " 1538 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader." 1539 << tcu::TestLog::EndMessage; 1540 return false; 1541 } 1542 1543 /* INVALID_VALUE is generated by DrawTransformFeedbackInstanced and 1544 DrawTransformFeedbackStreamInstanced if <id> is not name of transform 1545 feedback object */ 1546 1547 unsigned short int invalid_name = 1; 1548 1549 while (gl.isTransformFeedback(invalid_name)) 1550 { 1551 ++invalid_name; 1552 1553 /* Make sure that this loop ends someday, bad day. */ 1554 if (invalid_name == USHRT_MAX) 1555 { 1556 m_context.getTestContext().getLog() 1557 << tcu::TestLog::Message << "Cannot find unused trnasform feedback object." << tcu::TestLog::EndMessage; 1558 throw 0; 1559 } 1560 } 1561 1562 gl.drawTransformFeedbackInstanced(GL_PATCHES, (glw::GLuint)invalid_name, 1); 1563 1564 if (GL_INVALID_VALUE != gl.getError()) 1565 { 1566 gl.endTransformFeedback(); 1567 1568 return false; 1569 } 1570 1571 gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, (glw::GLuint)invalid_name, 0, 1); 1572 1573 if (GL_INVALID_VALUE != gl.getError()) 1574 { 1575 gl.endTransformFeedback(); 1576 1577 return false; 1578 } 1579 1580 /* INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and 1581 DrawTransformFeedbackStreamInstanced if a non-zero buffer object name is 1582 bound to an enabled array and the buffer object's data store is currently 1583 mapped */ 1584 1585 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0); 1586 1587 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed."); 1588 1589 gl.useProgram(m_program_id_with_input_output); 1590 1591 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 1592 1593 gl.bindVertexArray(m_vertex_array_object); 1594 1595 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 1596 1597 gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_1); 1598 1599 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 1600 1601 glw::GLint location = gl.getAttribLocation(m_program_id_with_input_output, (glw::GLchar*)"v_input"); 1602 1603 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 1604 1605 if (location < 0) 1606 { 1607 throw 0; 1608 } 1609 1610 gl.vertexAttribPointer(location, 1, GL_FLOAT, GL_FALSE, 0, NULL); 1611 1612 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribLPointer call failed."); 1613 1614 gl.enableVertexAttribArray(0); 1615 1616 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 1617 1618 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0); 1619 1620 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 1621 1622 gl.beginTransformFeedback(GL_POINTS); 1623 1624 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 1625 1626 gl.drawArrays(GL_POINTS, 0, 1); 1627 1628 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 1629 1630 gl.endTransformFeedback(); 1631 1632 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 1633 1634 glw::GLvoid* pointer UNUSED = gl.mapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); 1635 1636 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed."); 1637 1638 gl.drawTransformFeedbackInstanced(GL_POINTS, m_transform_feedback_object_0, 1); 1639 1640 if (GL_INVALID_OPERATION != gl.getError()) 1641 { 1642 m_context.getTestContext().getLog() 1643 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and " 1644 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader." 1645 << tcu::TestLog::EndMessage; 1646 1647 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 1648 1649 gl.disableVertexAttribArray(location); 1650 1651 return false; 1652 } 1653 1654 gl.drawTransformFeedbackStreamInstanced(GL_POINTS, m_transform_feedback_object_0, 0, 1); 1655 1656 if (GL_INVALID_OPERATION != gl.getError()) 1657 { 1658 m_context.getTestContext().getLog() 1659 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and " 1660 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader." 1661 << tcu::TestLog::EndMessage; 1662 1663 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 1664 1665 gl.disableVertexAttribArray(location); 1666 1667 return false; 1668 } 1669 1670 gl.unmapBuffer(GL_ARRAY_BUFFER); 1671 1672 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 1673 1674 pointer = DE_NULL; 1675 1676 gl.disableVertexAttribArray(location); 1677 1678 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray call failed."); 1679 1680 /* INVALID_OPERATION is generated if by DrawTransformFeedbackStreamInstanced 1681 if EndTransformFeedback was never called for the object named <id>. 1682 return true */ 1683 1684 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_1); 1685 1686 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed."); 1687 1688 gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, m_transform_feedback_object_1, 0, 1); 1689 1690 if (GL_INVALID_OPERATION != gl.getError()) 1691 { 1692 m_context.getTestContext().getLog() 1693 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and " 1694 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader." 1695 << tcu::TestLog::EndMessage; 1696 1697 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 1698 1699 gl.disableVertexAttribArray(location); 1700 1701 return false; 1702 } 1703 1704 return true; 1705 } 1706 1707 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_tessellation_control_shader = 1708 "#version 400\n" 1709 "\n" 1710 "layout (vertices = 2 ) out;\n" 1711 "\n" 1712 "void main()\n" 1713 "{\n" 1714 " gl_TessLevelOuter[1] = 3.0;\n" 1715 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 1716 "}\n"; 1717 1718 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_tessellation_evaluation_shader = 1719 "#version 400\n" 1720 "\n" 1721 "layout(isolines, equal_spacing, ccw) in;\n" 1722 "\n" 1723 "out float result;\n" 1724 "\n" 1725 "void main()\n" 1726 "{\n" 1727 " result = 0.5;\n" 1728 " gl_Position = gl_in[0].gl_Position + gl_in[1].gl_Position + gl_in[2].gl_Position;\n" 1729 "}\n"; 1730 1731 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_geometry_shader = 1732 "#version 150\n" 1733 "\n" 1734 "layout(points) in;\n" 1735 "layout(points, max_vertices = 2) out;\n" 1736 "\n" 1737 "out float result;\n" 1738 "\n" 1739 "void main()\n" 1740 "{\n" 1741 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.0, 0.0, 0.0);\n" 1742 " result = 0.0;\n" 1743 " EmitVertex();\n" 1744 "\n" 1745 " gl_Position = gl_in[0].gl_Position + vec4(1.0, 0.0, 0.0, 0.0);\n" 1746 " result = 1.0;\n" 1747 " EmitVertex();\n" 1748 "}\n"; 1749 1750 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_vertex_shader_with_output = 1751 "#version 130\n" 1752 "\n" 1753 "out float result;\n" 1754 "\n" 1755 "void main()\n" 1756 "{\n" 1757 " result = float(gl_VertexID);\n" 1758 " gl_Position = vec4(1.0);\n" 1759 "}\n"; 1760 1761 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_vertex_shader_with_input_output = 1762 "#version 130\n" 1763 "\n" 1764 "in float v_input;\n" 1765 "\n" 1766 "out float result;\n" 1767 "\n" 1768 "void main()\n" 1769 "{\n" 1770 " result = float(gl_VertexID);\n" 1771 " gl_Position = vec4(v_input);\n" 1772 "}\n"; 1773 1774 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_vertex_shader_without_output = 1775 "#version 130\n" 1776 "\n" 1777 "void main()\n" 1778 "{\n" 1779 " gl_Position = vec4(1.0);\n" 1780 "}\n"; 1781 1782 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_fragment_shader = "#version 130\n" 1783 "\n" 1784 "out vec4 color;\n" 1785 "\n" 1786 "void main()\n" 1787 "{\n" 1788 " color = vec4(1.0);\n" 1789 "}\n"; 1790 1791 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_varying_name = "result"; 1792 1793 const glw::GLfloat gl3cts::TransformFeedback::APIErrors::m_buffer_1_data[] = { 3.14159265359f, 2.7182818f }; 1794 1795 const glw::GLsizei gl3cts::TransformFeedback::APIErrors::m_buffer_1_size = 1796 sizeof(gl3cts::TransformFeedback::APIErrors::m_buffer_1_data); 1797 1798 /*-----------------------------------------------------------------------------------------------*/ 1799 1800 gl3cts::TransformFeedback::LinkingErrors::LinkingErrors(deqp::Context& context) 1801 : deqp::TestCase(context, "linking_errors_test", "Transform Feedback Linking Errors Test"), m_context(context) 1802 { 1803 /* Left intentionally blank. */ 1804 } 1805 1806 gl3cts::TransformFeedback::LinkingErrors::~LinkingErrors(void) 1807 { 1808 } 1809 1810 tcu::TestNode::IterateResult gl3cts::TransformFeedback::LinkingErrors::iterate(void) 1811 { 1812 bool is_ok = true; 1813 bool test_error = false; 1814 1815 try 1816 { 1817 is_ok = is_ok && testNoVertexNoGeometry(); 1818 is_ok = is_ok && testInvalidVarying(); 1819 is_ok = is_ok && testRepeatedVarying(); 1820 is_ok = is_ok && testTooManyVaryings(); 1821 } 1822 catch (...) 1823 { 1824 is_ok = false; 1825 test_error = true; 1826 } 1827 1828 /* Result's setup. */ 1829 if (is_ok) 1830 { 1831 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1832 } 1833 else 1834 { 1835 if (test_error) 1836 { 1837 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 1838 } 1839 else 1840 { 1841 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1842 } 1843 } 1844 1845 return STOP; 1846 } 1847 1848 bool gl3cts::TransformFeedback::LinkingErrors::testNoVertexNoGeometry(void) 1849 { 1850 /* Functions handler */ 1851 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1852 1853 /* Check if link process fails under the following conditions: 1854 <count> specified by TransformFeedbackVaryings is non-zero and program has 1855 neither vertex nor geometry shader; */ 1856 1857 glw::GLint linking_status = 1; 1858 1859 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram( 1860 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, NULL, s_fragment_shader, 1861 &s_valid_transform_feedback_varying, 1, GL_INTERLEAVED_ATTRIBS, false, &linking_status); 1862 1863 if ((GL_FALSE != linking_status) || program) 1864 { 1865 m_context.getTestContext().getLog() << tcu::TestLog::Message 1866 << "Linking unexpectedly succeded when Transform Feedback varying was " 1867 "specified but program had neither vertex nor geometry shader stages." 1868 << tcu::TestLog::EndMessage; 1869 1870 if (program) 1871 { 1872 gl.deleteProgram(program); 1873 } 1874 1875 return false; 1876 } 1877 1878 /* Log success. */ 1879 m_context.getTestContext().getLog() << tcu::TestLog::Message 1880 << "Linking failed as expected when Transform Feedback varying was specified " 1881 "but program had neither vertex nor geometry shader stages." 1882 << tcu::TestLog::EndMessage; 1883 1884 return true; 1885 } 1886 1887 bool gl3cts::TransformFeedback::LinkingErrors::testInvalidVarying(void) 1888 { 1889 /* Functions handler */ 1890 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1891 1892 /* Check if link process fails under the following conditions: 1893 <varyings> specified by TransformFeedbackVaryings contains name of 1894 variable that is not available for capture; */ 1895 1896 std::string vertex_shader(s_vertex_shader_template); 1897 1898 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 1899 vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", "in float data;\n"); 1900 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS", ""); 1901 1902 glw::GLint linking_status = 1; 1903 1904 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram( 1905 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader, 1906 &s_invalid_transform_feedback_varying, 1, GL_INTERLEAVED_ATTRIBS, false, &linking_status); 1907 1908 if ((GL_FALSE != linking_status) || program) 1909 { 1910 m_context.getTestContext().getLog() 1911 << tcu::TestLog::Message 1912 << "Linking unexpectedly succeded when Transform Feedback varying was specified with name of variable (" 1913 << s_invalid_transform_feedback_varying << ") that is not available for capture." 1914 << tcu::TestLog::EndMessage; 1915 1916 if (program) 1917 { 1918 gl.deleteProgram(program); 1919 } 1920 1921 return false; 1922 } 1923 1924 /* Log success. */ 1925 m_context.getTestContext().getLog() 1926 << tcu::TestLog::Message 1927 << "Linking failed as expected when Transform Feedback varying was specified with name of variable (" 1928 << s_invalid_transform_feedback_varying << ") that is not available for capture." << tcu::TestLog::EndMessage; 1929 1930 return true; 1931 } 1932 1933 bool gl3cts::TransformFeedback::LinkingErrors::testRepeatedVarying(void) 1934 { 1935 /* Functions handler */ 1936 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1937 1938 /* Check if link process fails under the following conditions: 1939 <varyings> specified by TransformFeedbackVaryings contains name of 1940 variable more than once; */ 1941 1942 std::string vertex_shader(s_vertex_shader_template); 1943 1944 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 1945 vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", "out float result;\n"); 1946 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS", 1947 " result = 0.577215664901532;\n"); 1948 1949 glw::GLint linking_status = 1; 1950 1951 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram( 1952 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader, 1953 s_repeated_transform_feedback_varying, s_repeated_transform_feedback_varying_count, GL_INTERLEAVED_ATTRIBS, 1954 false, &linking_status); 1955 1956 if ((GL_FALSE != linking_status) || program) 1957 { 1958 m_context.getTestContext().getLog() 1959 << tcu::TestLog::Message 1960 << "Linking unexpectedly succeded when Transform Feedback varying was specified twice." 1961 << tcu::TestLog::EndMessage; 1962 1963 if (program) 1964 { 1965 gl.deleteProgram(program); 1966 } 1967 1968 return false; 1969 } 1970 1971 /* Log success. */ 1972 m_context.getTestContext().getLog() 1973 << tcu::TestLog::Message << "Linking failed as expected when Transform Feedback varying was specified twice." 1974 << tcu::TestLog::EndMessage; 1975 1976 return true; 1977 } 1978 1979 bool gl3cts::TransformFeedback::LinkingErrors::testTooManyVaryings(void) 1980 { 1981 /* Functions handler */ 1982 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1983 1984 /* Check if link process fails under the following conditions: 1985 number of components specified to capture exceeds limits 1986 MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS or 1987 MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS. */ 1988 1989 /* Fetching limits. */ 1990 glw::GLint max_transform_feedback_separate_components = 0; 1991 glw::GLint max_transform_feedback_interleaved_components = 0; 1992 1993 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components); 1994 1995 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 1996 1997 if (max_transform_feedback_separate_components == 0) 1998 { 1999 throw 0; 2000 } 2001 2002 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components); 2003 2004 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2005 2006 if (max_transform_feedback_interleaved_components == 0) 2007 { 2008 throw 0; 2009 } 2010 2011 glw::GLint more_than_max_transform_feedback_components = 2012 deMax32(max_transform_feedback_separate_components, max_transform_feedback_interleaved_components) + 1; 2013 2014 /* Preparing source code. */ 2015 std::string vertex_shader(s_vertex_shader_template); 2016 std::string transform_feedback_variable_declarations(""); 2017 std::string transform_feedback_variable_setters(""); 2018 std::vector<std::string> transform_feedback_varyings(more_than_max_transform_feedback_components); 2019 std::vector<const glw::GLchar*> transform_feedback_varyings_c(more_than_max_transform_feedback_components); 2020 2021 for (glw::GLint i = 0; i < more_than_max_transform_feedback_components; ++i) 2022 { 2023 std::string varying = "result_"; 2024 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i)); 2025 2026 transform_feedback_varyings[i] = varying; 2027 2028 transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str(); 2029 2030 transform_feedback_variable_declarations.append("out float "); 2031 transform_feedback_variable_declarations.append(varying); 2032 transform_feedback_variable_declarations.append(";\n"); 2033 2034 transform_feedback_variable_setters.append(" "); 2035 transform_feedback_variable_setters.append(varying); 2036 transform_feedback_variable_setters.append(" = "); 2037 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * i)); 2038 transform_feedback_variable_setters.append(".0;\n"); 2039 } 2040 2041 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 2042 vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations); 2043 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS", 2044 transform_feedback_variable_setters); 2045 2046 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram( 2047 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader, 2048 &transform_feedback_varyings_c[0], more_than_max_transform_feedback_components, GL_INTERLEAVED_ATTRIBS); 2049 2050 /* Note: we check for program as not only linking shall fail, but also glTransformFeedbackVaryings shall return an error. */ 2051 2052 if (program) 2053 { 2054 m_context.getTestContext().getLog() << tcu::TestLog::Message 2055 << "Linking unexpectedly succeded when too many Transform Feedback varying " 2056 "were specified in INTERLEAVED mode." 2057 << tcu::TestLog::EndMessage; 2058 2059 if (program) 2060 { 2061 gl.deleteProgram(program); 2062 } 2063 2064 return false; 2065 } 2066 2067 program = gl3cts::TransformFeedback::Utilities::buildProgram( 2068 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader, 2069 &transform_feedback_varyings_c[0], more_than_max_transform_feedback_components, GL_SEPARATE_ATTRIBS); 2070 2071 if (program) 2072 { 2073 m_context.getTestContext().getLog() << tcu::TestLog::Message 2074 << "Linking unexpectedly succeded when too many Transform Feedback " 2075 "varyings were specified in SEPARATE mode." 2076 << tcu::TestLog::EndMessage; 2077 2078 if (program) 2079 { 2080 gl.deleteProgram(program); 2081 } 2082 2083 return false; 2084 } 2085 2086 /* Log success. */ 2087 m_context.getTestContext().getLog() 2088 << tcu::TestLog::Message 2089 << "Linking failed as expected when too many Transform Feedback varyings were specified." 2090 << tcu::TestLog::EndMessage; 2091 2092 return true; 2093 } 2094 2095 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_fragment_shader = "#version 130\n" 2096 "\n" 2097 "out vec4 color;\n" 2098 "\n" 2099 "void main()\n" 2100 "{\n" 2101 " color = vec4(1.0);\n" 2102 "}\n"; 2103 2104 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_vertex_shader_template = 2105 "#version 130\n" 2106 "\n" 2107 "TEMPLATE_INPUT_OUTPUT_DECLARATIONS" 2108 "\n" 2109 "void main()\n" 2110 "{\n" 2111 "TEMPLATE_OUTPUT_SETTERS" 2112 "\n" 2113 " gl_Position = vec4(1.618033988749);\n" 2114 "}\n"; 2115 2116 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_valid_transform_feedback_varying = "result"; 2117 2118 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_invalid_transform_feedback_varying = "data"; 2119 2120 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_repeated_transform_feedback_varying[] = { "result", 2121 "result" }; 2122 2123 const glw::GLsizei gl3cts::TransformFeedback::LinkingErrors::s_repeated_transform_feedback_varying_count = 2124 sizeof(s_repeated_transform_feedback_varying) / sizeof(s_repeated_transform_feedback_varying[0]); 2125 2126 /*-----------------------------------------------------------------------------------------------*/ 2127 2128 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_interleaved_components = 64; 2129 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_separate_attribs = 4; 2130 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_separate_components = 4; 2131 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_buffers = 4; 2132 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_vertex_streams = 1; 2133 2134 gl3cts::TransformFeedback::Limits::Limits(deqp::Context& context) 2135 : deqp::TestCase(context, "limits_test", "Transform Feedback Limits Test"), m_context(context) 2136 { 2137 } 2138 2139 gl3cts::TransformFeedback::Limits::~Limits(void) 2140 { 2141 } 2142 2143 tcu::TestNode::IterateResult gl3cts::TransformFeedback::Limits::iterate(void) 2144 { 2145 /* Initializations. */ 2146 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0))); 2147 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 2148 2149 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback"); 2150 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3"); 2151 2152 bool is_ok = true; 2153 bool test_error = false; 2154 2155 /* Tests. */ 2156 try 2157 { 2158 if (is_at_least_gl_30 || is_ext_tf_1) 2159 { 2160 is_ok = is_ok && test_max_transform_feedback_interleaved_components(); 2161 is_ok = is_ok && test_max_transform_feedback_separate_attribs(); 2162 is_ok = is_ok && test_max_transform_feedback_separate_components(); 2163 } 2164 2165 if (is_at_least_gl_40 || is_arb_tf_3) 2166 { 2167 is_ok = is_ok && test_max_transform_feedback_buffers(); 2168 is_ok = is_ok && test_max_vertex_streams(); 2169 } 2170 } 2171 catch (...) 2172 { 2173 is_ok = false; 2174 test_error = true; 2175 } 2176 2177 /* Result's setup. */ 2178 if (is_ok) 2179 { 2180 /* Log success. */ 2181 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Limits are in range of specification." 2182 << tcu::TestLog::EndMessage; 2183 2184 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2185 } 2186 else 2187 { 2188 if (test_error) 2189 { 2190 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 2191 } 2192 else 2193 { 2194 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2195 } 2196 } 2197 2198 return STOP; 2199 } 2200 2201 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_interleaved_components(void) 2202 { 2203 /* Functions handler */ 2204 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2205 2206 /* Check that MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is at least 64. */ 2207 glw::GLint max_transform_feedback_interleaved_components = 0; 2208 2209 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components); 2210 2211 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2212 2213 if (max_transform_feedback_interleaved_components < s_min_value_of_max_transform_feedback_interleaved_components) 2214 { 2215 m_context.getTestContext().getLog() 2216 << tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is equal to " 2217 << max_transform_feedback_interleaved_components << " which is less than expected " 2218 << s_min_value_of_max_transform_feedback_interleaved_components << "." << tcu::TestLog::EndMessage; 2219 return false; 2220 } 2221 2222 return true; 2223 } 2224 2225 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_separate_attribs(void) 2226 { 2227 /* Functions handler */ 2228 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2229 2230 /* Check that MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS is at least 4. */ 2231 glw::GLint max_transform_feedback_separate_attribs = 0; 2232 2233 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_transform_feedback_separate_attribs); 2234 2235 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2236 2237 if (max_transform_feedback_separate_attribs < s_min_value_of_max_transform_feedback_separate_attribs) 2238 { 2239 m_context.getTestContext().getLog() 2240 << tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS is equal to " 2241 << max_transform_feedback_separate_attribs << " which is less than expected " 2242 << s_min_value_of_max_transform_feedback_separate_attribs << "." << tcu::TestLog::EndMessage; 2243 return false; 2244 } 2245 2246 return true; 2247 } 2248 2249 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_separate_components(void) 2250 { 2251 /* Functions handler */ 2252 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2253 2254 /* Check that MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS is at least 4. */ 2255 glw::GLint max_transform_feedback_separate_components = 0; 2256 2257 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components); 2258 2259 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2260 2261 if (max_transform_feedback_separate_components < s_min_value_of_max_transform_feedback_separate_components) 2262 { 2263 m_context.getTestContext().getLog() 2264 << tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS is equal to " 2265 << max_transform_feedback_separate_components << " which is less than expected " 2266 << s_min_value_of_max_transform_feedback_separate_components << "." << tcu::TestLog::EndMessage; 2267 return false; 2268 } 2269 2270 return true; 2271 } 2272 2273 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_buffers(void) 2274 { 2275 /* Functions handler */ 2276 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2277 2278 /* Check that MAX_TRANSFORM_FEEDBACK_BUFFERS is at least 4. */ 2279 glw::GLint max_transform_feedback_buffers = 0; 2280 2281 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers); 2282 2283 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2284 2285 if (max_transform_feedback_buffers < s_min_value_of_max_transform_feedback_buffers) 2286 { 2287 m_context.getTestContext().getLog() << tcu::TestLog::Message << "MAX_TRANSFORM_FEEDBACK_BUFFERS is equal to " 2288 << max_transform_feedback_buffers << " which is less than expected " 2289 << s_min_value_of_max_transform_feedback_buffers << "." 2290 << tcu::TestLog::EndMessage; 2291 return false; 2292 } 2293 2294 return true; 2295 } 2296 2297 bool gl3cts::TransformFeedback::Limits::test_max_vertex_streams(void) 2298 { 2299 /* Functions handler */ 2300 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2301 2302 /* Check that MAX_VERTEX_STREAMS is at least 1. */ 2303 glw::GLint max_vertex_streams = 0; 2304 2305 gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams); 2306 2307 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2308 2309 if (max_vertex_streams < s_min_value_of_max_vertex_streams) 2310 { 2311 m_context.getTestContext().getLog() << tcu::TestLog::Message << "MAX_VERTEX_STREAMS is equal to " 2312 << max_vertex_streams << " which is less than expected " 2313 << s_min_value_of_max_vertex_streams << "." << tcu::TestLog::EndMessage; 2314 return false; 2315 } 2316 2317 return true; 2318 } 2319 2320 /*-----------------------------------------------------------------------------------------------*/ 2321 2322 gl3cts::TransformFeedback::CaptureVertexInterleaved::CaptureVertexInterleaved(deqp::Context& context, 2323 const char* test_name, 2324 const char* test_description) 2325 : deqp::TestCase(context, test_name, test_description) 2326 , m_context(context) 2327 , m_program(0) 2328 , m_framebuffer(0) 2329 , m_renderbuffer(0) 2330 , m_buffer(0) 2331 , m_buffer_size(0) 2332 , m_vertex_array_object(0) 2333 , m_max_transform_feedback_components(0) 2334 , m_attrib_type(GL_INTERLEAVED_ATTRIBS) 2335 , m_max_vertices_drawn(8) 2336 , m_glBindBufferOffsetEXT(DE_NULL) 2337 { 2338 } 2339 2340 gl3cts::TransformFeedback::CaptureVertexInterleaved::~CaptureVertexInterleaved(void) 2341 { 2342 } 2343 2344 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureVertexInterleaved::iterate(void) 2345 { 2346 /* Functions handler */ 2347 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2348 2349 /* Initializations. */ 2350 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0))); 2351 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback"); 2352 2353 bool is_ok = true; 2354 bool test_error = false; 2355 2356 try 2357 { 2358 if (is_ext_tf_1) 2359 { 2360 /* Extension query. */ 2361 m_glBindBufferOffsetEXT = 2362 (BindBufferOffsetEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glBindBufferOffsetEXT"); 2363 2364 if (DE_NULL == m_glBindBufferOffsetEXT) 2365 { 2366 throw 0; 2367 } 2368 } 2369 2370 if (is_at_least_gl_30 || is_ext_tf_1) 2371 { 2372 fetchLimits(); 2373 buildProgram(); 2374 createFramebuffer(); 2375 createTransformFeedbackBuffer(); 2376 createVertexArrayObject(); 2377 2378 gl.useProgram(m_program); 2379 2380 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 2381 2382 for (glw::GLint i_bind_case = 0; (i_bind_case < BIND_BUFFER_CASES_COUNT) && is_ok; ++i_bind_case) 2383 { 2384 if ((i_bind_case == BIND_BUFFER_OFFSET_CASE) && (DE_NULL == m_glBindBufferOffsetEXT)) 2385 { 2386 continue; 2387 } 2388 2389 bindBuffer((BindBufferCase)i_bind_case); 2390 2391 for (glw::GLuint i_primitive_case = 0; (i_primitive_case < s_primitive_cases_count) && is_ok; 2392 ++i_primitive_case) 2393 { 2394 draw(i_primitive_case); 2395 2396 is_ok = is_ok && checkFramebuffer(s_primitive_cases[i_primitive_case]); 2397 is_ok = is_ok && checkTransformFeedbackBuffer((BindBufferCase)i_bind_case, 2398 s_primitive_cases[i_primitive_case]); 2399 } 2400 } 2401 } 2402 } 2403 catch (...) 2404 { 2405 is_ok = false; 2406 test_error = true; 2407 } 2408 2409 /* Clean objects. */ 2410 clean(); 2411 2412 /* Result's setup. */ 2413 if (is_ok) 2414 { 2415 /* Log success. */ 2416 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Vertex have passed." 2417 << tcu::TestLog::EndMessage; 2418 2419 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2420 } 2421 else 2422 { 2423 if (test_error) 2424 { 2425 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 2426 } 2427 else 2428 { 2429 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2430 } 2431 } 2432 2433 return STOP; 2434 } 2435 2436 void gl3cts::TransformFeedback::CaptureVertexInterleaved::fetchLimits(void) 2437 { 2438 /* Functions handler */ 2439 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2440 2441 /* Fetching limits. */ 2442 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_transform_feedback_components); 2443 2444 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2445 2446 if (m_max_transform_feedback_components == 0) 2447 { 2448 throw 0; 2449 } 2450 2451 glw::GLint max_varyings_components = 0; 2452 2453 gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings_components); 2454 2455 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2456 2457 if (max_varyings_components == 0) 2458 { 2459 throw 0; 2460 } 2461 2462 if (m_max_transform_feedback_components > max_varyings_components) 2463 { 2464 m_max_transform_feedback_components = max_varyings_components; 2465 } 2466 } 2467 2468 void gl3cts::TransformFeedback::CaptureVertexInterleaved::buildProgram(void) 2469 { 2470 /* Functions handler */ 2471 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2472 2473 /* Preparing source code. */ 2474 std::string vertex_shader(s_vertex_shader_source_code_template); /* Storage for vertex shader source code. */ 2475 std::string transform_feedback_variable_declarations( 2476 ""); /* String to contain all custom outputs from vertex shader. */ 2477 std::string transform_feedback_variable_setters( 2478 ""); /* String containing all initializations of custom outputs from vertex shader. */ 2479 std::vector<std::string> transform_feedback_varyings(m_max_transform_feedback_components); /* Varyings array. */ 2480 std::vector<const glw::GLchar*> transform_feedback_varyings_c( 2481 m_max_transform_feedback_components); /* Varyings array in C form to pass to the GL. */ 2482 2483 glw::GLint user_defined_transform_feedback_interleaved_varyings_count = 2484 m_max_transform_feedback_components /* total max to be written by the shader */ 2485 / 4 /* components per vec4 */ 2486 - 1 /* gl_Position */; 2487 2488 glw::GLint all_transform_feedback_interleaved_varyings_count = 2489 user_defined_transform_feedback_interleaved_varyings_count + 1 /* gl_Position */; 2490 2491 /* Most of varyings is declarated output variables. */ 2492 for (glw::GLint i = 0; i < user_defined_transform_feedback_interleaved_varyings_count; ++i) 2493 { 2494 std::string varying = "result_"; 2495 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i)); 2496 2497 transform_feedback_varyings[i] = varying; 2498 2499 transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str(); 2500 2501 transform_feedback_variable_declarations.append("out vec4 "); 2502 transform_feedback_variable_declarations.append(varying); 2503 transform_feedback_variable_declarations.append(";\n"); 2504 2505 transform_feedback_variable_setters.append(" "); 2506 transform_feedback_variable_setters.append(varying); 2507 transform_feedback_variable_setters.append(" = vec4("); 2508 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4)); 2509 transform_feedback_variable_setters.append(".0, "); 2510 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 1)); 2511 transform_feedback_variable_setters.append(".0, "); 2512 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 2)); 2513 transform_feedback_variable_setters.append(".0, "); 2514 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 3)); 2515 transform_feedback_variable_setters.append(".0);\n"); 2516 } 2517 2518 /* Last four varying components are gl_Position components. */ 2519 transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count] = "gl_Position"; 2520 2521 transform_feedback_varyings_c[user_defined_transform_feedback_interleaved_varyings_count] = 2522 transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count].c_str(); 2523 2524 /* Preprocess vertex shader source code template. */ 2525 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 2526 vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations); 2527 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS", 2528 transform_feedback_variable_setters); 2529 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 2530 vertex_shader, "TEMPLATE_RASTERIZATION_EPSILON", 2531 gl3cts::TransformFeedback::Utilities::ftoa(s_rasterization_epsilon)); 2532 2533 /* Compile, link and check. */ 2534 m_program = gl3cts::TransformFeedback::Utilities::buildProgram( 2535 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader_source_code, 2536 &transform_feedback_varyings_c[0], all_transform_feedback_interleaved_varyings_count, m_attrib_type); 2537 2538 if (0 == m_program) 2539 { 2540 throw 0; 2541 } 2542 } 2543 2544 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createFramebuffer(void) 2545 { 2546 /* Functions handler */ 2547 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2548 2549 /* Setting clear color */ 2550 gl.clearColor(0.f, 0.f, 0.f, 1.f); 2551 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 2552 2553 /* Creating framebuffer */ 2554 gl.genFramebuffers(1, &m_framebuffer); 2555 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed."); 2556 2557 gl.genRenderbuffers(1, &m_renderbuffer); 2558 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed."); 2559 2560 gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); 2561 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); 2562 2563 gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer); 2564 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed."); 2565 2566 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32F, s_framebuffer_size, s_framebuffer_size); 2567 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed."); 2568 2569 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer); 2570 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed."); 2571 2572 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 2573 { 2574 throw 0; 2575 } 2576 2577 gl.viewport(0, 0, s_framebuffer_size, s_framebuffer_size); 2578 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed."); 2579 } 2580 2581 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createTransformFeedbackBuffer(void) 2582 { 2583 /* Functions handler */ 2584 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2585 2586 /* Creating xfb buffer */ 2587 gl.genBuffers(1, &m_buffer); 2588 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 2589 2590 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer); 2591 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 2592 2593 m_buffer_size = 2594 static_cast<glw::GLuint>(m_max_transform_feedback_components * m_max_vertices_drawn * sizeof(glw::GLfloat)); 2595 2596 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_size, NULL, GL_DYNAMIC_READ); 2597 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 2598 } 2599 2600 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createVertexArrayObject(void) 2601 { 2602 /* Functions handler */ 2603 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2604 2605 /* VAO Creations */ 2606 gl.genVertexArrays(1, &m_vertex_array_object); 2607 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 2608 2609 gl.bindVertexArray(m_vertex_array_object); 2610 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 2611 } 2612 2613 void gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(glw::GLuint primitive_case) 2614 { 2615 /* Functions handler */ 2616 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2617 2618 /* Draw */ 2619 gl.clear(GL_COLOR_BUFFER_BIT); 2620 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 2621 2622 gl.beginTransformFeedback(s_primitive_cases_xfb[primitive_case]); 2623 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedbac call failed."); 2624 2625 gl.drawElements(s_primitive_cases[primitive_case], s_element_indices_counts[primitive_case], GL_UNSIGNED_INT, 2626 s_element_indices[primitive_case]); 2627 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements call failed."); 2628 2629 gl.endTransformFeedback(); 2630 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedbac call failed."); 2631 } 2632 2633 bool gl3cts::TransformFeedback::CaptureVertexInterleaved::checkFramebuffer(glw::GLenum primitive_type UNUSED) 2634 { 2635 /* Functions handler */ 2636 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2637 2638 /* Fetch framebuffer. */ 2639 std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size); 2640 2641 if ((s_framebuffer_size > 0) && (s_framebuffer_size > 0)) 2642 { 2643 gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data()); 2644 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 2645 } 2646 2647 /* Check results. 2648 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */ 2649 for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i) 2650 { 2651 if (fabs(*i - 0.5f) > 0.0625f /* precision */) 2652 { 2653 return false; 2654 } 2655 } 2656 2657 return true; 2658 } 2659 2660 bool gl3cts::TransformFeedback::CaptureVertexInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED, 2661 glw::GLenum primitive_type) 2662 { 2663 /* Functions handler */ 2664 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2665 2666 /* Check */ 2667 glw::GLuint number_of_vertices = 0; 2668 2669 switch (primitive_type) 2670 { 2671 case GL_POINTS: 2672 number_of_vertices = 4; 2673 break; 2674 case GL_LINES: 2675 number_of_vertices = 4; 2676 break; 2677 case GL_LINE_LOOP: 2678 number_of_vertices = 8; 2679 break; 2680 case GL_LINE_STRIP: 2681 number_of_vertices = 6; 2682 break; 2683 case GL_TRIANGLES: 2684 number_of_vertices = 6; 2685 break; 2686 case GL_TRIANGLE_STRIP: 2687 number_of_vertices = 6; 2688 break; 2689 case GL_TRIANGLE_FAN: 2690 number_of_vertices = 6; 2691 break; 2692 default: 2693 throw 0; 2694 } 2695 2696 glw::GLfloat* results = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 2697 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed."); 2698 2699 bool is_ok = true; 2700 2701 for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j) 2702 { 2703 for (glw::GLint i = 0; i < m_max_transform_feedback_components - 4; ++i) 2704 { 2705 glw::GLfloat result = results[i + j * m_max_transform_feedback_components]; 2706 glw::GLfloat reference = (glw::GLfloat)(i); 2707 2708 if (fabs(result - reference) > 0.125 /* precision */) 2709 { 2710 is_ok = false; 2711 2712 break; 2713 } 2714 } 2715 2716 /* gl_Position */ 2717 glw::GLfloat result[4] = { results[(j + 1) * m_max_transform_feedback_components - 4], 2718 results[(j + 1) * m_max_transform_feedback_components - 3], 2719 results[(j + 1) * m_max_transform_feedback_components - 2], 2720 results[(j + 1) * m_max_transform_feedback_components - 1] }; 2721 2722 if ((fabs(fabs(result[0]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) || 2723 (fabs(fabs(result[1]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) || 2724 (fabs(result[2]) > 0.125 /* precision */) || (fabs(result[3] - 1.0) > 0.125 /* precision */)) 2725 { 2726 is_ok = false; 2727 2728 break; 2729 } 2730 } 2731 2732 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 2733 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 2734 2735 return is_ok; 2736 } 2737 2738 void gl3cts::TransformFeedback::CaptureVertexInterleaved::bindBuffer(BindBufferCase bind_case) 2739 { 2740 /* Functions handler */ 2741 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2742 2743 switch (bind_case) 2744 { 2745 case BIND_BUFFER_BASE_CASE: 2746 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer); 2747 break; 2748 case BIND_BUFFER_RANGE_CASE: 2749 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer, 0, m_buffer_size); 2750 break; 2751 case BIND_BUFFER_OFFSET_CASE: 2752 if (DE_NULL == m_glBindBufferOffsetEXT) 2753 { 2754 throw 0; 2755 } 2756 m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer, 0); 2757 break; 2758 default: 2759 throw 0; 2760 } 2761 } 2762 2763 void gl3cts::TransformFeedback::CaptureVertexInterleaved::clean(void) 2764 { 2765 /* Functions handler */ 2766 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2767 2768 if (m_program) 2769 { 2770 gl.deleteProgram(m_program); 2771 2772 m_program = 0; 2773 } 2774 2775 if (m_framebuffer) 2776 { 2777 gl.deleteFramebuffers(1, &m_framebuffer); 2778 2779 m_framebuffer = 0; 2780 } 2781 2782 if (m_renderbuffer) 2783 { 2784 gl.deleteRenderbuffers(1, &m_renderbuffer); 2785 2786 m_renderbuffer = 0; 2787 } 2788 2789 cleanBuffer(); 2790 2791 if (m_vertex_array_object) 2792 { 2793 gl.deleteVertexArrays(1, &m_vertex_array_object); 2794 2795 m_vertex_array_object = 0; 2796 } 2797 } 2798 2799 void gl3cts::TransformFeedback::CaptureVertexInterleaved::cleanBuffer(void) 2800 { 2801 /* Functions handler */ 2802 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2803 2804 if (m_buffer) 2805 { 2806 gl.deleteBuffers(1, &m_buffer); 2807 2808 m_buffer = 0; 2809 } 2810 } 2811 2812 const glw::GLchar* gl3cts::TransformFeedback::CaptureVertexInterleaved::s_vertex_shader_source_code_template = 2813 "#version 130\n" 2814 "\n" 2815 "TEMPLATE_INPUT_OUTPUT_DECLARATIONS" 2816 "\n" 2817 "void main()\n" 2818 "{\n" 2819 "TEMPLATE_OUTPUT_SETTERS" 2820 "\n" 2821 " vec4 position = vec4(0.0);\n" 2822 "\n" 2823 " /* Note: The points are moved 0.0625 from the borders to\n" 2824 " reduce non-XFB related rasterization problems. */\n" 2825 " switch(gl_VertexID)\n" 2826 " {\n" 2827 " case 0:\n" 2828 " position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 2829 "1.0);\n" 2830 " break;\n" 2831 " case 1:\n" 2832 " position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 2833 "1.0);\n" 2834 " break;\n" 2835 " case 2:\n" 2836 " position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 2837 "1.0);\n" 2838 " break;\n" 2839 " case 3:\n" 2840 " position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 2841 "1.0);\n" 2842 " break;\n" 2843 " }\n" 2844 "\n" 2845 " gl_Position = position;\n" 2846 "}\n"; 2847 2848 const glw::GLchar* gl3cts::TransformFeedback::CaptureVertexInterleaved::s_fragment_shader_source_code = 2849 "#version 130\n" 2850 "\n" 2851 "out vec4 color;\n" 2852 "\n" 2853 "void main()\n" 2854 "{\n" 2855 " color = vec4(0.5);\n" 2856 "}\n"; 2857 2858 const glw::GLuint 2859 gl3cts::TransformFeedback::CaptureVertexInterleaved::s_element_indices[][s_max_element_indices_count] = { 2860 { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, { 0, 1, 3, 2 }, { 0, 1, 3, 2 }, 2861 { 2, 0, 1, 2, 1, 3 }, { 0, 1, 2, 3 }, { 2, 0, 1, 3 } 2862 }; 2863 2864 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases_count = 2865 sizeof(s_element_indices) / sizeof(s_element_indices[0]); 2866 2867 const glw::GLenum gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases[] = { 2868 GL_POINTS, GL_LINES, GL_LINE_LOOP, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN 2869 }; 2870 2871 const glw::GLenum gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases_xfb[] = { 2872 GL_POINTS, GL_LINES, GL_LINES, GL_LINES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES 2873 }; 2874 2875 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_element_indices_counts[] = { 4, 4, 4, 4, 2876 6, 4, 4 }; 2877 2878 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_framebuffer_size = 2879 2; /* If you change this, update checkFramebuffer function according. */ 2880 2881 const glw::GLfloat gl3cts::TransformFeedback::CaptureVertexInterleaved::s_rasterization_epsilon = 0.0625; 2882 2883 /*-----------------------------------------------------------------------------------------------*/ 2884 2885 gl3cts::TransformFeedback::CaptureGeometryInterleaved::CaptureGeometryInterleaved(deqp::Context& context, 2886 const char* test_name, 2887 const char* test_description) 2888 : CaptureVertexInterleaved(context, test_name, test_description) 2889 { 2890 } 2891 2892 gl3cts::TransformFeedback::CaptureGeometryInterleaved::~CaptureGeometryInterleaved(void) 2893 { 2894 } 2895 2896 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureGeometryInterleaved::iterate(void) 2897 { 2898 /* Functions handler */ 2899 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2900 2901 /* Initializations. */ 2902 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0))); 2903 bool is_at_least_gl_32 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 2))); 2904 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback"); 2905 bool is_arb_gs_4 = m_context.getContextInfo().isExtensionSupported("GL_ARB_geometry_shader4"); 2906 2907 bool is_ok = true; 2908 bool test_error = false; 2909 2910 /* Tests. */ 2911 try 2912 { 2913 if ((is_at_least_gl_30 || is_ext_tf_1) && (is_at_least_gl_32 || is_arb_gs_4)) 2914 { 2915 fetchLimits(); 2916 createFramebuffer(); 2917 createTransformFeedbackBuffer(); 2918 createVertexArrayObject(); 2919 2920 for (glw::GLuint i_primitive_case = 0; 2921 (i_primitive_case < s_geometry_interleaved_primitive_cases_count) && is_ok; ++i_primitive_case) 2922 { 2923 buildProgram(i_primitive_case); 2924 2925 gl.useProgram(m_program); 2926 2927 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 2928 2929 for (glw::GLint i_bind_case = 0; (i_bind_case < BIND_BUFFER_CASES_COUNT) && is_ok; ++i_bind_case) 2930 { 2931 if ((i_bind_case == BIND_BUFFER_OFFSET_CASE) && (DE_NULL == m_glBindBufferOffsetEXT)) 2932 { 2933 continue; 2934 } 2935 2936 bindBuffer((BindBufferCase)i_bind_case); 2937 2938 draw(i_primitive_case); 2939 2940 is_ok = is_ok && checkFramebuffer(s_primitive_cases[i_primitive_case]); 2941 is_ok = is_ok && 2942 checkTransformFeedbackBuffer((BindBufferCase)i_bind_case, 2943 s_geometry_interleaved_primitive_cases_xfb[i_primitive_case]); 2944 } 2945 2946 gl.deleteProgram(m_program); 2947 2948 m_program = 0; 2949 2950 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram call failed."); 2951 } 2952 } 2953 } 2954 catch (...) 2955 { 2956 is_ok = false; 2957 test_error = true; 2958 } 2959 2960 /* Clean objects. */ 2961 clean(); 2962 2963 /* Result's setup. */ 2964 if (is_ok) 2965 { 2966 /* Log success. */ 2967 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Geometry have passed." 2968 << tcu::TestLog::EndMessage; 2969 2970 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2971 } 2972 else 2973 { 2974 if (test_error) 2975 { 2976 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 2977 } 2978 else 2979 { 2980 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2981 } 2982 } 2983 2984 return STOP; 2985 } 2986 2987 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::fetchLimits(void) 2988 { 2989 /* Functions handler */ 2990 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2991 2992 /* Fetching limits. */ 2993 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_transform_feedback_components); 2994 2995 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2996 2997 if (m_max_transform_feedback_components == 0) 2998 { 2999 throw 0; 3000 } 3001 3002 glw::GLint max_geometry_total_components = 0; 3003 3004 gl.getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &max_geometry_total_components); 3005 3006 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 3007 3008 if (max_geometry_total_components == 0) 3009 { 3010 throw 0; 3011 } 3012 3013 if (m_max_transform_feedback_components * 4 > max_geometry_total_components) 3014 { 3015 m_max_transform_feedback_components = max_geometry_total_components / 4; 3016 } 3017 } 3018 3019 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::buildProgram(glw::GLuint primitive_case) 3020 { 3021 /* Functions handler */ 3022 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3023 3024 /* Preparing source code. */ 3025 std::string geometry_shader(s_geometry_shader_source_code_template); /* Storage for vertex shader source code. */ 3026 std::string transform_feedback_variable_declarations( 3027 ""); /* String to contain all custom outputs from vertex shader. */ 3028 std::string transform_feedback_variable_setters( 3029 ""); /* String containing all initializations of custom outputs from vertex shader. */ 3030 std::vector<std::string> transform_feedback_varyings(m_max_transform_feedback_components); /* Varyings array. */ 3031 std::vector<const glw::GLchar*> transform_feedback_varyings_c( 3032 m_max_transform_feedback_components); /* Varyings array in C form to pass to the GL. */ 3033 3034 glw::GLint user_defined_transform_feedback_interleaved_varyings_count = 3035 m_max_transform_feedback_components /* total max to be written by the shader */ 3036 / 4 /* components per vec4 */ 3037 // / 4 /* number of vertices */ 3038 - 1 /* gl_Position */; 3039 3040 glw::GLint all_transform_feedback_interleaved_varyings_count = 3041 user_defined_transform_feedback_interleaved_varyings_count + 1 /* gl_Position */; 3042 3043 /* Most of varyings is declarated output variables. */ 3044 for (glw::GLint i = 0; i < user_defined_transform_feedback_interleaved_varyings_count; ++i) 3045 { 3046 /* Preparing variable name. */ 3047 std::string varying = "result_"; 3048 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i)); 3049 3050 transform_feedback_varyings[i] = varying; 3051 3052 transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str(); 3053 3054 /* Preparing variable declaration. */ 3055 transform_feedback_variable_declarations.append("out vec4 "); 3056 transform_feedback_variable_declarations.append(varying); 3057 transform_feedback_variable_declarations.append(";\n"); 3058 3059 /* Preparing variable setters. */ 3060 transform_feedback_variable_setters.append(" "); 3061 transform_feedback_variable_setters.append(varying); 3062 transform_feedback_variable_setters.append(" = vec4("); 3063 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4)); 3064 transform_feedback_variable_setters.append(".0, "); 3065 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 1)); 3066 transform_feedback_variable_setters.append(".0, "); 3067 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 2)); 3068 transform_feedback_variable_setters.append(".0, "); 3069 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 3)); 3070 transform_feedback_variable_setters.append(".0);\n"); 3071 } 3072 3073 /* Last four varying components are gl_Position components. */ 3074 transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */] = 3075 "gl_Position"; 3076 3077 transform_feedback_varyings_c[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */] = 3078 transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */] 3079 .c_str(); 3080 3081 /* Preprocess vertex shader source code template. */ 3082 geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 3083 geometry_shader, "TEMPLATE_PRIMITIVE_TYPE", s_geometry_interleaved_primitive_cases[primitive_case]); 3084 geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 3085 geometry_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations); 3086 geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(geometry_shader, "TEMPLATE_OUTPUT_SETTERS", 3087 transform_feedback_variable_setters); 3088 geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 3089 geometry_shader, "TEMPLATE_RASTERIZATION_EPSILON", 3090 gl3cts::TransformFeedback::Utilities::ftoa(s_rasterization_epsilon)); 3091 3092 /* Compile, link and check. */ 3093 m_program = gl3cts::TransformFeedback::Utilities::buildProgram( 3094 gl, m_context.getTestContext().getLog(), geometry_shader.c_str(), NULL, NULL, s_blank_vertex_shader_source_code, 3095 s_fragment_shader_source_code, &transform_feedback_varyings_c[0], 3096 all_transform_feedback_interleaved_varyings_count, m_attrib_type); 3097 3098 if (0 == m_program) 3099 { 3100 throw 0; 3101 } 3102 } 3103 3104 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(glw::GLuint primitive_case) 3105 { 3106 /* Functions handler */ 3107 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3108 3109 gl.clear(GL_COLOR_BUFFER_BIT); 3110 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 3111 3112 gl.beginTransformFeedback(s_geometry_interleaved_primitive_cases_xfb[primitive_case]); 3113 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 3114 3115 gl.drawArrays(GL_POINTS, 0, 1); 3116 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 3117 3118 gl.endTransformFeedback(); 3119 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedbac call failed."); 3120 } 3121 3122 const glw::GLchar* gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_shader_source_code_template = 3123 "#version 150\n" 3124 "\n" 3125 "layout(points) in;\n" 3126 "layout(TEMPLATE_PRIMITIVE_TYPE, max_vertices = 4) out;\n" 3127 "\n" 3128 "TEMPLATE_INPUT_OUTPUT_DECLARATIONS" 3129 "\n" 3130 "void main()\n" 3131 "{\n" 3132 " /* Note: The points are moved 0.0625 from the borders to\n" 3133 " reduce non-XFB related rasterization problems. */\n" 3134 "\n" 3135 " gl_Position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 3136 "1.0);\n" 3137 "TEMPLATE_OUTPUT_SETTERS" 3138 " EmitVertex();\n" 3139 "\n" 3140 " gl_Position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 3141 "1.0);\n" 3142 "TEMPLATE_OUTPUT_SETTERS" 3143 " EmitVertex();\n" 3144 "\n" 3145 " gl_Position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 3146 "1.0);\n" 3147 "TEMPLATE_OUTPUT_SETTERS" 3148 " EmitVertex();\n" 3149 "\n" 3150 " gl_Position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 3151 "1.0);\n" 3152 "TEMPLATE_OUTPUT_SETTERS" 3153 " EmitVertex();\n" 3154 "}\n"; 3155 3156 const glw::GLchar* gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_blank_vertex_shader_source_code = 3157 "#version 130\n" 3158 "\n" 3159 "void main()\n" 3160 "{\n" 3161 "}\n"; 3162 3163 const glw::GLchar* gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases[] = { 3164 "points", "line_strip", "triangle_strip" 3165 }; 3166 3167 const glw::GLenum gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases_xfb[] = 3168 { GL_POINTS, GL_LINES, GL_TRIANGLES }; 3169 3170 const glw::GLuint gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases_count = 3171 sizeof(s_geometry_interleaved_primitive_cases) / sizeof(s_geometry_interleaved_primitive_cases[0]); 3172 3173 /*-----------------------------------------------------------------------------------------------*/ 3174 3175 gl3cts::TransformFeedback::CaptureVertexSeparate::CaptureVertexSeparate(deqp::Context& context, const char* test_name, 3176 const char* test_description) 3177 : CaptureVertexInterleaved(context, test_name, test_description) 3178 , m_buffers(DE_NULL) 3179 , m_max_transform_feedback_separate_attribs(0) 3180 { 3181 m_attrib_type = GL_SEPARATE_ATTRIBS; 3182 } 3183 3184 void gl3cts::TransformFeedback::CaptureVertexSeparate::fetchLimits(void) 3185 { 3186 /* Functions handler */ 3187 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3188 3189 /* Fetching limits. */ 3190 glw::GLint max_transform_feedback_separate_components; 3191 3192 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components); 3193 3194 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 3195 3196 if (max_transform_feedback_separate_components < 4) 3197 { 3198 throw 0; 3199 } 3200 3201 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_max_transform_feedback_separate_attribs); 3202 3203 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 3204 3205 if (m_max_transform_feedback_separate_attribs == 0) 3206 { 3207 throw 0; 3208 } 3209 3210 m_max_transform_feedback_components = m_max_transform_feedback_separate_attribs * 4 /* vec4 is used */; 3211 3212 glw::GLint max_varyings_components = 0; 3213 3214 gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings_components); 3215 3216 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 3217 3218 if (max_varyings_components == 0) 3219 { 3220 throw 0; 3221 } 3222 3223 if (m_max_transform_feedback_components > max_varyings_components) 3224 { 3225 m_max_transform_feedback_components = max_varyings_components; 3226 } 3227 } 3228 3229 void gl3cts::TransformFeedback::CaptureVertexSeparate::createTransformFeedbackBuffer(void) 3230 { 3231 /* Functions handler */ 3232 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3233 3234 m_buffers = new glw::GLuint[m_max_transform_feedback_components]; 3235 3236 if (DE_NULL == m_buffers) 3237 { 3238 throw 0; 3239 } 3240 3241 gl.genBuffers(m_max_transform_feedback_separate_attribs, m_buffers); 3242 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 3243 3244 m_buffer_size = static_cast<glw::GLuint>(m_max_vertices_drawn * 4 /* vec4 */ * sizeof(glw::GLfloat)); 3245 3246 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i) 3247 { 3248 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[i]); 3249 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 3250 3251 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_size, NULL, GL_DYNAMIC_READ); 3252 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 3253 } 3254 } 3255 3256 void gl3cts::TransformFeedback::CaptureVertexSeparate::bindBuffer(BindBufferCase bind_case) 3257 { 3258 /* Functions handler */ 3259 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3260 3261 switch (bind_case) 3262 { 3263 case BIND_BUFFER_BASE_CASE: 3264 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i) 3265 { 3266 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i]); 3267 } 3268 break; 3269 case BIND_BUFFER_RANGE_CASE: 3270 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i) 3271 { 3272 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i], 0, m_buffer_size); 3273 } 3274 break; 3275 case BIND_BUFFER_OFFSET_CASE: 3276 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i) 3277 { 3278 m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffers[i], 0); 3279 } 3280 break; 3281 default: 3282 throw 0; 3283 } 3284 } 3285 3286 void gl3cts::TransformFeedback::CaptureVertexSeparate::cleanBuffer(void) 3287 { 3288 /* Functions handler */ 3289 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3290 3291 if (DE_NULL != m_buffers) 3292 { 3293 gl.deleteBuffers(m_max_transform_feedback_separate_attribs, m_buffers); 3294 3295 delete[] m_buffers; 3296 3297 m_buffers = DE_NULL; 3298 } 3299 } 3300 3301 bool gl3cts::TransformFeedback::CaptureVertexSeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED, 3302 glw::GLenum primitive_type) 3303 { 3304 /* Functions handler */ 3305 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3306 3307 glw::GLuint number_of_vertices = 0; 3308 3309 switch (primitive_type) 3310 { 3311 case GL_POINTS: 3312 number_of_vertices = 4; 3313 break; 3314 case GL_LINES: 3315 number_of_vertices = 4; 3316 break; 3317 case GL_LINE_LOOP: 3318 number_of_vertices = 8; 3319 break; 3320 case GL_LINE_STRIP: 3321 number_of_vertices = 6; 3322 break; 3323 case GL_TRIANGLES: 3324 number_of_vertices = 6; 3325 break; 3326 case GL_TRIANGLE_STRIP: 3327 number_of_vertices = 6; 3328 break; 3329 case GL_TRIANGLE_FAN: 3330 number_of_vertices = 6; 3331 break; 3332 default: 3333 throw 0; 3334 } 3335 3336 bool is_ok = true; 3337 3338 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs - 1; ++i) 3339 { 3340 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[i]); 3341 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 3342 3343 glw::GLfloat* results = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 3344 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed."); 3345 3346 for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j) 3347 { 3348 for (glw::GLuint k = 0; k < 4 /* vec4 */; ++k) 3349 { 3350 glw::GLfloat result = results[j * 4 + k]; 3351 glw::GLfloat reference = (glw::GLfloat)(i * 4 + k); 3352 3353 if (fabs(result - reference) > 0.125 /* precision */) 3354 { 3355 is_ok = false; 3356 3357 break; 3358 } 3359 } 3360 } 3361 3362 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 3363 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 3364 } 3365 3366 /* gl_Position */ 3367 if (is_ok) 3368 { 3369 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[m_max_transform_feedback_separate_attribs - 1]); 3370 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 3371 3372 glw::GLfloat* results = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 3373 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed."); 3374 3375 for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j) 3376 { 3377 glw::GLfloat result[4] = { results[j * 4], results[j * 4 + 1], results[j * 4 + 2], results[j * 4 + 3] }; 3378 3379 if ((fabs(fabs(result[0]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) || 3380 (fabs(fabs(result[1]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) || 3381 (fabs(result[2]) > 0.125 /* precision */) || (fabs(result[3] - 1.0) > 0.125 /* precision */)) 3382 { 3383 is_ok = false; 3384 3385 break; 3386 } 3387 } 3388 3389 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 3390 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 3391 } 3392 3393 return is_ok; 3394 } 3395 3396 /*-----------------------------------------------------------------------------------------------*/ 3397 3398 gl3cts::TransformFeedback::CaptureGeometrySeparate::CaptureGeometrySeparate(deqp::Context& context, 3399 const char* test_name, 3400 const char* test_description) 3401 : CaptureVertexInterleaved(context, test_name, test_description) 3402 , CaptureVertexSeparate(context, test_name, test_description) 3403 , CaptureGeometryInterleaved(context, test_name, test_description) 3404 , m_buffers(DE_NULL) 3405 , m_max_transform_feedback_separate_attribs(0) 3406 { 3407 } 3408 3409 /*-----------------------------------------------------------------------------------------------*/ 3410 3411 gl3cts::TransformFeedback::CheckGetXFBVarying::CheckGetXFBVarying(deqp::Context& context, const char* test_name, 3412 const char* test_description) 3413 : deqp::TestCase(context, test_name, test_description) 3414 , m_context(context) 3415 , m_max_xfb_interleaved_components(0) 3416 , m_max_xfb_separate_attributes(0) 3417 , m_max_xfb_separate_components(0) 3418 , m_max_varying_components(0) 3419 , m_max_varying_vectors(0) 3420 , m_max_geometry_total_output_components(0) 3421 { 3422 } 3423 3424 gl3cts::TransformFeedback::CheckGetXFBVarying::~CheckGetXFBVarying(void) 3425 { 3426 } 3427 3428 void gl3cts::TransformFeedback::CheckGetXFBVarying::fetchLimits(void) 3429 { 3430 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3431 3432 /* Fetching limits. */ 3433 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_xfb_interleaved_components); 3434 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_max_xfb_separate_attributes); 3435 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &m_max_xfb_separate_components); 3436 gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &m_max_varying_components); 3437 gl.getIntegerv(GL_MAX_VARYING_VECTORS, &m_max_varying_vectors); 3438 gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &m_max_geometry_total_output_components); 3439 3440 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 3441 } 3442 3443 glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::numberOfAttributes(glw::GLuint capture_way, 3444 glw::GLuint shader_case, 3445 glw::GLuint varying_type) 3446 { 3447 /* Setup limits of the case. */ 3448 const glw::GLuint max_total_components = 3449 ((s_shader_cases[shader_case].geometry_shader == DE_NULL) ? m_max_varying_components : 3450 m_max_geometry_total_output_components) - 3451 4 /* gl_Position is not captured */; 3452 3453 const glw::GLuint attribute_components = s_varying_types[varying_type].components_count; 3454 const glw::GLuint max_xfb_components = (s_capture_ways[capture_way] == GL_INTERLEAVED_ATTRIBS) ? 3455 m_max_xfb_interleaved_components : 3456 (attribute_components * m_max_xfb_separate_components); 3457 3458 if (s_capture_ways[capture_way] == GL_SEPARATE_ATTRIBS) 3459 { 3460 if (attribute_components > glw::GLuint(m_max_xfb_separate_components)) 3461 { 3462 return 0; 3463 } 3464 } 3465 3466 /* Setup number of attributes. */ 3467 glw::GLuint number_of_attributes = max_xfb_components / attribute_components; 3468 3469 if (s_capture_ways[capture_way] == GL_SEPARATE_ATTRIBS && 3470 number_of_attributes > glw::GLuint(m_max_xfb_separate_attributes)) 3471 { 3472 number_of_attributes = m_max_xfb_separate_attributes; 3473 } 3474 3475 /* Clamp to limits. */ 3476 if (number_of_attributes * attribute_components > max_total_components) 3477 { 3478 number_of_attributes = max_total_components / attribute_components; 3479 } 3480 3481 /* Vectors limit. */ 3482 if (attribute_components <= 4) 3483 { 3484 if (number_of_attributes > glw::GLuint(m_max_varying_vectors)) 3485 { 3486 number_of_attributes = m_max_varying_vectors; 3487 } 3488 } 3489 else 3490 { 3491 if (number_of_attributes > glw::GLuint(m_max_varying_vectors) / 4) 3492 { 3493 number_of_attributes = glw::GLuint(m_max_varying_vectors) / 4; 3494 } 3495 } 3496 3497 /* Return. */ 3498 return number_of_attributes; 3499 } 3500 3501 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CheckGetXFBVarying::iterate(void) 3502 { 3503 /* Functions handler */ 3504 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3505 3506 /* Initializations. */ 3507 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0))); 3508 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback"); 3509 3510 bool is_ok = true; 3511 bool test_error = false; 3512 3513 glw::GLuint program = 0; 3514 3515 /* Tests. */ 3516 try 3517 { 3518 if (is_at_least_gl_30 || is_ext_tf_1) 3519 { 3520 fetchLimits(); 3521 3522 for (glw::GLuint i = 0; (i < s_capture_ways_count) && is_ok; ++i) 3523 { 3524 for (glw::GLuint j = 0; (j < s_shader_cases_count) && is_ok; ++j) 3525 { 3526 for (glw::GLuint k = 0; (k < s_varying_types_count) && is_ok; ++k) 3527 { 3528 glw::GLuint n = numberOfAttributes(i, j, k); 3529 3530 if (n) 3531 { 3532 program = buildProgram(i, j, k, n); 3533 3534 is_ok = is_ok && (program != 0); 3535 3536 is_ok = is_ok && check(program, i, j, k, n); 3537 3538 gl.deleteProgram(program); 3539 3540 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram call failed."); 3541 3542 program = 0; 3543 } 3544 } 3545 } 3546 } 3547 } 3548 } 3549 catch (...) 3550 { 3551 is_ok = false; 3552 test_error = true; 3553 3554 if (program) 3555 { 3556 gl.deleteProgram(program); 3557 3558 program = 0; 3559 } 3560 } 3561 3562 /* Result's setup. */ 3563 if (is_ok) 3564 { 3565 /* Log success. */ 3566 m_context.getTestContext().getLog() << tcu::TestLog::Message 3567 << "Test checking Get Transform Feedback Varying have passed." 3568 << tcu::TestLog::EndMessage; 3569 3570 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3571 } 3572 else 3573 { 3574 if (test_error) 3575 { 3576 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 3577 } 3578 else 3579 { 3580 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3581 } 3582 } 3583 3584 return STOP; 3585 } 3586 3587 glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::buildProgram(glw::GLuint capture_way, 3588 glw::GLuint shader_case, 3589 glw::GLuint varying_type, 3590 glw::GLuint number_of_attributes) 3591 { 3592 /* Functions handler */ 3593 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3594 3595 /* Preparing source code. */ 3596 std::string xfb_variable_declarations(""); 3597 std::string xfb_variable_setters(""); 3598 std::vector<std::string> xfb_varyings(number_of_attributes); 3599 std::vector<const glw::GLchar*> xfb_varyings_c(number_of_attributes); 3600 3601 /* Most of varyings is declarated output variables. */ 3602 for (glw::GLuint i = 0; i < number_of_attributes; ++i) 3603 { 3604 /* Varying name: result_# */ 3605 std::string varying = "result_"; 3606 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i)); 3607 3608 xfb_varyings[i] = varying; 3609 xfb_varyings_c[i] = xfb_varyings[i].c_str(); 3610 3611 /* Varying declaration: out TYPE result_#;*/ 3612 xfb_variable_declarations.append("out "); 3613 xfb_variable_declarations.append(s_varying_types[varying_type].name); 3614 xfb_variable_declarations.append(" "); 3615 xfb_variable_declarations.append(varying); 3616 xfb_variable_declarations.append(";\n"); 3617 3618 /* Varying setter: result_# = TYPE(#); */ 3619 xfb_variable_setters.append(" "); 3620 xfb_variable_setters.append(varying); 3621 xfb_variable_setters.append(" = "); 3622 xfb_variable_setters.append(s_varying_types[varying_type].name); 3623 xfb_variable_setters.append("("); 3624 xfb_variable_setters.append("2"); //gl3cts::TransformFeedback::Utilities::itoa(i)); 3625 if (s_varying_types[varying_type].float_component) 3626 { 3627 /* if varying is float varying setter is: result_# = TYPE(#.0); */ 3628 xfb_variable_setters.append(".0"); 3629 } 3630 xfb_variable_setters.append(");\n"); 3631 } 3632 3633 /* Preprocess vertex shader source code template. */ 3634 const glw::GLchar* vertex_shader = s_shader_cases[shader_case].vertex_shader; 3635 const glw::GLchar* geometry_shader = s_shader_cases[shader_case].geometry_shader; 3636 3637 std::string xfb_shader; 3638 3639 if (DE_NULL == s_shader_cases[shader_case].geometry_shader) 3640 { 3641 /* XFB tested in vertex shader. */ 3642 xfb_shader = vertex_shader; 3643 } 3644 else 3645 { 3646 /* XFB tested in geometry shader. */ 3647 xfb_shader = geometry_shader; 3648 } 3649 3650 /* Preprocess shader. */ 3651 xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_DECLARATIONS", 3652 xfb_variable_declarations); 3653 xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_SETTERS", 3654 xfb_variable_setters); 3655 3656 if (DE_NULL == s_shader_cases[shader_case].geometry_shader) 3657 { 3658 /* XFB tested in vertex shader. */ 3659 vertex_shader = xfb_shader.c_str(); 3660 } 3661 else 3662 { 3663 /* XFB tested in geometry shader. */ 3664 geometry_shader = xfb_shader.c_str(); 3665 } 3666 3667 /* Compile, link and check. */ 3668 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram( 3669 gl, m_context.getTestContext().getLog(), geometry_shader, NULL, NULL, vertex_shader, s_generic_fragment_shader, 3670 &xfb_varyings_c[0], number_of_attributes, s_capture_ways[capture_way]); 3671 3672 /* Check compilation status. */ 3673 if (0 == program) 3674 { 3675 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Building program has failed.\nVertex shader:\n" 3676 << vertex_shader << "Geometry shader:\n" 3677 << ((DE_NULL == geometry_shader) ? "" : geometry_shader) 3678 << "Fragment shader:\n" 3679 << s_generic_fragment_shader << tcu::TestLog::EndMessage; 3680 3681 throw 0; 3682 } 3683 3684 return program; 3685 } 3686 3687 bool gl3cts::TransformFeedback::CheckGetXFBVarying::check(glw::GLuint program, glw::GLuint capture_way, 3688 glw::GLuint shader_case UNUSED, glw::GLuint varying_type, 3689 glw::GLuint number_of_attributes) 3690 { 3691 /* Functions handler */ 3692 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3693 glw::GLuint max_length = 0; 3694 3695 /* Inspect glGetTransformFeedbackVarying. */ 3696 for (glw::GLuint i = 0; i < number_of_attributes; ++i) 3697 { 3698 const glw::GLsizei bufSize = 18; 3699 glw::GLsizei length = 0; 3700 glw::GLsizei size = 0; 3701 glw::GLenum type = GL_NONE; 3702 glw::GLchar name[18] = { 0 }; /* Size of bufSize. */ 3703 3704 gl.getTransformFeedbackVarying(program, i, bufSize, &length, &size, &type, name); 3705 3706 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbackVarying call failed."); 3707 3708 max_length = deMaxu32(max_length, glw::GLuint(length)); 3709 3710 /* Check name. */ 3711 if (length) 3712 { 3713 std::string varying = name; 3714 std::string varying_ref = "result_"; 3715 varying_ref.append(gl3cts::TransformFeedback::Utilities::itoa(i)); 3716 3717 if (0 != varying.compare(varying_ref)) 3718 { 3719 return false; 3720 } 3721 } 3722 else 3723 { 3724 return false; 3725 } 3726 3727 /* Check size. */ 3728 const glw::GLuint size_ref = 1; 3729 3730 if (size != size_ref) 3731 { 3732 return false; 3733 } 3734 3735 /* Check type. */ 3736 if (type != s_varying_types[varying_type].type) 3737 { 3738 return false; 3739 } 3740 } 3741 3742 /* Inspect glGetProgramiv. */ 3743 glw::GLint xfb_varyings = 0; 3744 glw::GLint xfb_mode = 0; 3745 glw::GLint xfb_varying_max_length = 0; 3746 3747 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &xfb_varyings); 3748 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, &xfb_mode); 3749 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &xfb_varying_max_length); 3750 3751 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed."); 3752 3753 if (glw::GLuint(xfb_varyings) != number_of_attributes) 3754 { 3755 return false; 3756 } 3757 3758 if (glw::GLenum(xfb_mode) != s_capture_ways[capture_way]) 3759 { 3760 return false; 3761 } 3762 3763 if (glw::GLuint(xfb_varying_max_length) < max_length) 3764 { 3765 return false; 3766 } 3767 3768 return true; 3769 } 3770 3771 const glw::GLchar* gl3cts::TransformFeedback::CheckGetXFBVarying::s_generic_fragment_shader = "#version 130\n" 3772 "\n" 3773 "out vec4 color;\n" 3774 "\n" 3775 "void main()\n" 3776 "{\n" 3777 " color = vec4(1.0);\n" 3778 "}\n"; 3779 3780 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::ShaderCase 3781 gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases[] = { { /* Vertex Shader. */ 3782 "#version 130\n" 3783 "\n" 3784 "TEMPLATE_OUTPUT_DECLARATIONS" 3785 "\n" 3786 "void main()\n" 3787 "{\n" 3788 " gl_Position = vec4(1.0);\n" 3789 "TEMPLATE_OUTPUT_SETTERS" 3790 "}\n", 3791 3792 /* Geometry Shader. */ 3793 NULL }, 3794 { /* Vertex Shader. */ 3795 "#version 130\n" 3796 "\n" 3797 "void main()\n" 3798 "{\n" 3799 "}\n", 3800 3801 /* Geometry Shader. */ 3802 "#version 150\n" 3803 "\n" 3804 "layout(points) in;\n" 3805 "layout(points, max_vertices = 1) out;\n" 3806 "\n" 3807 "TEMPLATE_OUTPUT_DECLARATIONS" 3808 "\n" 3809 "void main()\n" 3810 "{\n" 3811 " gl_Position = vec4(1.0);\n" 3812 "TEMPLATE_OUTPUT_SETTERS" 3813 " EmitVertex();\n" 3814 "}\n" } }; 3815 3816 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases_count = 3817 sizeof(s_shader_cases) / sizeof(s_shader_cases[0]); 3818 3819 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::VaryingType 3820 gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types[] = { 3821 /* type, name, #components, is component float */ 3822 { GL_FLOAT, "float", 1, true }, 3823 { GL_FLOAT_VEC2, "vec2", 2, true }, 3824 { GL_FLOAT_VEC3, "vec3", 3, true }, 3825 { GL_FLOAT_VEC4, "vec4", 4, true }, 3826 { GL_INT, "int", 1, false }, 3827 { GL_INT_VEC2, "ivec2", 2, false }, 3828 { GL_INT_VEC3, "ivec3", 3, false }, 3829 { GL_INT_VEC4, "ivec4", 4, false }, 3830 { GL_UNSIGNED_INT, "uint", 1, false }, 3831 { GL_UNSIGNED_INT_VEC2, "uvec2", 2, false }, 3832 { GL_UNSIGNED_INT_VEC3, "uvec3", 3, false }, 3833 { GL_UNSIGNED_INT_VEC4, "uvec4", 4, false }, 3834 { GL_FLOAT_MAT2, "mat2", 4, true }, 3835 { GL_FLOAT_MAT3, "mat3", 9, true }, 3836 { GL_FLOAT_MAT4, "mat4", 16, true } 3837 }; 3838 3839 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types_count = 3840 sizeof(s_varying_types) / sizeof(s_varying_types[0]); 3841 3842 const glw::GLenum gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways[] = { GL_INTERLEAVED_ATTRIBS, 3843 GL_SEPARATE_ATTRIBS }; 3844 3845 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways_count = 3846 sizeof(s_capture_ways) / sizeof(s_capture_ways[0]); 3847 3848 /*-----------------------------------------------------------------------------------------------*/ 3849 3850 gl3cts::TransformFeedback::QueryVertexInterleaved::QueryVertexInterleaved(deqp::Context& context, const char* test_name, 3851 const char* test_description) 3852 : CaptureVertexInterleaved(context, test_name, test_description), m_query_object(0) 3853 { 3854 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */ 3855 } 3856 3857 void gl3cts::TransformFeedback::QueryVertexInterleaved::createTransformFeedbackBuffer(void) 3858 { 3859 /* Functions handler */ 3860 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3861 3862 /* Create buffer object. */ 3863 gl3cts::TransformFeedback::CaptureVertexInterleaved::createTransformFeedbackBuffer(); 3864 3865 /* Create query object. */ 3866 gl.genQueries(1, &m_query_object); 3867 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed."); 3868 } 3869 3870 void gl3cts::TransformFeedback::QueryVertexInterleaved::draw(glw::GLuint primitive_case) 3871 { 3872 /* Functions handler */ 3873 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3874 3875 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object); 3876 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed."); 3877 3878 gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case); 3879 3880 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); 3881 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed."); 3882 } 3883 3884 bool gl3cts::TransformFeedback::QueryVertexInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED, 3885 glw::GLenum primitive_type) 3886 { 3887 /* Functions handler */ 3888 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3889 3890 glw::GLuint number_of_primitives; 3891 3892 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives); 3893 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed."); 3894 3895 /* expected result */ 3896 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */ 3897 3898 if (number_of_primitives_reference != number_of_primitives) 3899 { 3900 return false; 3901 } 3902 3903 return true; 3904 } 3905 3906 void gl3cts::TransformFeedback::QueryVertexInterleaved::clean(void) 3907 { 3908 /* Functions handler */ 3909 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3910 3911 /* Delete query object. */ 3912 gl.deleteQueries(1, &m_query_object); 3913 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed."); 3914 3915 /* Other */ 3916 gl3cts::TransformFeedback::CaptureVertexInterleaved::clean(); 3917 } 3918 3919 /*-----------------------------------------------------------------------------------------------*/ 3920 3921 gl3cts::TransformFeedback::QueryGeometryInterleaved::QueryGeometryInterleaved(deqp::Context& context, 3922 const char* test_name, 3923 const char* test_description) 3924 : CaptureVertexInterleaved(context, test_name, test_description) 3925 , CaptureGeometryInterleaved(context, test_name, test_description) 3926 { 3927 m_query_object = 0; 3928 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */ 3929 } 3930 3931 void gl3cts::TransformFeedback::QueryGeometryInterleaved::createTransformFeedbackBuffer(void) 3932 { 3933 /* Functions handler */ 3934 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3935 3936 /* Create buffer object. */ 3937 gl3cts::TransformFeedback::CaptureGeometryInterleaved::createTransformFeedbackBuffer(); 3938 3939 /* Create query object. */ 3940 gl.genQueries(1, &m_query_object); 3941 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed."); 3942 } 3943 3944 void gl3cts::TransformFeedback::QueryGeometryInterleaved::draw(glw::GLuint primitive_case) 3945 { 3946 /* Functions handler */ 3947 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3948 3949 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object); 3950 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed."); 3951 3952 gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case); 3953 3954 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); 3955 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed."); 3956 } 3957 3958 bool gl3cts::TransformFeedback::QueryGeometryInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED, 3959 glw::GLenum primitive_type) 3960 { 3961 /* Functions handler */ 3962 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3963 3964 glw::GLuint number_of_primitives; 3965 3966 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives); 3967 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed."); 3968 3969 /* expected result */ 3970 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */ 3971 3972 if (number_of_primitives_reference != number_of_primitives) 3973 { 3974 return false; 3975 } 3976 3977 return true; 3978 } 3979 3980 void gl3cts::TransformFeedback::QueryGeometryInterleaved::clean(void) 3981 { 3982 /* Functions handler */ 3983 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3984 3985 /* Delete query object. */ 3986 gl.deleteQueries(1, &m_query_object); 3987 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed."); 3988 3989 /* Other. */ 3990 gl3cts::TransformFeedback::CaptureGeometryInterleaved::clean(); 3991 } 3992 3993 /*-----------------------------------------------------------------------------------------------*/ 3994 3995 gl3cts::TransformFeedback::QueryVertexSeparate::QueryVertexSeparate(deqp::Context& context, const char* test_name, 3996 const char* test_description) 3997 : CaptureVertexInterleaved(context, test_name, test_description) 3998 , CaptureVertexSeparate(context, test_name, test_description) 3999 { 4000 m_query_object = 0; 4001 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */ 4002 } 4003 4004 void gl3cts::TransformFeedback::QueryVertexSeparate::createTransformFeedbackBuffer(void) 4005 { 4006 /* Functions handler */ 4007 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4008 4009 /* Create buffer object. */ 4010 gl3cts::TransformFeedback::CaptureVertexSeparate::createTransformFeedbackBuffer(); 4011 4012 /* Create query object. */ 4013 gl.genQueries(1, &m_query_object); 4014 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed."); 4015 } 4016 4017 void gl3cts::TransformFeedback::QueryVertexSeparate::draw(glw::GLuint primitive_case) 4018 { 4019 /* Functions handler */ 4020 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4021 4022 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object); 4023 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed."); 4024 4025 gl3cts::TransformFeedback::CaptureVertexSeparate::draw(primitive_case); 4026 4027 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); 4028 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed."); 4029 } 4030 4031 bool gl3cts::TransformFeedback::QueryVertexSeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED, 4032 glw::GLenum primitive_type) 4033 { 4034 /* Functions handler */ 4035 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4036 4037 glw::GLuint number_of_primitives; 4038 4039 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives); 4040 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed."); 4041 4042 /* expected result */ 4043 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */ 4044 4045 if (number_of_primitives_reference != number_of_primitives) 4046 { 4047 return false; 4048 } 4049 4050 return true; 4051 } 4052 4053 void gl3cts::TransformFeedback::QueryVertexSeparate::clean(void) 4054 { 4055 /* Functions handler */ 4056 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4057 4058 /* Delete query object. */ 4059 gl.deleteQueries(1, &m_query_object); 4060 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed."); 4061 4062 /* Other */ 4063 gl3cts::TransformFeedback::CaptureVertexSeparate::clean(); 4064 } 4065 4066 /*-----------------------------------------------------------------------------------------------*/ 4067 4068 gl3cts::TransformFeedback::QueryGeometrySeparate::QueryGeometrySeparate(deqp::Context& context, const char* test_name, 4069 const char* test_description) 4070 : CaptureVertexInterleaved(context, test_name, test_description) 4071 , CaptureVertexSeparate(context, test_name, test_description) 4072 , CaptureGeometrySeparate(context, test_name, test_description) 4073 { 4074 m_query_object = 0; 4075 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */ 4076 } 4077 4078 void gl3cts::TransformFeedback::QueryGeometrySeparate::createTransformFeedbackBuffer(void) 4079 { 4080 /* Functions handler */ 4081 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4082 4083 /* Create buffer object. */ 4084 gl3cts::TransformFeedback::CaptureGeometrySeparate::createTransformFeedbackBuffer(); 4085 4086 /* Create query object. */ 4087 gl.genQueries(1, &m_query_object); 4088 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed."); 4089 } 4090 4091 void gl3cts::TransformFeedback::QueryGeometrySeparate::draw(glw::GLuint primitive_case) 4092 { 4093 /* Functions handler */ 4094 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4095 4096 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object); 4097 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed."); 4098 4099 gl3cts::TransformFeedback::CaptureGeometrySeparate::draw(primitive_case); 4100 4101 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); 4102 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed."); 4103 } 4104 4105 bool gl3cts::TransformFeedback::QueryGeometrySeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED, 4106 glw::GLenum primitive_type) 4107 { 4108 /* Functions handler */ 4109 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4110 4111 glw::GLuint number_of_primitives; 4112 4113 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives); 4114 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed."); 4115 4116 /* expected result */ 4117 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */ 4118 4119 if (number_of_primitives_reference != number_of_primitives) 4120 { 4121 return false; 4122 } 4123 4124 return true; 4125 } 4126 4127 void gl3cts::TransformFeedback::QueryGeometrySeparate::clean(void) 4128 { 4129 /* Functions handler */ 4130 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4131 4132 /* Delete query object. */ 4133 gl.deleteQueries(1, &m_query_object); 4134 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed."); 4135 4136 /* Other */ 4137 gl3cts::TransformFeedback::CaptureGeometrySeparate::clean(); 4138 } 4139 4140 /*-----------------------------------------------------------------------------------------------*/ 4141 4142 gl3cts::TransformFeedback::DiscardVertex::DiscardVertex(deqp::Context& context, const char* test_name, 4143 const char* test_description) 4144 : CaptureVertexInterleaved(context, test_name, test_description) 4145 { 4146 } 4147 4148 void gl3cts::TransformFeedback::DiscardVertex::draw(glw::GLuint primitive_case) 4149 { 4150 /* Functions handler */ 4151 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4152 4153 /* Must clear before rasterizer discard */ 4154 gl.clear(GL_COLOR_BUFFER_BIT); 4155 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 4156 4157 gl.enable(GL_RASTERIZER_DISCARD); 4158 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 4159 4160 gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case); 4161 4162 gl.disable(GL_RASTERIZER_DISCARD); 4163 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 4164 } 4165 4166 bool gl3cts::TransformFeedback::DiscardVertex::checkFramebuffer(glw::GLuint primitive_case UNUSED) 4167 { 4168 /* Functions handler */ 4169 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4170 4171 /* Fetch framebuffer. */ 4172 std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size); 4173 4174 if ((s_framebuffer_size > 0) && (s_framebuffer_size > 0)) 4175 { 4176 gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data()); 4177 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 4178 } 4179 4180 /* Check results. 4181 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */ 4182 for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i) 4183 { 4184 if (fabs(*i) > 0.0625f /* precision */) 4185 { 4186 return false; 4187 } 4188 } 4189 4190 return true; 4191 } 4192 4193 /*-----------------------------------------------------------------------------------------------*/ 4194 4195 gl3cts::TransformFeedback::DiscardGeometry::DiscardGeometry(deqp::Context& context, const char* test_name, 4196 const char* test_description) 4197 : CaptureVertexInterleaved(context, test_name, test_description) 4198 , CaptureGeometryInterleaved(context, test_name, test_description) 4199 { 4200 } 4201 4202 void gl3cts::TransformFeedback::DiscardGeometry::draw(glw::GLuint primitive_case) 4203 { 4204 /* Functions handler */ 4205 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4206 4207 /* Must clear before rasterizer discard */ 4208 gl.clear(GL_COLOR_BUFFER_BIT); 4209 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 4210 4211 gl.enable(GL_RASTERIZER_DISCARD); 4212 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 4213 4214 gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case); 4215 4216 gl.disable(GL_RASTERIZER_DISCARD); 4217 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 4218 } 4219 4220 bool gl3cts::TransformFeedback::DiscardGeometry::checkFramebuffer(glw::GLuint primitive_case UNUSED) 4221 { 4222 /* Functions handler */ 4223 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4224 4225 /* Fetch framebuffer. */ 4226 std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size); 4227 4228 if ((s_framebuffer_size > 0) && (s_framebuffer_size > 0)) 4229 { 4230 gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data()); 4231 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 4232 } 4233 4234 /* Check results. 4235 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */ 4236 for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i) 4237 { 4238 if (fabs(*i) > 0.0625f /* precision */) 4239 { 4240 return false; 4241 } 4242 } 4243 4244 return true; 4245 } 4246 4247 /*-----------------------------------------------------------------------------------------------*/ 4248 4249 gl3cts::TransformFeedback::DrawXFB::DrawXFB(deqp::Context& context, const char* test_name, const char* test_description) 4250 : deqp::TestCase(context, test_name, test_description) 4251 , m_context(context) 4252 , m_program_id_xfb(0) 4253 , m_program_id_draw(0) 4254 , m_fbo_id(0) 4255 , m_rbo_id(0) 4256 , m_vao_id(0) 4257 { 4258 memset(m_xfb_id, 0, sizeof(m_xfb_id)); 4259 memset(m_bo_id, 0, sizeof(m_bo_id)); 4260 } 4261 4262 gl3cts::TransformFeedback::DrawXFB::~DrawXFB(void) 4263 { 4264 } 4265 4266 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFB::iterate(void) 4267 { 4268 /* Initializations. */ 4269 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 4270 bool is_arb_tf_2 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2"); 4271 4272 bool is_ok = true; 4273 bool test_error = false; 4274 4275 /* Tests. */ 4276 try 4277 { 4278 if (is_at_least_gl_40 || is_arb_tf_2) 4279 { 4280 for (glw::GLuint i = 0; (i < s_capture_modes_count) && is_ok; ++i) 4281 { 4282 prepare(s_capture_modes[i]); 4283 4284 bindVAO(m_vao_id); 4285 useProgram(m_program_id_xfb); 4286 4287 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j) 4288 { 4289 bindXFB(m_xfb_id[j]); 4290 bindBOForXFB(s_capture_modes[i], m_bo_id[j]); 4291 useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]); 4292 useGeometrySet(m_program_id_xfb, false); 4293 drawForCapture(true, true, false, false); 4294 4295 is_ok = is_ok && inspectXFBState(true, true); 4296 } 4297 4298 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j) 4299 { 4300 bindXFB(m_xfb_id[j]); 4301 useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]); 4302 useGeometrySet(m_program_id_xfb, true); 4303 drawForCapture(false, false, true, true); 4304 4305 is_ok = is_ok && inspectXFBState(false, false); 4306 } 4307 4308 useProgram(m_program_id_draw); 4309 4310 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j) 4311 { 4312 bindXFB(m_xfb_id[j]); 4313 bindBOForDraw(m_program_id_draw, s_capture_modes[i], m_bo_id[j]); 4314 drawToFramebuffer(m_xfb_id[j]); 4315 4316 is_ok = 4317 is_ok && checkFramebuffer(s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]); 4318 } 4319 4320 clean(); 4321 } 4322 } 4323 } 4324 catch (...) 4325 { 4326 is_ok = false; 4327 test_error = true; 4328 clean(); 4329 } 4330 4331 /* Result's setup. */ 4332 if (is_ok) 4333 { 4334 /* Log success. */ 4335 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have passed." 4336 << tcu::TestLog::EndMessage; 4337 4338 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4339 } 4340 else 4341 { 4342 if (test_error) 4343 { 4344 /* Log error. */ 4345 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have approached error." 4346 << tcu::TestLog::EndMessage; 4347 4348 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 4349 } 4350 else 4351 { 4352 /* Log fail. */ 4353 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have failed." 4354 << tcu::TestLog::EndMessage; 4355 4356 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4357 } 4358 } 4359 4360 return STOP; 4361 } 4362 4363 void gl3cts::TransformFeedback::DrawXFB::prepare(glw::GLenum capture_mode) 4364 { 4365 /* Functions handler */ 4366 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4367 4368 /* Prepare programs. */ 4369 m_program_id_xfb = gl3cts::TransformFeedback::Utilities::buildProgram( 4370 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_xfb, s_fragment_shader, 4371 s_xfb_varyings, s_xfb_varyings_count, capture_mode); 4372 4373 if (0 == m_program_id_xfb) 4374 { 4375 throw 0; 4376 } 4377 4378 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(), 4379 NULL, NULL, NULL, s_vertex_shader_draw, 4380 s_fragment_shader, NULL, 0, capture_mode); 4381 4382 if (0 == m_program_id_draw) 4383 { 4384 throw 0; 4385 } 4386 4387 /* Prepare transform feedbacks. */ 4388 gl.genTransformFeedbacks(s_xfb_count, m_xfb_id); 4389 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 4390 4391 /* Prepare buffer objects. */ 4392 gl.genBuffers(s_xfb_count, m_bo_id); 4393 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 4394 4395 for (glw::GLuint i = 0; i < s_xfb_count; ++i) 4396 { 4397 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]); 4398 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4399 4400 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_capture_size, NULL, GL_DYNAMIC_COPY); 4401 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 4402 } 4403 4404 /* Prepare framebuffer. */ 4405 gl.clearColor(0.f, 0.f, 0.f, 1.f); 4406 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 4407 4408 gl.genFramebuffers(1, &m_fbo_id); 4409 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed."); 4410 4411 gl.genRenderbuffers(1, &m_rbo_id); 4412 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed."); 4413 4414 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 4415 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); 4416 4417 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id); 4418 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed."); 4419 4420 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, s_view_size, s_view_size); 4421 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed."); 4422 4423 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id); 4424 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed."); 4425 4426 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 4427 { 4428 throw 0; 4429 } 4430 4431 gl.viewport(0, 0, s_view_size, s_view_size); 4432 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed."); 4433 4434 /* Create empty Vertex Array Object */ 4435 gl.genVertexArrays(1, &m_vao_id); 4436 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 4437 } 4438 4439 void gl3cts::TransformFeedback::DrawXFB::bindXFB(glw::GLuint xfb_id) 4440 { 4441 /* Functions handler */ 4442 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4443 4444 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb_id); 4445 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed."); 4446 } 4447 4448 void gl3cts::TransformFeedback::DrawXFB::bindVAO(glw::GLuint vao_id) 4449 { 4450 /* Functions handler */ 4451 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4452 4453 gl.bindVertexArray(vao_id); 4454 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 4455 } 4456 4457 void gl3cts::TransformFeedback::DrawXFB::bindBOForXFB(glw::GLenum capture_mode, glw::GLuint bo_id) 4458 { 4459 /* Functions handler */ 4460 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4461 4462 switch (capture_mode) 4463 { 4464 case GL_INTERLEAVED_ATTRIBS: 4465 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id); 4466 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 4467 break; 4468 case GL_SEPARATE_ATTRIBS: 4469 for (glw::GLuint i = 0; i < s_xfb_varyings_count; ++i) 4470 { 4471 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, bo_id, i * s_capture_size / s_xfb_varyings_count, 4472 (i + 1) * s_capture_size / s_xfb_varyings_count); 4473 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 4474 } 4475 break; 4476 default: 4477 throw 0; 4478 }; 4479 } 4480 4481 void gl3cts::TransformFeedback::DrawXFB::bindBOForDraw(glw::GLuint program_id, glw::GLenum capture_mode, 4482 glw::GLuint bo_id) 4483 { 4484 /* Functions handler */ 4485 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4486 4487 gl.bindBuffer(GL_ARRAY_BUFFER, bo_id); 4488 4489 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4490 4491 glw::GLuint position_location = gl.getAttribLocation(program_id, "position"); 4492 glw::GLuint color_location = gl.getAttribLocation(program_id, "color"); 4493 4494 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 4495 4496 glw::GLvoid* color_offset = (capture_mode == GL_INTERLEAVED_ATTRIBS) ? 4497 (glw::GLvoid*)(4 /* components */ * sizeof(glw::GLfloat)) : 4498 (glw::GLvoid*)(4 /* components */ * 6 /* vertices */ * sizeof(glw::GLfloat)); 4499 4500 glw::GLuint stride = 4501 static_cast<glw::GLuint>((capture_mode == GL_INTERLEAVED_ATTRIBS) ? 4502 (4 /* components */ * 2 /* position and color */ * sizeof(glw::GLfloat)) : 4503 (4 /* components */ * sizeof(glw::GLfloat))); 4504 4505 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, stride, NULL); 4506 gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, stride, color_offset); 4507 4508 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); 4509 4510 gl.enableVertexAttribArray(position_location); 4511 gl.enableVertexAttribArray(color_location); 4512 4513 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 4514 } 4515 4516 void gl3cts::TransformFeedback::DrawXFB::useProgram(glw::GLuint program_id) 4517 { 4518 /* Functions handler */ 4519 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4520 4521 gl.useProgram(program_id); 4522 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 4523 } 4524 4525 void gl3cts::TransformFeedback::DrawXFB::useColour(glw::GLuint program_id, glw::GLfloat r, glw::GLfloat g, 4526 glw::GLfloat b, glw::GLfloat a) 4527 { 4528 /* Functions handler */ 4529 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4530 4531 glw::GLint location = gl.getUniformLocation(program_id, "color"); 4532 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed."); 4533 4534 gl.uniform4f(location, r, g, b, a); 4535 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed."); 4536 } 4537 4538 void gl3cts::TransformFeedback::DrawXFB::useGeometrySet(glw::GLuint program_id, bool invert_sign) 4539 { 4540 /* Functions handler */ 4541 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4542 4543 glw::GLint location = gl.getUniformLocation(program_id, "invert_sign"); 4544 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed."); 4545 4546 gl.uniform1f(location, invert_sign ? -1.f : 1.f); 4547 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed."); 4548 } 4549 4550 void gl3cts::TransformFeedback::DrawXFB::clean() 4551 { 4552 /* Functions handler */ 4553 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4554 4555 gl.useProgram(0); 4556 4557 if (m_program_id_xfb) 4558 { 4559 gl.deleteProgram(m_program_id_xfb); 4560 4561 m_program_id_xfb = 0; 4562 } 4563 4564 if (m_program_id_draw) 4565 { 4566 gl.deleteProgram(m_program_id_draw); 4567 4568 m_program_id_draw = 1; 4569 } 4570 4571 for (glw::GLuint i = 0; i < s_xfb_count; ++i) 4572 { 4573 if (m_xfb_id[i]) 4574 { 4575 gl.deleteTransformFeedbacks(1, &m_xfb_id[i]); 4576 4577 m_xfb_id[i] = 0; 4578 } 4579 } 4580 4581 for (glw::GLuint i = 0; i < s_xfb_count; ++i) 4582 { 4583 if (m_bo_id[i]) 4584 { 4585 gl.deleteBuffers(1, &m_bo_id[i]); 4586 4587 m_bo_id[i] = 0; 4588 } 4589 } 4590 4591 if (m_vao_id) 4592 { 4593 gl.deleteVertexArrays(1, &m_vao_id); 4594 4595 m_vao_id = 0; 4596 } 4597 4598 if (m_fbo_id) 4599 { 4600 gl.deleteFramebuffers(1, &m_fbo_id); 4601 4602 m_fbo_id = 0; 4603 } 4604 4605 if (m_rbo_id) 4606 { 4607 gl.deleteRenderbuffers(1, &m_rbo_id); 4608 4609 m_rbo_id = 0; 4610 } 4611 } 4612 4613 void gl3cts::TransformFeedback::DrawXFB::drawForCapture(bool begin_xfb, bool pause_xfb, bool resume_xfb, bool end_xfb) 4614 { 4615 /* Functions handler */ 4616 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4617 4618 gl.enable(GL_RASTERIZER_DISCARD); 4619 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 4620 4621 if (begin_xfb) 4622 { 4623 gl.beginTransformFeedback(GL_POINTS); 4624 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 4625 } 4626 4627 if (resume_xfb) 4628 { 4629 gl.resumeTransformFeedback(); 4630 GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback call failed."); 4631 } 4632 4633 gl.drawArrays(GL_POINTS, 0, 3); 4634 4635 if (pause_xfb) 4636 { 4637 gl.pauseTransformFeedback(); 4638 GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed."); 4639 } 4640 4641 if (end_xfb) 4642 { 4643 gl.endTransformFeedback(); 4644 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 4645 } 4646 4647 gl.disable(GL_RASTERIZER_DISCARD); 4648 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 4649 } 4650 4651 void gl3cts::TransformFeedback::DrawXFB::drawToFramebuffer(glw::GLuint xfb_id) 4652 { 4653 /* Functions handler */ 4654 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4655 4656 gl.clearColor(0.f, 0.f, 0.f, 0.f); 4657 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 4658 4659 gl.clear(GL_COLOR_BUFFER_BIT); 4660 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 4661 4662 gl.drawTransformFeedback(GL_TRIANGLES, xfb_id); 4663 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed."); 4664 } 4665 4666 bool gl3cts::TransformFeedback::DrawXFB::checkFramebuffer(glw::GLfloat r, glw::GLfloat g, glw::GLfloat b, 4667 glw::GLfloat a) 4668 { 4669 /* Functions handler */ 4670 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4671 4672 /* Number of pixels. */ 4673 const glw::GLuint number_of_pixels = s_view_size * s_view_size; 4674 4675 /* Fetch framebuffer. */ 4676 std::vector<glw::GLubyte> pixels(number_of_pixels * 4 /* components */); 4677 4678 if ((s_view_size > 0) && (s_view_size > 0)) 4679 { 4680 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); 4681 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 4682 } 4683 4684 /* Convert color to integer. */ 4685 glw::GLubyte ir = (glw::GLubyte)(255.f * r); 4686 glw::GLubyte ig = (glw::GLubyte)(255.f * g); 4687 glw::GLubyte ib = (glw::GLubyte)(255.f * b); 4688 glw::GLubyte ia = (glw::GLubyte)(255.f * a); 4689 4690 /* Check results. */ 4691 for (glw::GLuint i = 0; i < number_of_pixels; ++i) 4692 { 4693 if ((pixels[i * 4 /* components */] != ir) || (pixels[i * 4 /* components */ + 1] != ig) || 4694 (pixels[i * 4 /* components */ + 2] != ib) || (pixels[i * 4 /* components */ + 3] != ia)) 4695 { 4696 return false; 4697 } 4698 } 4699 4700 return true; 4701 } 4702 4703 bool gl3cts::TransformFeedback::DrawXFB::inspectXFBState(bool shall_be_paused, bool shall_be_active) 4704 { 4705 /* Functions handler */ 4706 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4707 4708 glw::GLint is_paused = 0; 4709 glw::GLint is_active = 0; 4710 4711 gl.getIntegerv(GL_TRANSFORM_FEEDBACK_PAUSED, &is_paused); 4712 gl.getIntegerv(GL_TRANSFORM_FEEDBACK_ACTIVE, &is_active); 4713 4714 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 4715 4716 if ((is_paused == -1) || (is_active == -1)) 4717 { 4718 throw 0; 4719 } 4720 4721 if (shall_be_paused ^ (is_paused == GL_TRUE)) 4722 { 4723 return false; 4724 } 4725 4726 if (shall_be_active ^ (is_active == GL_TRUE)) 4727 { 4728 return false; 4729 } 4730 4731 return true; 4732 } 4733 4734 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_xfb = 4735 "#version 130\n" 4736 "\n" 4737 "uniform vec4 color;\n" 4738 "uniform float invert_sign;\n" 4739 "out vec4 colour;\n" 4740 "\n" 4741 "void main()\n" 4742 "{\n" 4743 " switch(gl_VertexID)\n" 4744 " {\n" 4745 " case 0:\n" 4746 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 4747 " break;\n" 4748 " case 1:\n" 4749 " gl_Position = vec4(-1.0 * invert_sign, 1.0, 0.0, 1.0);\n" 4750 " break;\n" 4751 " case 2:\n" 4752 " gl_Position = vec4( 1.0, 1.0 * invert_sign, 0.0, 1.0);\n" 4753 " break;\n" 4754 " }\n" 4755 "\n" 4756 " colour = color;\n" 4757 "}\n"; 4758 4759 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_draw = "#version 130\n" 4760 "\n" 4761 "in vec4 color;\n" 4762 "in vec4 position;\n" 4763 "out vec4 colour;\n" 4764 "\n" 4765 "void main()\n" 4766 "{\n" 4767 " gl_Position = position;\n" 4768 " colour = color;\n" 4769 "}\n"; 4770 4771 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_fragment_shader = "#version 130\n" 4772 "\n" 4773 "in vec4 colour;\n" 4774 "out vec4 pixel;\n" 4775 "\n" 4776 "void main()\n" 4777 "{\n" 4778 " pixel = colour;\n" 4779 "}\n"; 4780 4781 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_xfb_varyings[s_xfb_varyings_count] = { "gl_Position", 4782 "colour" }; 4783 4784 const glw::GLenum gl3cts::TransformFeedback::DrawXFB::s_capture_modes[] = { GL_INTERLEAVED_ATTRIBS, 4785 GL_SEPARATE_ATTRIBS }; 4786 const glw::GLuint gl3cts::TransformFeedback::DrawXFB::s_capture_modes_count = 4787 sizeof(s_capture_modes) / sizeof(s_capture_modes[0]); 4788 4789 const glw::GLfloat gl3cts::TransformFeedback::DrawXFB::s_colours[s_xfb_count][4] = { { 1.f, 0.f, 0.f, 1.f }, 4790 { 0.f, 1.f, 0.f, 1.f }, 4791 { 0.f, 0.f, 1.f, 1.f } }; 4792 4793 /*-----------------------------------------------------------------------------------------------*/ 4794 4795 gl3cts::TransformFeedback::DrawXFBFeedback::DrawXFBFeedback(deqp::Context& context, const char* test_name, 4796 const char* test_description) 4797 : deqp::TestCase(context, test_name, test_description) 4798 , m_context(context) 4799 , m_program_id(0) 4800 , m_xfb_id(0) 4801 , m_source_bo_index(0) 4802 { 4803 memset(m_bo_id, 1, sizeof(m_bo_id)); 4804 memset(m_bo_id, 1, sizeof(m_vao_id)); 4805 } 4806 4807 gl3cts::TransformFeedback::DrawXFBFeedback::~DrawXFBFeedback(void) 4808 { 4809 } 4810 4811 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBFeedback::iterate(void) 4812 { 4813 /* Initializations. */ 4814 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 4815 bool is_arb_tf_2 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2"); 4816 4817 bool is_ok = true; 4818 bool test_error = false; 4819 4820 /* Tests. */ 4821 try 4822 { 4823 if (is_at_least_gl_40 || is_arb_tf_2) 4824 { 4825 prepareAndBind(); 4826 draw(true); 4827 swapBuffers(); 4828 draw(false); 4829 swapBuffers(); 4830 draw(false); 4831 4832 is_ok = is_ok && check(); 4833 } 4834 } 4835 catch (...) 4836 { 4837 is_ok = false; 4838 test_error = true; 4839 } 4840 4841 /* Clean GL objects. */ 4842 clean(); 4843 4844 /* Result's setup. */ 4845 if (is_ok) 4846 { 4847 /* Log success. */ 4848 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have passed." 4849 << tcu::TestLog::EndMessage; 4850 4851 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4852 } 4853 else 4854 { 4855 if (test_error) 4856 { 4857 /* Log error. */ 4858 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have approached error." 4859 << tcu::TestLog::EndMessage; 4860 4861 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 4862 } 4863 else 4864 { 4865 /* Log fail. */ 4866 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have failed." 4867 << tcu::TestLog::EndMessage; 4868 4869 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4870 } 4871 } 4872 4873 return STOP; 4874 } 4875 4876 void gl3cts::TransformFeedback::DrawXFBFeedback::prepareAndBind() 4877 { 4878 /* Functions handler */ 4879 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4880 4881 /* Prepare programs. */ 4882 m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(), NULL, 4883 NULL, NULL, s_vertex_shader, s_fragment_shader, 4884 &s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS); 4885 4886 if (0 == m_program_id) 4887 { 4888 throw 0; 4889 } 4890 4891 gl.useProgram(m_program_id); 4892 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 4893 4894 /* Prepare transform feedbacks. */ 4895 gl.genTransformFeedbacks(1, &m_xfb_id); 4896 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 4897 4898 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id); 4899 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed."); 4900 4901 /* Prepare buffer objects. */ 4902 gl.genBuffers(s_bo_count, m_bo_id); 4903 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 4904 4905 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[0]); 4906 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4907 4908 gl.bufferData(GL_ARRAY_BUFFER, s_bo_size, s_initial_data, GL_DYNAMIC_COPY); 4909 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 4910 4911 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[1]); 4912 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4913 4914 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); 4915 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 4916 4917 /* Setup vertex arrays. */ 4918 gl.genVertexArrays(s_bo_count, m_vao_id); 4919 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 4920 4921 glw::GLuint position_location = gl.getAttribLocation(m_program_id, "position"); 4922 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 4923 4924 for (glw::GLuint i = 0; i < 2; ++i) 4925 { 4926 gl.bindVertexArray(m_vao_id[i]); 4927 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 4928 4929 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[i]); 4930 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4931 4932 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL); 4933 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); 4934 4935 gl.enableVertexAttribArray(position_location); 4936 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 4937 } 4938 4939 gl.bindBuffer(GL_ARRAY_BUFFER, 0); 4940 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4941 4942 gl.bindVertexArray(m_vao_id[0]); 4943 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 4944 } 4945 4946 void gl3cts::TransformFeedback::DrawXFBFeedback::swapBuffers() 4947 { 4948 /* Functions handler */ 4949 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4950 4951 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[m_source_bo_index]); 4952 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4953 4954 m_source_bo_index = (m_source_bo_index + 1) % 2; 4955 4956 gl.bindVertexArray(m_vao_id[(m_source_bo_index)]); 4957 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 4958 } 4959 4960 void gl3cts::TransformFeedback::DrawXFBFeedback::draw(bool is_first_draw) 4961 { 4962 /* Functions handler */ 4963 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4964 4965 gl.enable(GL_RASTERIZER_DISCARD); 4966 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 4967 4968 gl.beginTransformFeedback(GL_POINTS); 4969 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 4970 4971 if (is_first_draw) 4972 { 4973 gl.drawArrays(GL_POINTS, 0, 1); 4974 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 4975 } 4976 else 4977 { 4978 gl.drawTransformFeedback(GL_POINTS, m_xfb_id); 4979 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed."); 4980 } 4981 4982 gl.endTransformFeedback(); 4983 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 4984 4985 gl.disable(GL_RASTERIZER_DISCARD); 4986 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 4987 } 4988 4989 bool gl3cts::TransformFeedback::DrawXFBFeedback::check() 4990 { 4991 /* Functions handler */ 4992 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4993 4994 glw::GLfloat* results = 4995 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT); 4996 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed."); 4997 4998 bool is_ok = false; 4999 5000 if (results) 5001 { 5002 if ((results[0] == 8.f) && (results[1] == 16.f) && (results[2] == 24.f) && (results[3] == 32.f)) 5003 { 5004 is_ok = true; 5005 } 5006 5007 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 5008 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 5009 } 5010 5011 return is_ok; 5012 } 5013 5014 void gl3cts::TransformFeedback::DrawXFBFeedback::clean() 5015 { 5016 /* Functions handler */ 5017 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5018 5019 gl.useProgram(0); 5020 5021 if (m_program_id) 5022 { 5023 gl.deleteProgram(m_program_id); 5024 5025 m_program_id = 0; 5026 } 5027 5028 if (m_xfb_id) 5029 { 5030 gl.deleteTransformFeedbacks(1, &m_xfb_id); 5031 5032 m_xfb_id = 0; 5033 } 5034 5035 for (glw::GLuint i = 0; i < s_bo_count; ++i) 5036 { 5037 if (m_bo_id[i]) 5038 { 5039 gl.deleteBuffers(1, &m_bo_id[i]); 5040 5041 m_bo_id[i] = 0; 5042 } 5043 } 5044 5045 for (glw::GLuint i = 0; i < s_bo_count; ++i) 5046 { 5047 if (m_vao_id[i]) 5048 { 5049 gl.deleteVertexArrays(1, &m_vao_id[i]); 5050 5051 m_vao_id[i] = 0; 5052 } 5053 } 5054 } 5055 5056 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_vertex_shader = "#version 130\n" 5057 "\n" 5058 "in vec4 position;\n" 5059 "\n" 5060 "void main()\n" 5061 "{\n" 5062 " gl_Position = position * 2.0;\n" 5063 "}\n"; 5064 5065 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_fragment_shader = "#version 130\n" 5066 "\n" 5067 "out vec4 pixel;\n" 5068 "\n" 5069 "void main()\n" 5070 "{\n" 5071 " pixel = vec4(1.0);\n" 5072 "}\n"; 5073 5074 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_xfb_varying = "gl_Position"; 5075 5076 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_attrib = "position"; 5077 5078 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBFeedback::s_initial_data[] = { 1.f, 2.f, 3.f, 4.f }; 5079 5080 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_draw_vertex_count = 5081 sizeof(s_initial_data) / sizeof(s_initial_data[0]) / 4 /* components */; 5082 5083 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_bo_size = sizeof(s_initial_data); 5084 5085 /*-----------------------------------------------------------------------------------------------*/ 5086 5087 gl3cts::TransformFeedback::CaptureSpecialInterleaved::CaptureSpecialInterleaved(deqp::Context& context, 5088 const char* test_name, 5089 const char* test_description) 5090 : deqp::TestCase(context, test_name, test_description) 5091 , m_context(context) 5092 , m_program_id(0) 5093 , m_vao_id(0) 5094 , m_xfb_id(0) 5095 { 5096 memset(m_bo_id, 0, sizeof(m_bo_id)); 5097 } 5098 5099 gl3cts::TransformFeedback::CaptureSpecialInterleaved::~CaptureSpecialInterleaved(void) 5100 { 5101 } 5102 5103 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureSpecialInterleaved::iterate(void) 5104 { 5105 /* Initializations. */ 5106 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 5107 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3"); 5108 5109 bool is_ok = true; 5110 bool test_error = false; 5111 5112 /* Tests. */ 5113 try 5114 { 5115 if (is_at_least_gl_40 || is_arb_tf_3) 5116 { 5117 prepareAndBind(); 5118 draw(); 5119 5120 is_ok = is_ok && check(); 5121 } 5122 } 5123 catch (...) 5124 { 5125 is_ok = false; 5126 test_error = true; 5127 } 5128 5129 /* Clean GL objects. */ 5130 clean(); 5131 5132 /* Result's setup. */ 5133 if (is_ok) 5134 { 5135 /* Log success. */ 5136 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Special Interleaved have passed." 5137 << tcu::TestLog::EndMessage; 5138 5139 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5140 } 5141 else 5142 { 5143 if (test_error) 5144 { 5145 /* Log error. */ 5146 m_context.getTestContext().getLog() << tcu::TestLog::Message 5147 << "Capture Special Interleaved have approached error." 5148 << tcu::TestLog::EndMessage; 5149 5150 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 5151 } 5152 else 5153 { 5154 /* Log fail. */ 5155 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Special Interleaved have failed." 5156 << tcu::TestLog::EndMessage; 5157 5158 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5159 } 5160 } 5161 5162 return STOP; 5163 } 5164 5165 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::prepareAndBind() 5166 { 5167 /* Functions handler */ 5168 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5169 5170 /* Prepare programs. */ 5171 m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram( 5172 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader, s_fragment_shader, s_xfb_varyings, 5173 s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS); 5174 5175 if (0 == m_program_id) 5176 { 5177 throw 0; 5178 } 5179 5180 gl.useProgram(m_program_id); 5181 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 5182 5183 /* Prepare transform feedbacks. */ 5184 gl.genTransformFeedbacks(1, &m_xfb_id); 5185 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 5186 5187 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id); 5188 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed."); 5189 5190 /* Create empty Vertex Array Object */ 5191 gl.genVertexArrays(1, &m_vao_id); 5192 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 5193 5194 gl.bindVertexArray(m_vao_id); 5195 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 5196 5197 /* Prepare buffer objects. */ 5198 gl.genBuffers(s_bo_ids_count, m_bo_id); 5199 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 5200 5201 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i) 5202 { 5203 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]); 5204 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5205 5206 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */ 5207 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 5208 5209 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]); 5210 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 5211 } 5212 } 5213 5214 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::draw() 5215 { 5216 /* Functions handler */ 5217 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5218 5219 gl.enable(GL_RASTERIZER_DISCARD); 5220 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 5221 5222 gl.beginTransformFeedback(GL_POINTS); 5223 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 5224 5225 gl.drawArrays(GL_POINTS, 0, 1); 5226 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 5227 5228 gl.endTransformFeedback(); 5229 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 5230 5231 gl.disable(GL_RASTERIZER_DISCARD); 5232 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 5233 } 5234 5235 bool gl3cts::TransformFeedback::CaptureSpecialInterleaved::check() 5236 { 5237 /* Functions handler */ 5238 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5239 5240 bool is_ok = true; 5241 5242 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[0]); 5243 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5244 5245 glw::GLfloat* results = 5246 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT); 5247 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed."); 5248 5249 if ((results[0] != 1.0) || (results[1] != 2.0) || (results[2] != 3.0) || (results[3] != 4.0) || 5250 /* gl_SkipComponents4 here */ 5251 (results[8] != 5.0) || (results[9] != 6.0) || (results[10] != 7.0) || (results[11] != 8.0)) 5252 { 5253 is_ok = false; 5254 } 5255 5256 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 5257 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 5258 5259 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[1]); 5260 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5261 5262 results = (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT); 5263 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed."); 5264 5265 if ((results[0] != 9.0) || (results[1] != 10.0) || (results[2] != 11.0) || (results[3] != 12.0) || 5266 /* gl_SkipComponents4 here */ 5267 (results[8] != 13.0) || (results[9] != 14.0) || (results[10] != 15.0) || (results[11] != 16.0)) 5268 { 5269 is_ok = false; 5270 } 5271 5272 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 5273 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 5274 5275 return is_ok; 5276 } 5277 5278 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::clean() 5279 { 5280 /* Functions handler */ 5281 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5282 5283 gl.useProgram(0); 5284 5285 if (m_program_id) 5286 { 5287 gl.deleteProgram(m_program_id); 5288 5289 m_program_id = 0; 5290 } 5291 5292 if (m_xfb_id) 5293 { 5294 gl.deleteTransformFeedbacks(1, &m_xfb_id); 5295 5296 m_xfb_id = 0; 5297 } 5298 5299 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i) 5300 { 5301 if (m_bo_id[i]) 5302 { 5303 gl.deleteBuffers(1, &m_bo_id[i]); 5304 5305 m_bo_id[i] = 0; 5306 } 5307 } 5308 5309 if (m_vao_id) 5310 { 5311 gl.deleteVertexArrays(1, &m_vao_id); 5312 5313 m_vao_id = 0; 5314 } 5315 } 5316 5317 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_vertex_shader = 5318 "#version 130\n" 5319 "\n" 5320 "out vec4 variable_1;\n" 5321 "out vec4 variable_2;\n" 5322 "out vec4 variable_3;\n" 5323 "out vec4 variable_4;\n" 5324 "\n" 5325 "void main()\n" 5326 "{\n" 5327 " variable_1 = vec4(1.0, 2.0, 3.0, 4.0);\n" 5328 " variable_2 = vec4(5.0, 6.0, 7.0, 8.0);\n" 5329 " variable_3 = vec4(9.0, 10.0, 11.0, 12.0);\n" 5330 " variable_4 = vec4(13.0, 14.0, 15.0, 16.0);\n" 5331 "\n" 5332 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" 5333 "}\n"; 5334 5335 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_fragment_shader = "#version 130\n" 5336 "\n" 5337 "out vec4 pixel;\n" 5338 "\n" 5339 "void main()\n" 5340 "{\n" 5341 " pixel = vec4(1.0);\n" 5342 "}\n"; 5343 5344 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings[] = 5345 { "variable_1", "gl_SkipComponents4", "variable_2", "gl_NextBuffer", 5346 "variable_3", "gl_SkipComponents4", "variable_4" }; 5347 5348 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings_count = 5349 sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]); 5350 5351 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_bo_size = 5352 3 /*number of variables / empty places */ * 4 /* vec4 */ 5353 * sizeof(glw::GLfloat); 5354 5355 /*-----------------------------------------------------------------------------------------------*/ 5356 5357 gl3cts::TransformFeedback::DrawXFBStream::DrawXFBStream(deqp::Context& context, const char* test_name, 5358 const char* test_description) 5359 : deqp::TestCase(context, test_name, test_description) 5360 , m_context(context) 5361 , m_program_id_generate(0) 5362 , m_program_id_draw(0) 5363 , m_vao_id(0) 5364 , m_xfb_id(0) 5365 , m_fbo_id(0) 5366 , m_rbo_id(0) 5367 { 5368 memset(m_bo_id, 0, sizeof(m_bo_id)); 5369 memset(m_qo_id, 0, sizeof(m_qo_id)); 5370 } 5371 5372 gl3cts::TransformFeedback::DrawXFBStream::~DrawXFBStream(void) 5373 { 5374 } 5375 5376 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStream::iterate(void) 5377 { 5378 /* Functions handler */ 5379 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5380 5381 /* Initializations. */ 5382 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 5383 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3"); 5384 bool is_arb_gpu_shader5 = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"); 5385 5386 glw::GLint max_vertex_streams = 0; 5387 5388 bool is_ok = true; 5389 bool test_error = false; 5390 5391 /* Tests. */ 5392 try 5393 { 5394 if (is_at_least_gl_40 || (is_arb_tf_3 && is_arb_gpu_shader5)) 5395 { 5396 gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams); 5397 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 5398 5399 if (max_vertex_streams >= 2) 5400 { 5401 prepareObjects(); 5402 5403 useProgram(m_program_id_generate); 5404 5405 drawForXFB(); 5406 5407 is_ok = is_ok && inspectQueries(); 5408 5409 useProgram(m_program_id_draw); 5410 5411 setupVertexArray(m_bo_id[0]); 5412 5413 drawForFramebuffer(0); 5414 5415 setupVertexArray(m_bo_id[1]); 5416 5417 drawForFramebuffer(1); 5418 5419 is_ok = is_ok && check(); 5420 } 5421 } 5422 } 5423 catch (...) 5424 { 5425 is_ok = false; 5426 test_error = true; 5427 } 5428 5429 /* Clean GL objects. */ 5430 clean(); 5431 5432 /* Result's setup. */ 5433 if (is_ok) 5434 { 5435 /* Log success. */ 5436 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have passed." 5437 << tcu::TestLog::EndMessage; 5438 5439 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5440 } 5441 else 5442 { 5443 if (test_error) 5444 { 5445 /* Log error. */ 5446 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have approached error." 5447 << tcu::TestLog::EndMessage; 5448 5449 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 5450 } 5451 else 5452 { 5453 /* Log fail. */ 5454 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have failed." 5455 << tcu::TestLog::EndMessage; 5456 5457 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5458 } 5459 } 5460 5461 return STOP; 5462 } 5463 5464 void gl3cts::TransformFeedback::DrawXFBStream::prepareObjects() 5465 { 5466 /* Functions handler */ 5467 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5468 5469 /* Prepare programs. */ 5470 m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram( 5471 gl, m_context.getTestContext().getLog(), s_geometry_shader, NULL, NULL, s_vertex_shader_blank, 5472 s_fragment_shader, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS); 5473 5474 if (0 == m_program_id_generate) 5475 { 5476 throw 0; 5477 } 5478 5479 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram( 5480 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_pass, s_fragment_shader, NULL, 0, 5481 GL_INTERLEAVED_ATTRIBS); 5482 5483 if (0 == m_program_id_draw) 5484 { 5485 throw 0; 5486 } 5487 5488 /* Prepare transform feedbacks. */ 5489 gl.genTransformFeedbacks(1, &m_xfb_id); 5490 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 5491 5492 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id); 5493 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed."); 5494 5495 /* Create empty Vertex Array Object */ 5496 gl.genVertexArrays(1, &m_vao_id); 5497 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 5498 5499 gl.bindVertexArray(m_vao_id); 5500 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 5501 5502 /* Prepare buffer objects. */ 5503 gl.genBuffers(s_bo_ids_count, m_bo_id); 5504 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 5505 5506 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i) 5507 { 5508 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]); 5509 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5510 5511 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */ 5512 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 5513 5514 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]); 5515 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 5516 } 5517 5518 /* Generate queries */ 5519 gl.genQueries(s_qo_ids_count, m_qo_id); 5520 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed."); 5521 5522 /* Prepare framebuffer. */ 5523 gl.clearColor(0.f, 0.f, 0.f, 1.f); 5524 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 5525 5526 gl.genFramebuffers(1, &m_fbo_id); 5527 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed."); 5528 5529 gl.genRenderbuffers(1, &m_rbo_id); 5530 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed."); 5531 5532 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 5533 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); 5534 5535 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id); 5536 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed."); 5537 5538 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size); 5539 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed."); 5540 5541 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id); 5542 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed."); 5543 5544 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 5545 { 5546 throw 0; 5547 } 5548 5549 gl.viewport(0, 0, s_view_size, s_view_size); 5550 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed."); 5551 } 5552 5553 void gl3cts::TransformFeedback::DrawXFBStream::setupVertexArray(glw::GLuint bo_id) 5554 { 5555 /* Functions handler */ 5556 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5557 5558 gl.bindBuffer(GL_ARRAY_BUFFER, bo_id); 5559 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5560 5561 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position"); 5562 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 5563 5564 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL); 5565 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); 5566 5567 gl.enableVertexAttribArray(position_location); 5568 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 5569 } 5570 5571 void gl3cts::TransformFeedback::DrawXFBStream::useProgram(glw::GLuint program_id) 5572 { 5573 /* Functions handler */ 5574 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5575 5576 gl.useProgram(program_id); 5577 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 5578 } 5579 5580 void gl3cts::TransformFeedback::DrawXFBStream::drawForXFB() 5581 { 5582 /* Functions handler */ 5583 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5584 5585 gl.enable(GL_RASTERIZER_DISCARD); 5586 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 5587 5588 gl.beginTransformFeedback(GL_POINTS); 5589 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 5590 5591 gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 0, m_qo_id[0]); 5592 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed."); 5593 5594 gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 1, m_qo_id[1]); 5595 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed."); 5596 5597 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0, m_qo_id[2]); 5598 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed."); 5599 5600 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1, m_qo_id[3]); 5601 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed."); 5602 5603 gl.drawArrays(GL_POINTS, 0, 1); 5604 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 5605 5606 gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 0); 5607 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed."); 5608 5609 gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 1); 5610 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed."); 5611 5612 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0); 5613 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed."); 5614 5615 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1); 5616 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed."); 5617 5618 gl.endTransformFeedback(); 5619 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 5620 5621 gl.disable(GL_RASTERIZER_DISCARD); 5622 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 5623 } 5624 5625 void gl3cts::TransformFeedback::DrawXFBStream::drawForFramebuffer(glw::GLuint stream) 5626 { 5627 /* Functions handler */ 5628 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5629 5630 gl.drawTransformFeedbackStream(GL_TRIANGLES, m_xfb_id, stream); 5631 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedbackStream call failed."); 5632 } 5633 5634 bool gl3cts::TransformFeedback::DrawXFBStream::inspectQueries() 5635 { 5636 /* Functions handler */ 5637 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5638 5639 glw::GLint generated_primitives_to_stream_0 = 0; 5640 glw::GLint generated_primitives_to_stream_1 = 0; 5641 5642 gl.getQueryObjectiv(m_qo_id[0], GL_QUERY_RESULT, &generated_primitives_to_stream_0); 5643 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed."); 5644 5645 gl.getQueryObjectiv(m_qo_id[1], GL_QUERY_RESULT, &generated_primitives_to_stream_1); 5646 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed."); 5647 5648 glw::GLint primitives_written_to_xfb_to_stream_0 = 0; 5649 glw::GLint primitives_written_to_xfb_to_stream_1 = 0; 5650 5651 gl.getQueryObjectiv(m_qo_id[2], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_0); 5652 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed."); 5653 5654 gl.getQueryObjectiv(m_qo_id[3], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_1); 5655 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed."); 5656 5657 if ((generated_primitives_to_stream_0 == 3) && (generated_primitives_to_stream_1 == 3) && 5658 (primitives_written_to_xfb_to_stream_0 == 3) && (primitives_written_to_xfb_to_stream_1 == 3)) 5659 { 5660 return true; 5661 } 5662 5663 return false; 5664 } 5665 5666 bool gl3cts::TransformFeedback::DrawXFBStream::check() 5667 { 5668 /* Functions handler */ 5669 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5670 5671 /* Number of pixels. */ 5672 const glw::GLuint number_of_pixels = s_view_size * s_view_size; 5673 5674 /* Fetch framebuffer. */ 5675 std::vector<glw::GLfloat> pixels(number_of_pixels); 5676 5677 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]); 5678 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 5679 5680 /* Check results. */ 5681 for (glw::GLuint i = 0; i < number_of_pixels; ++i) 5682 { 5683 if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */) 5684 { 5685 return false; 5686 } 5687 } 5688 5689 return true; 5690 } 5691 5692 void gl3cts::TransformFeedback::DrawXFBStream::clean() 5693 { 5694 /* Functions handler */ 5695 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5696 5697 gl.useProgram(0); 5698 5699 if (m_program_id_generate) 5700 { 5701 gl.deleteProgram(m_program_id_generate); 5702 5703 m_program_id_generate = 0; 5704 } 5705 5706 if (m_program_id_draw) 5707 { 5708 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position"); 5709 5710 gl.disableVertexAttribArray(position_location); 5711 5712 gl.deleteProgram(m_program_id_draw); 5713 5714 m_program_id_draw = 0; 5715 } 5716 5717 if (m_xfb_id) 5718 { 5719 gl.deleteTransformFeedbacks(1, &m_xfb_id); 5720 5721 m_xfb_id = 0; 5722 } 5723 5724 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i) 5725 { 5726 if (m_bo_id[i]) 5727 { 5728 gl.deleteBuffers(1, &m_bo_id[i]); 5729 5730 m_bo_id[i] = 0; 5731 } 5732 } 5733 5734 if (m_vao_id) 5735 { 5736 gl.deleteVertexArrays(1, &m_vao_id); 5737 5738 m_vao_id = 0; 5739 } 5740 5741 if (m_fbo_id) 5742 { 5743 gl.deleteFramebuffers(1, &m_fbo_id); 5744 5745 m_fbo_id = 0; 5746 } 5747 5748 if (m_rbo_id) 5749 { 5750 gl.deleteRenderbuffers(1, &m_rbo_id); 5751 5752 m_rbo_id = 0; 5753 } 5754 } 5755 5756 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_blank = "#version 130\n" 5757 "\n" 5758 "void main()\n" 5759 "{\n" 5760 "}\n"; 5761 5762 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_pass = "#version 130\n" 5763 "\n" 5764 "in vec4 position;\n" 5765 "\n" 5766 "void main()\n" 5767 "{\n" 5768 " gl_Position = position;\n" 5769 "}\n"; 5770 5771 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_geometry_shader = 5772 "#version 400\n" 5773 "\n" 5774 "layout(points) in;\n" 5775 "layout(points, max_vertices = 6) out;\n" 5776 "\n" 5777 "layout(stream = 1) out vec4 position;\n" 5778 "\n" 5779 "void main()\n" 5780 "{\n" 5781 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 5782 " EmitStreamVertex(0);\n" 5783 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n" 5784 " EmitStreamVertex(0);\n" 5785 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 5786 " EmitStreamVertex(0);\n" 5787 "\n" 5788 " position = vec4( 1.0, -1.0, 0.0, 1.0);\n" 5789 " EmitStreamVertex(1);\n" 5790 " position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 5791 " EmitStreamVertex(1);\n" 5792 " position = vec4( 1.0, 1.0, 0.0, 1.0);\n" 5793 " EmitStreamVertex(1);\n" 5794 "}\n"; 5795 5796 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_fragment_shader = "#version 130\n" 5797 "\n" 5798 "out vec4 pixel;\n" 5799 "\n" 5800 "void main()\n" 5801 "{\n" 5802 " pixel = vec4(1.0);\n" 5803 "}\n"; 5804 5805 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings[] = { "gl_Position", "gl_NextBuffer", 5806 "position" }; 5807 5808 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings_count = 5809 sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]); 5810 5811 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_bo_size = 5812 3 /* triangles */ * 4 /* vec4 */ * sizeof(glw::GLfloat); 5813 5814 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_view_size = 2; 5815 5816 /*-----------------------------------------------------------------------------------------------*/ 5817 5818 gl3cts::TransformFeedback::DrawXFBInstanced::DrawXFBInstanced(deqp::Context& context, const char* test_name, 5819 const char* test_description) 5820 : deqp::TestCase(context, test_name, test_description) 5821 , m_context(context) 5822 , m_program_id_generate(0) 5823 , m_program_id_draw(0) 5824 , m_vao_id(0) 5825 , m_xfb_id(0) 5826 , m_bo_id_xfb(0) 5827 , m_bo_id_uniform(0) 5828 , m_fbo_id(0) 5829 , m_rbo_id(0) 5830 { 5831 } 5832 5833 gl3cts::TransformFeedback::DrawXFBInstanced::~DrawXFBInstanced(void) 5834 { 5835 } 5836 5837 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBInstanced::iterate(void) 5838 { 5839 /* Initializations. */ 5840 bool is_at_least_gl_42 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2))); 5841 bool is_at_least_gl_31 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1))); 5842 bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced"); 5843 bool is_arb_ubo = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object"); 5844 5845 bool is_ok = true; 5846 bool test_error = false; 5847 5848 try 5849 { 5850 if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_tf_instanced)) 5851 { 5852 prepareObjects(); 5853 drawForXFB(); 5854 drawInstanced(); 5855 5856 is_ok = is_ok && check(); 5857 } 5858 } 5859 catch (...) 5860 { 5861 is_ok = false; 5862 test_error = true; 5863 } 5864 5865 /* Clean GL objects */ 5866 clean(); 5867 5868 /* Result's setup. */ 5869 if (is_ok) 5870 { 5871 /* Log success. */ 5872 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have passed." 5873 << tcu::TestLog::EndMessage; 5874 5875 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5876 } 5877 else 5878 { 5879 if (test_error) 5880 { 5881 /* Log error. */ 5882 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have approached error." 5883 << tcu::TestLog::EndMessage; 5884 5885 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 5886 } 5887 else 5888 { 5889 /* Log fail. */ 5890 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have failed." 5891 << tcu::TestLog::EndMessage; 5892 5893 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5894 } 5895 } 5896 5897 return STOP; 5898 } 5899 5900 void gl3cts::TransformFeedback::DrawXFBInstanced::prepareObjects() 5901 { 5902 /* Functions handler */ 5903 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5904 5905 /* Prepare programs. */ 5906 m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram( 5907 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_generate, s_fragment_shader, 5908 &s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS); 5909 5910 if (0 == m_program_id_generate) 5911 { 5912 throw 0; 5913 } 5914 5915 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram( 5916 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader, NULL, 0, 5917 GL_INTERLEAVED_ATTRIBS); 5918 5919 if (0 == m_program_id_draw) 5920 { 5921 throw 0; 5922 } 5923 5924 /* Prepare transform feedbacks. */ 5925 gl.genTransformFeedbacks(1, &m_xfb_id); 5926 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 5927 5928 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id); 5929 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed."); 5930 5931 /* Create empty Vertex Array Object */ 5932 gl.genVertexArrays(1, &m_vao_id); 5933 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 5934 5935 gl.bindVertexArray(m_vao_id); 5936 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 5937 5938 /* Prepare xfb buffer object. */ 5939 gl.genBuffers(1, &m_bo_id_xfb); 5940 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 5941 5942 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb); 5943 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5944 5945 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */ 5946 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 5947 5948 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb); 5949 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 5950 5951 /* Prepare uniform buffer object. */ 5952 gl.genBuffers(1, &m_bo_id_uniform); 5953 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 5954 5955 gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform); 5956 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5957 5958 gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */ 5959 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 5960 5961 gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform); 5962 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 5963 5964 glw::GLuint uniform_index = gl.getUniformBlockIndex(m_program_id_draw, s_uniform); 5965 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed."); 5966 5967 if (GL_INVALID_INDEX == uniform_index) 5968 { 5969 throw 0; 5970 } 5971 5972 gl.uniformBlockBinding(m_program_id_draw, uniform_index, 0); 5973 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed."); 5974 5975 /* Prepare framebuffer. */ 5976 gl.clearColor(0.f, 0.f, 0.f, 1.f); 5977 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 5978 5979 gl.genFramebuffers(1, &m_fbo_id); 5980 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed."); 5981 5982 gl.genRenderbuffers(1, &m_rbo_id); 5983 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed."); 5984 5985 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 5986 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); 5987 5988 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id); 5989 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed."); 5990 5991 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size); 5992 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed."); 5993 5994 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id); 5995 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed."); 5996 5997 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 5998 { 5999 throw 0; 6000 } 6001 6002 gl.viewport(0, 0, s_view_size, s_view_size); 6003 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed."); 6004 } 6005 6006 void gl3cts::TransformFeedback::DrawXFBInstanced::drawForXFB() 6007 { 6008 /* Functions handler */ 6009 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6010 6011 gl.useProgram(m_program_id_generate); 6012 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 6013 6014 gl.enable(GL_RASTERIZER_DISCARD); 6015 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 6016 6017 gl.beginTransformFeedback(GL_POINTS); 6018 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 6019 6020 gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */); 6021 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 6022 6023 gl.endTransformFeedback(); 6024 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 6025 6026 gl.disable(GL_RASTERIZER_DISCARD); 6027 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 6028 } 6029 6030 void gl3cts::TransformFeedback::DrawXFBInstanced::drawInstanced() 6031 { 6032 /* Functions handler */ 6033 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6034 6035 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb); 6036 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 6037 6038 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position"); 6039 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 6040 6041 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL); 6042 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); 6043 6044 gl.enableVertexAttribArray(position_location); 6045 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 6046 6047 gl.clear(GL_COLOR_BUFFER_BIT); 6048 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 6049 6050 gl.useProgram(m_program_id_draw); 6051 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 6052 6053 gl.drawTransformFeedbackInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 4); 6054 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 6055 } 6056 6057 bool gl3cts::TransformFeedback::DrawXFBInstanced::check() 6058 { 6059 /* Functions handler */ 6060 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6061 6062 /* Number of pixels. */ 6063 const glw::GLuint number_of_pixels = s_view_size * s_view_size; 6064 6065 /* Fetch framebuffer. */ 6066 std::vector<glw::GLfloat> pixels(number_of_pixels); 6067 6068 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]); 6069 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 6070 6071 /* Check results. */ 6072 for (glw::GLuint i = 0; i < number_of_pixels; ++i) 6073 { 6074 if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */) 6075 { 6076 return false; 6077 } 6078 } 6079 6080 return true; 6081 } 6082 6083 void gl3cts::TransformFeedback::DrawXFBInstanced::clean() 6084 { 6085 /* Functions handler */ 6086 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6087 6088 gl.useProgram(0); 6089 6090 if (m_program_id_generate) 6091 { 6092 gl.deleteProgram(m_program_id_generate); 6093 6094 m_program_id_generate = 0; 6095 } 6096 6097 if (m_program_id_draw) 6098 { 6099 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position"); 6100 6101 gl.disableVertexAttribArray(position_location); 6102 6103 gl.deleteProgram(m_program_id_draw); 6104 6105 m_program_id_draw = 0; 6106 } 6107 6108 if (m_xfb_id) 6109 { 6110 gl.deleteTransformFeedbacks(1, &m_xfb_id); 6111 6112 m_xfb_id = 0; 6113 } 6114 6115 if (m_bo_id_xfb) 6116 { 6117 gl.deleteBuffers(1, &m_bo_id_xfb); 6118 6119 m_bo_id_xfb = 0; 6120 } 6121 6122 if (m_bo_id_uniform) 6123 { 6124 gl.deleteBuffers(1, &m_bo_id_uniform); 6125 6126 m_bo_id_uniform = 0; 6127 } 6128 6129 if (m_vao_id) 6130 { 6131 gl.deleteVertexArrays(1, &m_vao_id); 6132 6133 m_vao_id = 0; 6134 } 6135 6136 if (m_fbo_id) 6137 { 6138 gl.deleteFramebuffers(1, &m_fbo_id); 6139 6140 m_fbo_id = 0; 6141 } 6142 6143 if (m_rbo_id) 6144 { 6145 gl.deleteRenderbuffers(1, &m_rbo_id); 6146 6147 m_rbo_id = 0; 6148 } 6149 } 6150 6151 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_generate = 6152 "#version 140\n" 6153 "\n" 6154 "void main()\n" 6155 "{\n" 6156 " switch(gl_VertexID % 4)\n" 6157 " {\n" 6158 " case 0:\n" 6159 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 6160 " break;\n" 6161 " case 1:\n" 6162 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n" 6163 " break;\n" 6164 " case 2:\n" 6165 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 6166 " break;\n" 6167 " case 3:\n" 6168 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n" 6169 " break;\n" 6170 " }\n" 6171 "}\n"; 6172 6173 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_draw = 6174 "#version 140\n" 6175 "\n" 6176 "uniform MatrixBlock\n" 6177 "{\n" 6178 " mat4 transformation_0;\n" 6179 " mat4 transformation_1;\n" 6180 " mat4 transformation_2;\n" 6181 " mat4 transformation_3;\n" 6182 "};\n" 6183 "\n" 6184 "in vec4 position;\n" 6185 "\n" 6186 "void main()\n" 6187 "{\n" 6188 " switch(gl_InstanceID % 4)\n" 6189 " {\n" 6190 " case 0:\n" 6191 " gl_Position = position * transformation_0;\n" 6192 " break;\n" 6193 " case 1:\n" 6194 " gl_Position = position * transformation_1;\n" 6195 " break;\n" 6196 " case 2:\n" 6197 " gl_Position = position * transformation_2;\n" 6198 " break;\n" 6199 " case 3:\n" 6200 " gl_Position = position * transformation_3;\n" 6201 " break;\n" 6202 " }\n" 6203 "}\n"; 6204 6205 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_fragment_shader = "#version 130\n" 6206 "\n" 6207 "out vec4 pixel;\n" 6208 "\n" 6209 "void main()\n" 6210 "{\n" 6211 " pixel = vec4(1.0);\n" 6212 "}\n"; 6213 6214 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_xfb_varying = "gl_Position"; 6215 6216 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_uniform = "MatrixBlock"; 6217 6218 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_xfb_size = 6219 4 /* vertex count */ * 4 /* vec4 components */ 6220 * sizeof(glw::GLfloat) /* data type size */; 6221 6222 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_data[] = { 6223 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 6224 6225 0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 6226 6227 0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 6228 6229 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f 6230 }; 6231 6232 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data); 6233 6234 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_view_size = 4; 6235 6236 /*-----------------------------------------------------------------------------------------------*/ 6237 6238 gl3cts::TransformFeedback::DrawXFBStreamInstanced::DrawXFBStreamInstanced(deqp::Context& context, const char* test_name, 6239 const char* test_description) 6240 : deqp::TestCase(context, test_name, test_description) 6241 , m_context(context) 6242 , m_program_id_generate(0) 6243 , m_program_id_draw(0) 6244 , m_vao_id(0) 6245 , m_xfb_id(0) 6246 , m_bo_id_xfb_position(0) 6247 , m_bo_id_xfb_color(0) 6248 , m_bo_id_uniform(0) 6249 , m_fbo_id(0) 6250 , m_rbo_id(0) 6251 { 6252 } 6253 6254 gl3cts::TransformFeedback::DrawXFBStreamInstanced::~DrawXFBStreamInstanced(void) 6255 { 6256 } 6257 6258 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStreamInstanced::iterate(void) 6259 { 6260 /* Initializations. */ 6261 bool is_at_least_gl_31 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1))); 6262 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 6263 bool is_at_least_gl_42 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2))); 6264 bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced"); 6265 bool is_arb_ubo = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object"); 6266 bool is_arb_gpu_shader5 = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"); 6267 6268 bool is_ok = true; 6269 bool test_error = false; 6270 6271 /* Test. */ 6272 try 6273 { 6274 if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_gpu_shader5 && is_arb_tf_instanced) || 6275 (is_at_least_gl_40 && is_arb_tf_instanced)) 6276 { 6277 prepareObjects(); 6278 drawForXFB(); 6279 drawStreamInstanced(); 6280 6281 is_ok = is_ok && check(); 6282 } 6283 } 6284 catch (...) 6285 { 6286 is_ok = false; 6287 test_error = true; 6288 } 6289 6290 /* Clean GL objects */ 6291 clean(); 6292 6293 /* Result's setup. */ 6294 if (is_ok) 6295 { 6296 /* Log success. */ 6297 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream Instanced have passed." 6298 << tcu::TestLog::EndMessage; 6299 6300 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 6301 } 6302 else 6303 { 6304 if (test_error) 6305 { 6306 /* Log error. */ 6307 m_context.getTestContext().getLog() << tcu::TestLog::Message 6308 << "Draw XFB Stream Instanced have approached error." 6309 << tcu::TestLog::EndMessage; 6310 6311 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 6312 } 6313 else 6314 { 6315 /* Log fail. */ 6316 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream Instanced have failed." 6317 << tcu::TestLog::EndMessage; 6318 6319 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 6320 } 6321 } 6322 6323 return STOP; 6324 } 6325 6326 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::prepareObjects() 6327 { 6328 /* Functions handler */ 6329 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6330 6331 /* Prepare programs. */ 6332 m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram( 6333 gl, m_context.getTestContext().getLog(), s_geometry_shader_generate, NULL, NULL, s_vertex_shader_blank, 6334 s_fragment_shader_blank, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS); 6335 6336 if (0 == m_program_id_generate) 6337 { 6338 throw 0; 6339 } 6340 6341 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram( 6342 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader_draw, NULL, 6343 0, GL_INTERLEAVED_ATTRIBS); 6344 6345 if (0 == m_program_id_draw) 6346 { 6347 throw 0; 6348 } 6349 6350 /* Prepare transform feedbacks. */ 6351 gl.genTransformFeedbacks(1, &m_xfb_id); 6352 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 6353 6354 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id); 6355 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed."); 6356 6357 /* Create empty Vertex Array Object */ 6358 gl.genVertexArrays(1, &m_vao_id); 6359 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 6360 6361 gl.bindVertexArray(m_vao_id); 6362 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 6363 6364 /* Prepare xfb buffer objects. */ 6365 gl.genBuffers(1, &m_bo_id_xfb_position); 6366 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 6367 6368 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_position); 6369 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 6370 6371 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */ 6372 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 6373 6374 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb_position); 6375 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 6376 6377 gl.genBuffers(1, &m_bo_id_xfb_color); 6378 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 6379 6380 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_color); 6381 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 6382 6383 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */ 6384 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 6385 6386 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, m_bo_id_xfb_color); 6387 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 6388 6389 /* Prepare uniform buffer object. */ 6390 gl.genBuffers(1, &m_bo_id_uniform); 6391 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 6392 6393 gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform); 6394 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 6395 6396 gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */ 6397 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 6398 6399 gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform); 6400 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 6401 6402 glw::GLuint uniform_index = gl.getUniformBlockIndex(m_program_id_draw, s_uniform); 6403 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed."); 6404 6405 if (GL_INVALID_INDEX == uniform_index) 6406 { 6407 throw 0; 6408 } 6409 6410 gl.uniformBlockBinding(m_program_id_draw, uniform_index, 0); 6411 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed."); 6412 6413 /* Prepare framebuffer. */ 6414 gl.clearColor(0.f, 0.f, 0.f, 1.f); 6415 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 6416 6417 gl.genFramebuffers(1, &m_fbo_id); 6418 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed."); 6419 6420 gl.genRenderbuffers(1, &m_rbo_id); 6421 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed."); 6422 6423 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 6424 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); 6425 6426 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id); 6427 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed."); 6428 6429 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size); 6430 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed."); 6431 6432 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id); 6433 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed."); 6434 6435 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 6436 { 6437 throw 0; 6438 } 6439 6440 gl.viewport(0, 0, s_view_size, s_view_size); 6441 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed."); 6442 } 6443 6444 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawForXFB() 6445 { 6446 /* Functions handler */ 6447 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6448 6449 gl.useProgram(m_program_id_generate); 6450 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 6451 6452 gl.enable(GL_RASTERIZER_DISCARD); 6453 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 6454 6455 gl.beginTransformFeedback(GL_POINTS); 6456 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 6457 6458 gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */); 6459 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 6460 6461 gl.endTransformFeedback(); 6462 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 6463 6464 gl.disable(GL_RASTERIZER_DISCARD); 6465 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 6466 } 6467 6468 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawStreamInstanced() 6469 { 6470 /* Functions handler */ 6471 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6472 6473 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_position); 6474 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 6475 6476 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position"); 6477 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 6478 6479 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL); 6480 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); 6481 6482 gl.enableVertexAttribArray(position_location); 6483 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 6484 6485 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_color); 6486 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 6487 6488 glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color"); 6489 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 6490 6491 gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, 0, NULL); 6492 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); 6493 6494 gl.enableVertexAttribArray(color_location); 6495 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 6496 6497 gl.useProgram(m_program_id_draw); 6498 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 6499 6500 gl.drawTransformFeedbackStreamInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 0, 4); 6501 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 6502 } 6503 6504 bool gl3cts::TransformFeedback::DrawXFBStreamInstanced::check() 6505 { 6506 /* Functions handler */ 6507 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6508 6509 /* Number of pixels. */ 6510 const glw::GLuint number_of_pixels = s_view_size * s_view_size; 6511 6512 /* Fetch framebuffer. */ 6513 std::vector<glw::GLfloat> pixels(number_of_pixels); 6514 6515 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]); 6516 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 6517 6518 /* Check results. */ 6519 for (glw::GLuint i = 0; i < number_of_pixels; ++i) 6520 { 6521 if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */) 6522 { 6523 return false; 6524 } 6525 } 6526 6527 return true; 6528 } 6529 6530 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::clean() 6531 { 6532 /* Functions handler */ 6533 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6534 6535 gl.useProgram(0); 6536 6537 if (m_program_id_generate) 6538 { 6539 gl.deleteProgram(m_program_id_generate); 6540 6541 m_program_id_generate = 0; 6542 } 6543 6544 if (m_program_id_draw) 6545 { 6546 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position"); 6547 6548 gl.disableVertexAttribArray(position_location); 6549 6550 glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color"); 6551 6552 gl.disableVertexAttribArray(color_location); 6553 6554 gl.deleteProgram(m_program_id_draw); 6555 6556 m_program_id_draw = 0; 6557 } 6558 6559 if (m_xfb_id) 6560 { 6561 gl.deleteTransformFeedbacks(1, &m_xfb_id); 6562 6563 m_xfb_id = 0; 6564 } 6565 6566 if (m_bo_id_xfb_position) 6567 { 6568 gl.deleteBuffers(1, &m_bo_id_xfb_position); 6569 6570 m_bo_id_xfb_position = 0; 6571 } 6572 6573 if (m_bo_id_xfb_color) 6574 { 6575 gl.deleteBuffers(1, &m_bo_id_xfb_color); 6576 6577 m_bo_id_xfb_position = 0; 6578 } 6579 6580 if (m_bo_id_uniform) 6581 { 6582 gl.deleteBuffers(1, &m_bo_id_uniform); 6583 6584 m_bo_id_uniform = 0; 6585 } 6586 6587 if (m_vao_id) 6588 { 6589 gl.deleteVertexArrays(1, &m_vao_id); 6590 6591 m_vao_id = 0; 6592 } 6593 6594 if (m_fbo_id) 6595 { 6596 gl.deleteFramebuffers(1, &m_fbo_id); 6597 6598 m_fbo_id = 0; 6599 } 6600 6601 if (m_rbo_id) 6602 { 6603 gl.deleteRenderbuffers(1, &m_rbo_id); 6604 6605 m_rbo_id = 0; 6606 } 6607 } 6608 6609 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_blank = "#version 140\n" 6610 "\n" 6611 "void main()\n" 6612 "{\n" 6613 "}\n"; 6614 6615 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_geometry_shader_generate = 6616 "#version 400\n" 6617 "\n" 6618 "layout(points) in;\n" 6619 "layout(points, max_vertices = 8) out;\n" 6620 "\n" 6621 "layout(stream = 1) out vec4 color;\n" 6622 "\n" 6623 "void main()\n" 6624 "{\n" 6625 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 6626 " EmitStreamVertex(0);\n" 6627 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n" 6628 " EmitStreamVertex(0);\n" 6629 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 6630 " EmitStreamVertex(0);\n" 6631 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n" 6632 " EmitStreamVertex(0);\n" 6633 "\n" 6634 " color = vec4(1.0, 1.0, 1.0, 1.0);\n" 6635 " EmitStreamVertex(1);\n" 6636 " color = vec4(1.0, 1.0, 1.0, 1.0);\n" 6637 " EmitStreamVertex(1);\n" 6638 " color = vec4(1.0, 1.0, 1.0, 1.0);\n" 6639 " EmitStreamVertex(1);\n" 6640 " color = vec4(1.0, 1.0, 1.0, 1.0);\n" 6641 " EmitStreamVertex(1);\n" 6642 "}\n"; 6643 6644 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_draw = 6645 "#version 140\n" 6646 "\n" 6647 "uniform MatrixBlock\n" 6648 "{\n" 6649 " mat4 transformation_0;\n" 6650 " mat4 transformation_1;\n" 6651 " mat4 transformation_2;\n" 6652 " mat4 transformation_3;\n" 6653 "};\n" 6654 "\n" 6655 "in vec4 position;\n" 6656 "in vec4 color;\n" 6657 "out vec4 colour;\n" 6658 "\n" 6659 "void main()\n" 6660 "{\n" 6661 " switch(gl_InstanceID % 4)\n" 6662 " {\n" 6663 " case 0:\n" 6664 " gl_Position = position * transformation_0;\n" 6665 " break;\n" 6666 " case 1:\n" 6667 " gl_Position = position * transformation_1;\n" 6668 " break;\n" 6669 " case 2:\n" 6670 " gl_Position = position * transformation_2;\n" 6671 " break;\n" 6672 " case 3:\n" 6673 " gl_Position = position * transformation_3;\n" 6674 " break;\n" 6675 " }\n" 6676 " colour = color;\n" 6677 "}\n"; 6678 6679 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_blank = 6680 "#version 130\n" 6681 "\n" 6682 "out vec4 pixel;\n" 6683 "\n" 6684 "void main()\n" 6685 "{\n" 6686 " pixel = vec4(1.0);\n" 6687 "}\n"; 6688 6689 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_draw = "#version 130\n" 6690 "\n" 6691 "in vec4 colour;\n" 6692 "out vec4 pixel;\n" 6693 "\n" 6694 "void main()\n" 6695 "{\n" 6696 " pixel = colour;\n" 6697 "}\n"; 6698 6699 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings[] = { "gl_Position", 6700 "gl_NextBuffer", "color" }; 6701 6702 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings_count = 6703 sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]); 6704 6705 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_uniform = "MatrixBlock"; 6706 6707 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_xfb_size = 6708 4 /* vertex count */ * 4 /* vec4 components */ 6709 * sizeof(glw::GLfloat) /* data type size */; 6710 6711 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_data[] = { 6712 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 6713 6714 0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 6715 6716 0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 6717 6718 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f 6719 }; 6720 6721 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data); 6722 6723 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_view_size = 4; 6724 6725 /*-----------------------------------------------------------------------------------------------*/ 6726 6727 glw::GLuint gl3cts::TransformFeedback::Utilities::buildProgram( 6728 glw::Functions const& gl, tcu::TestLog& log, glw::GLchar const* const geometry_shader_source, 6729 glw::GLchar const* const tessellation_control_shader_source, 6730 glw::GLchar const* const tessellation_evaluation_shader_source, glw::GLchar const* const vertex_shader_source, 6731 glw::GLchar const* const fragment_shader_source, glw::GLchar const* const* const transform_feedback_varyings, 6732 glw::GLsizei const transform_feedback_varyings_count, glw::GLenum const transform_feedback_varyings_mode, 6733 bool const do_not_detach, glw::GLint* linking_status) 6734 { 6735 glw::GLuint program = 0; 6736 6737 struct Shader 6738 { 6739 glw::GLchar const* const source; 6740 glw::GLenum const type; 6741 glw::GLuint id; 6742 } shader[] = { { geometry_shader_source, GL_GEOMETRY_SHADER, 0 }, 6743 { tessellation_control_shader_source, GL_TESS_CONTROL_SHADER, 0 }, 6744 { tessellation_evaluation_shader_source, GL_TESS_EVALUATION_SHADER, 0 }, 6745 { vertex_shader_source, GL_VERTEX_SHADER, 0 }, 6746 { fragment_shader_source, GL_FRAGMENT_SHADER, 0 } }; 6747 6748 glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]); 6749 6750 try 6751 { 6752 /* Create program. */ 6753 program = gl.createProgram(); 6754 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed."); 6755 6756 /* Shader compilation. */ 6757 6758 for (glw::GLuint i = 0; i < shader_count; ++i) 6759 { 6760 if (DE_NULL != shader[i].source) 6761 { 6762 shader[i].id = gl.createShader(shader[i].type); 6763 6764 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed."); 6765 6766 gl.attachShader(program, shader[i].id); 6767 6768 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed."); 6769 6770 gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL); 6771 6772 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed."); 6773 6774 gl.compileShader(shader[i].id); 6775 6776 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed."); 6777 6778 glw::GLint status = GL_FALSE; 6779 6780 gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status); 6781 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed."); 6782 6783 if (GL_FALSE == status) 6784 { 6785 glw::GLint log_size = 0; 6786 gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size); 6787 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed."); 6788 6789 glw::GLchar* log_text = new glw::GLchar[log_size]; 6790 6791 gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]); 6792 6793 log << tcu::TestLog::Message << "Shader compilation has failed.\n" 6794 << "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n" 6795 << "Shader compilation error log:\n" 6796 << log_text << "\n" 6797 << "Shader source code:\n" 6798 << shader[i].source << "\n" 6799 << tcu::TestLog::EndMessage; 6800 6801 delete[] log_text; 6802 6803 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed."); 6804 6805 throw 0; 6806 } 6807 } 6808 } 6809 6810 /* Link. */ 6811 if (transform_feedback_varyings_count) 6812 { 6813 gl.transformFeedbackVaryings(program, transform_feedback_varyings_count, transform_feedback_varyings, 6814 transform_feedback_varyings_mode); 6815 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed."); 6816 } 6817 6818 gl.linkProgram(program); 6819 6820 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed."); 6821 6822 glw::GLint status = GL_FALSE; 6823 6824 gl.getProgramiv(program, GL_LINK_STATUS, &status); 6825 6826 if (DE_NULL != linking_status) 6827 { 6828 *linking_status = status; 6829 } 6830 6831 if (GL_TRUE == status) 6832 { 6833 if (!do_not_detach) 6834 { 6835 for (glw::GLuint i = 0; i < shader_count; ++i) 6836 { 6837 if (shader[i].id) 6838 { 6839 gl.detachShader(program, shader[i].id); 6840 6841 GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed."); 6842 } 6843 } 6844 } 6845 } 6846 else 6847 { 6848 glw::GLint log_size = 0; 6849 6850 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &log_size); 6851 6852 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed."); 6853 6854 glw::GLchar* log_text = new glw::GLchar[log_size]; 6855 6856 gl.getProgramInfoLog(program, log_size, NULL, &log_text[0]); 6857 6858 log << tcu::TestLog::Message << "Program linkage has failed due to:\n" 6859 << log_text << "\n" 6860 << tcu::TestLog::EndMessage; 6861 6862 delete[] log_text; 6863 6864 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed."); 6865 6866 throw 0; 6867 } 6868 } 6869 catch (...) 6870 { 6871 if (program) 6872 { 6873 gl.deleteProgram(program); 6874 6875 program = 0; 6876 } 6877 } 6878 6879 for (glw::GLuint i = 0; i < shader_count; ++i) 6880 { 6881 if (0 != shader[i].id) 6882 { 6883 gl.deleteShader(shader[i].id); 6884 6885 shader[i].id = 0; 6886 } 6887 } 6888 6889 return program; 6890 } 6891 6892 /** @brief Substitute key with value within source code. 6893 * 6894 * @param [in] source Source code to be prerocessed. 6895 * @param [in] key Key to be substituted. 6896 * @param [in] value Value to be inserted. 6897 * 6898 * @return Resulting string. 6899 */ 6900 std::string gl3cts::TransformFeedback::Utilities::preprocessCode(std::string source, std::string key, std::string value) 6901 { 6902 std::string destination = source; 6903 6904 while (true) 6905 { 6906 /* Find token in source code. */ 6907 size_t position = destination.find(key, 0); 6908 6909 /* No more occurences of this key. */ 6910 if (position == std::string::npos) 6911 { 6912 break; 6913 } 6914 6915 /* Replace token with sub_code. */ 6916 destination.replace(position, key.size(), value); 6917 } 6918 6919 return destination; 6920 } 6921 6922 /** @brief Convert an integer to a string. 6923 * 6924 * @param [in] i Integer to be converted. 6925 * 6926 * @return String representing integer. 6927 */ 6928 std::string gl3cts::TransformFeedback::Utilities::itoa(glw::GLint i) 6929 { 6930 std::stringstream stream; 6931 6932 stream << i; 6933 6934 return stream.str(); 6935 } 6936 6937 /** @brief Convert an float to a string. 6938 * 6939 * @param [in] f Float to be converted. 6940 * 6941 * @return String representing integer. 6942 */ 6943 std::string gl3cts::TransformFeedback::Utilities::ftoa(glw::GLfloat f) 6944 { 6945 std::stringstream stream; 6946 6947 stream << f; 6948 6949 return stream.str(); 6950 } 6951