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 if by DrawTransformFeedbackStreamInstanced 1581 if EndTransformFeedback was never called for the object named <id>. 1582 return true */ 1583 1584 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_1); 1585 1586 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed."); 1587 1588 gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, m_transform_feedback_object_1, 0, 1); 1589 1590 if (GL_INVALID_OPERATION != gl.getError()) 1591 { 1592 m_context.getTestContext().getLog() 1593 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and " 1594 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader." 1595 << tcu::TestLog::EndMessage; 1596 1597 return false; 1598 } 1599 1600 return true; 1601 } 1602 1603 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_tessellation_control_shader = 1604 "#version 400\n" 1605 "\n" 1606 "layout (vertices = 2 ) out;\n" 1607 "\n" 1608 "void main()\n" 1609 "{\n" 1610 " gl_TessLevelOuter[1] = 3.0;\n" 1611 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 1612 "}\n"; 1613 1614 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_tessellation_evaluation_shader = 1615 "#version 400\n" 1616 "\n" 1617 "layout(isolines, equal_spacing, ccw) in;\n" 1618 "\n" 1619 "out float result;\n" 1620 "\n" 1621 "void main()\n" 1622 "{\n" 1623 " result = 0.5;\n" 1624 " gl_Position = gl_in[0].gl_Position + gl_in[1].gl_Position + gl_in[2].gl_Position;\n" 1625 "}\n"; 1626 1627 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_geometry_shader = 1628 "#version 150\n" 1629 "\n" 1630 "layout(points) in;\n" 1631 "layout(points, max_vertices = 2) out;\n" 1632 "\n" 1633 "out float result;\n" 1634 "\n" 1635 "void main()\n" 1636 "{\n" 1637 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.0, 0.0, 0.0);\n" 1638 " result = 0.0;\n" 1639 " EmitVertex();\n" 1640 "\n" 1641 " gl_Position = gl_in[0].gl_Position + vec4(1.0, 0.0, 0.0, 0.0);\n" 1642 " result = 1.0;\n" 1643 " EmitVertex();\n" 1644 "}\n"; 1645 1646 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_vertex_shader_with_output = 1647 "#version 130\n" 1648 "\n" 1649 "out float result;\n" 1650 "\n" 1651 "void main()\n" 1652 "{\n" 1653 " result = float(gl_VertexID);\n" 1654 " gl_Position = vec4(1.0);\n" 1655 "}\n"; 1656 1657 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_vertex_shader_with_input_output = 1658 "#version 130\n" 1659 "\n" 1660 "in float v_input;\n" 1661 "\n" 1662 "out float result;\n" 1663 "\n" 1664 "void main()\n" 1665 "{\n" 1666 " result = float(gl_VertexID);\n" 1667 " gl_Position = vec4(v_input);\n" 1668 "}\n"; 1669 1670 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_vertex_shader_without_output = 1671 "#version 130\n" 1672 "\n" 1673 "void main()\n" 1674 "{\n" 1675 " gl_Position = vec4(1.0);\n" 1676 "}\n"; 1677 1678 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_fragment_shader = "#version 130\n" 1679 "\n" 1680 "out vec4 color;\n" 1681 "\n" 1682 "void main()\n" 1683 "{\n" 1684 " color = vec4(1.0);\n" 1685 "}\n"; 1686 1687 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_varying_name = "result"; 1688 1689 const glw::GLfloat gl3cts::TransformFeedback::APIErrors::m_buffer_1_data[] = { 3.14159265359f, 2.7182818f }; 1690 1691 const glw::GLsizei gl3cts::TransformFeedback::APIErrors::m_buffer_1_size = 1692 sizeof(gl3cts::TransformFeedback::APIErrors::m_buffer_1_data); 1693 1694 /*-----------------------------------------------------------------------------------------------*/ 1695 1696 gl3cts::TransformFeedback::LinkingErrors::LinkingErrors(deqp::Context& context) 1697 : deqp::TestCase(context, "linking_errors_test", "Transform Feedback Linking Errors Test"), m_context(context) 1698 { 1699 /* Left intentionally blank. */ 1700 } 1701 1702 gl3cts::TransformFeedback::LinkingErrors::~LinkingErrors(void) 1703 { 1704 } 1705 1706 tcu::TestNode::IterateResult gl3cts::TransformFeedback::LinkingErrors::iterate(void) 1707 { 1708 bool is_ok = true; 1709 bool test_error = false; 1710 1711 try 1712 { 1713 is_ok = is_ok && testNoVertexNoGeometry(); 1714 is_ok = is_ok && testInvalidVarying(); 1715 is_ok = is_ok && testRepeatedVarying(); 1716 is_ok = is_ok && testTooManyVaryings(); 1717 } 1718 catch (...) 1719 { 1720 is_ok = false; 1721 test_error = true; 1722 } 1723 1724 /* Result's setup. */ 1725 if (is_ok) 1726 { 1727 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1728 } 1729 else 1730 { 1731 if (test_error) 1732 { 1733 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 1734 } 1735 else 1736 { 1737 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 1738 } 1739 } 1740 1741 return STOP; 1742 } 1743 1744 bool gl3cts::TransformFeedback::LinkingErrors::testNoVertexNoGeometry(void) 1745 { 1746 /* Functions handler */ 1747 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1748 1749 /* Check if link process fails under the following conditions: 1750 <count> specified by TransformFeedbackVaryings is non-zero and program has 1751 neither vertex nor geometry shader; */ 1752 1753 glw::GLint linking_status = 1; 1754 1755 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram( 1756 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, NULL, s_fragment_shader, 1757 &s_valid_transform_feedback_varying, 1, GL_INTERLEAVED_ATTRIBS, false, &linking_status); 1758 1759 if ((GL_FALSE != linking_status) || program) 1760 { 1761 m_context.getTestContext().getLog() << tcu::TestLog::Message 1762 << "Linking unexpectedly succeded when Transform Feedback varying was " 1763 "specified but program had neither vertex nor geometry shader stages." 1764 << tcu::TestLog::EndMessage; 1765 1766 if (program) 1767 { 1768 gl.deleteProgram(program); 1769 } 1770 1771 return false; 1772 } 1773 1774 /* Log success. */ 1775 m_context.getTestContext().getLog() << tcu::TestLog::Message 1776 << "Linking failed as expected when Transform Feedback varying was specified " 1777 "but program had neither vertex nor geometry shader stages." 1778 << tcu::TestLog::EndMessage; 1779 1780 return true; 1781 } 1782 1783 bool gl3cts::TransformFeedback::LinkingErrors::testInvalidVarying(void) 1784 { 1785 /* Functions handler */ 1786 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1787 1788 /* Check if link process fails under the following conditions: 1789 <varyings> specified by TransformFeedbackVaryings contains name of 1790 variable that is not available for capture; */ 1791 1792 std::string vertex_shader(s_vertex_shader_template); 1793 1794 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 1795 vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", "in float data;\n"); 1796 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS", ""); 1797 1798 glw::GLint linking_status = 1; 1799 1800 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram( 1801 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader, 1802 &s_invalid_transform_feedback_varying, 1, GL_INTERLEAVED_ATTRIBS, false, &linking_status); 1803 1804 if ((GL_FALSE != linking_status) || program) 1805 { 1806 m_context.getTestContext().getLog() 1807 << tcu::TestLog::Message 1808 << "Linking unexpectedly succeded when Transform Feedback varying was specified with name of variable (" 1809 << s_invalid_transform_feedback_varying << ") that is not available for capture." 1810 << tcu::TestLog::EndMessage; 1811 1812 if (program) 1813 { 1814 gl.deleteProgram(program); 1815 } 1816 1817 return false; 1818 } 1819 1820 /* Log success. */ 1821 m_context.getTestContext().getLog() 1822 << tcu::TestLog::Message 1823 << "Linking failed as expected when Transform Feedback varying was specified with name of variable (" 1824 << s_invalid_transform_feedback_varying << ") that is not available for capture." << tcu::TestLog::EndMessage; 1825 1826 return true; 1827 } 1828 1829 bool gl3cts::TransformFeedback::LinkingErrors::testRepeatedVarying(void) 1830 { 1831 /* Functions handler */ 1832 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1833 1834 /* Check if link process fails under the following conditions: 1835 <varyings> specified by TransformFeedbackVaryings contains name of 1836 variable more than once; */ 1837 1838 std::string vertex_shader(s_vertex_shader_template); 1839 1840 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 1841 vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", "out float result;\n"); 1842 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS", 1843 " result = 0.577215664901532;\n"); 1844 1845 glw::GLint linking_status = 1; 1846 1847 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram( 1848 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader, 1849 s_repeated_transform_feedback_varying, s_repeated_transform_feedback_varying_count, GL_INTERLEAVED_ATTRIBS, 1850 false, &linking_status); 1851 1852 if ((GL_FALSE != linking_status) || program) 1853 { 1854 m_context.getTestContext().getLog() 1855 << tcu::TestLog::Message 1856 << "Linking unexpectedly succeded when Transform Feedback varying was specified twice." 1857 << tcu::TestLog::EndMessage; 1858 1859 if (program) 1860 { 1861 gl.deleteProgram(program); 1862 } 1863 1864 return false; 1865 } 1866 1867 /* Log success. */ 1868 m_context.getTestContext().getLog() 1869 << tcu::TestLog::Message << "Linking failed as expected when Transform Feedback varying was specified twice." 1870 << tcu::TestLog::EndMessage; 1871 1872 return true; 1873 } 1874 1875 bool gl3cts::TransformFeedback::LinkingErrors::testTooManyVaryings(void) 1876 { 1877 /* Functions handler */ 1878 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1879 1880 /* Check if link process fails under the following conditions: 1881 number of components specified to capture exceeds limits 1882 MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS or 1883 MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS. */ 1884 1885 /* Fetching limits. */ 1886 glw::GLint max_transform_feedback_separate_components = 0; 1887 glw::GLint max_transform_feedback_interleaved_components = 0; 1888 1889 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components); 1890 1891 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 1892 1893 if (max_transform_feedback_separate_components == 0) 1894 { 1895 throw 0; 1896 } 1897 1898 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components); 1899 1900 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 1901 1902 if (max_transform_feedback_interleaved_components == 0) 1903 { 1904 throw 0; 1905 } 1906 1907 glw::GLint more_than_max_transform_feedback_components = 1908 deMax32(max_transform_feedback_separate_components, max_transform_feedback_interleaved_components) + 1; 1909 1910 /* Preparing source code. */ 1911 std::string vertex_shader(s_vertex_shader_template); 1912 std::string transform_feedback_variable_declarations(""); 1913 std::string transform_feedback_variable_setters(""); 1914 std::vector<std::string> transform_feedback_varyings(more_than_max_transform_feedback_components); 1915 std::vector<const glw::GLchar*> transform_feedback_varyings_c(more_than_max_transform_feedback_components); 1916 1917 for (glw::GLint i = 0; i < more_than_max_transform_feedback_components; ++i) 1918 { 1919 std::string varying = "result_"; 1920 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i)); 1921 1922 transform_feedback_varyings[i] = varying; 1923 1924 transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str(); 1925 1926 transform_feedback_variable_declarations.append("out float "); 1927 transform_feedback_variable_declarations.append(varying); 1928 transform_feedback_variable_declarations.append(";\n"); 1929 1930 transform_feedback_variable_setters.append(" "); 1931 transform_feedback_variable_setters.append(varying); 1932 transform_feedback_variable_setters.append(" = "); 1933 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * i)); 1934 transform_feedback_variable_setters.append(".0;\n"); 1935 } 1936 1937 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 1938 vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations); 1939 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS", 1940 transform_feedback_variable_setters); 1941 1942 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram( 1943 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader, 1944 &transform_feedback_varyings_c[0], more_than_max_transform_feedback_components, GL_INTERLEAVED_ATTRIBS); 1945 1946 /* Note: we check for program as not only linking shall fail, but also glTransformFeedbackVaryings shall return an error. */ 1947 1948 if (program) 1949 { 1950 m_context.getTestContext().getLog() << tcu::TestLog::Message 1951 << "Linking unexpectedly succeded when too many Transform Feedback varying " 1952 "were specified in INTERLEAVED mode." 1953 << tcu::TestLog::EndMessage; 1954 1955 if (program) 1956 { 1957 gl.deleteProgram(program); 1958 } 1959 1960 return false; 1961 } 1962 1963 program = gl3cts::TransformFeedback::Utilities::buildProgram( 1964 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader, 1965 &transform_feedback_varyings_c[0], more_than_max_transform_feedback_components, GL_SEPARATE_ATTRIBS); 1966 1967 if (program) 1968 { 1969 m_context.getTestContext().getLog() << tcu::TestLog::Message 1970 << "Linking unexpectedly succeded when too many Transform Feedback " 1971 "varyings were specified in SEPARATE mode." 1972 << tcu::TestLog::EndMessage; 1973 1974 if (program) 1975 { 1976 gl.deleteProgram(program); 1977 } 1978 1979 return false; 1980 } 1981 1982 /* Log success. */ 1983 m_context.getTestContext().getLog() 1984 << tcu::TestLog::Message 1985 << "Linking failed as expected when too many Transform Feedback varyings were specified." 1986 << tcu::TestLog::EndMessage; 1987 1988 return true; 1989 } 1990 1991 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_fragment_shader = "#version 130\n" 1992 "\n" 1993 "out vec4 color;\n" 1994 "\n" 1995 "void main()\n" 1996 "{\n" 1997 " color = vec4(1.0);\n" 1998 "}\n"; 1999 2000 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_vertex_shader_template = 2001 "#version 130\n" 2002 "\n" 2003 "TEMPLATE_INPUT_OUTPUT_DECLARATIONS" 2004 "\n" 2005 "void main()\n" 2006 "{\n" 2007 "TEMPLATE_OUTPUT_SETTERS" 2008 "\n" 2009 " gl_Position = vec4(1.618033988749);\n" 2010 "}\n"; 2011 2012 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_valid_transform_feedback_varying = "result"; 2013 2014 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_invalid_transform_feedback_varying = "data"; 2015 2016 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_repeated_transform_feedback_varying[] = { "result", 2017 "result" }; 2018 2019 const glw::GLsizei gl3cts::TransformFeedback::LinkingErrors::s_repeated_transform_feedback_varying_count = 2020 sizeof(s_repeated_transform_feedback_varying) / sizeof(s_repeated_transform_feedback_varying[0]); 2021 2022 /*-----------------------------------------------------------------------------------------------*/ 2023 2024 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_interleaved_components = 64; 2025 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_separate_attribs = 4; 2026 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_separate_components = 4; 2027 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_buffers = 4; 2028 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_vertex_streams = 1; 2029 2030 gl3cts::TransformFeedback::Limits::Limits(deqp::Context& context) 2031 : deqp::TestCase(context, "limits_test", "Transform Feedback Limits Test"), m_context(context) 2032 { 2033 } 2034 2035 gl3cts::TransformFeedback::Limits::~Limits(void) 2036 { 2037 } 2038 2039 tcu::TestNode::IterateResult gl3cts::TransformFeedback::Limits::iterate(void) 2040 { 2041 /* Initializations. */ 2042 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0))); 2043 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 2044 2045 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback"); 2046 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3"); 2047 2048 bool is_ok = true; 2049 bool test_error = false; 2050 2051 /* Tests. */ 2052 try 2053 { 2054 if (is_at_least_gl_30 || is_ext_tf_1) 2055 { 2056 is_ok = is_ok && test_max_transform_feedback_interleaved_components(); 2057 is_ok = is_ok && test_max_transform_feedback_separate_attribs(); 2058 is_ok = is_ok && test_max_transform_feedback_separate_components(); 2059 } 2060 2061 if (is_at_least_gl_40 || is_arb_tf_3) 2062 { 2063 is_ok = is_ok && test_max_transform_feedback_buffers(); 2064 is_ok = is_ok && test_max_vertex_streams(); 2065 } 2066 } 2067 catch (...) 2068 { 2069 is_ok = false; 2070 test_error = true; 2071 } 2072 2073 /* Result's setup. */ 2074 if (is_ok) 2075 { 2076 /* Log success. */ 2077 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Limits are in range of specification." 2078 << tcu::TestLog::EndMessage; 2079 2080 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2081 } 2082 else 2083 { 2084 if (test_error) 2085 { 2086 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 2087 } 2088 else 2089 { 2090 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2091 } 2092 } 2093 2094 return STOP; 2095 } 2096 2097 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_interleaved_components(void) 2098 { 2099 /* Functions handler */ 2100 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2101 2102 /* Check that MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is at least 64. */ 2103 glw::GLint max_transform_feedback_interleaved_components = 0; 2104 2105 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components); 2106 2107 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2108 2109 if (max_transform_feedback_interleaved_components < s_min_value_of_max_transform_feedback_interleaved_components) 2110 { 2111 m_context.getTestContext().getLog() 2112 << tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is equal to " 2113 << max_transform_feedback_interleaved_components << " which is less than expected " 2114 << s_min_value_of_max_transform_feedback_interleaved_components << "." << tcu::TestLog::EndMessage; 2115 return false; 2116 } 2117 2118 return true; 2119 } 2120 2121 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_separate_attribs(void) 2122 { 2123 /* Functions handler */ 2124 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2125 2126 /* Check that MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS is at least 4. */ 2127 glw::GLint max_transform_feedback_separate_attribs = 0; 2128 2129 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_transform_feedback_separate_attribs); 2130 2131 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2132 2133 if (max_transform_feedback_separate_attribs < s_min_value_of_max_transform_feedback_separate_attribs) 2134 { 2135 m_context.getTestContext().getLog() 2136 << tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS is equal to " 2137 << max_transform_feedback_separate_attribs << " which is less than expected " 2138 << s_min_value_of_max_transform_feedback_separate_attribs << "." << tcu::TestLog::EndMessage; 2139 return false; 2140 } 2141 2142 return true; 2143 } 2144 2145 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_separate_components(void) 2146 { 2147 /* Functions handler */ 2148 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2149 2150 /* Check that MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS is at least 4. */ 2151 glw::GLint max_transform_feedback_separate_components = 0; 2152 2153 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components); 2154 2155 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2156 2157 if (max_transform_feedback_separate_components < s_min_value_of_max_transform_feedback_separate_components) 2158 { 2159 m_context.getTestContext().getLog() 2160 << tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS is equal to " 2161 << max_transform_feedback_separate_components << " which is less than expected " 2162 << s_min_value_of_max_transform_feedback_separate_components << "." << tcu::TestLog::EndMessage; 2163 return false; 2164 } 2165 2166 return true; 2167 } 2168 2169 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_buffers(void) 2170 { 2171 /* Functions handler */ 2172 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2173 2174 /* Check that MAX_TRANSFORM_FEEDBACK_BUFFERS is at least 4. */ 2175 glw::GLint max_transform_feedback_buffers = 0; 2176 2177 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers); 2178 2179 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2180 2181 if (max_transform_feedback_buffers < s_min_value_of_max_transform_feedback_buffers) 2182 { 2183 m_context.getTestContext().getLog() << tcu::TestLog::Message << "MAX_TRANSFORM_FEEDBACK_BUFFERS is equal to " 2184 << max_transform_feedback_buffers << " which is less than expected " 2185 << s_min_value_of_max_transform_feedback_buffers << "." 2186 << tcu::TestLog::EndMessage; 2187 return false; 2188 } 2189 2190 return true; 2191 } 2192 2193 bool gl3cts::TransformFeedback::Limits::test_max_vertex_streams(void) 2194 { 2195 /* Functions handler */ 2196 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2197 2198 /* Check that MAX_VERTEX_STREAMS is at least 1. */ 2199 glw::GLint max_vertex_streams = 0; 2200 2201 gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams); 2202 2203 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2204 2205 if (max_vertex_streams < s_min_value_of_max_vertex_streams) 2206 { 2207 m_context.getTestContext().getLog() << tcu::TestLog::Message << "MAX_VERTEX_STREAMS is equal to " 2208 << max_vertex_streams << " which is less than expected " 2209 << s_min_value_of_max_vertex_streams << "." << tcu::TestLog::EndMessage; 2210 return false; 2211 } 2212 2213 return true; 2214 } 2215 2216 /*-----------------------------------------------------------------------------------------------*/ 2217 2218 gl3cts::TransformFeedback::CaptureVertexInterleaved::CaptureVertexInterleaved(deqp::Context& context, 2219 const char* test_name, 2220 const char* test_description) 2221 : deqp::TestCase(context, test_name, test_description) 2222 , m_context(context) 2223 , m_program(0) 2224 , m_framebuffer(0) 2225 , m_renderbuffer(0) 2226 , m_buffer(0) 2227 , m_buffer_size(0) 2228 , m_vertex_array_object(0) 2229 , m_max_transform_feedback_components(0) 2230 , m_attrib_type(GL_INTERLEAVED_ATTRIBS) 2231 , m_max_vertices_drawn(8) 2232 , m_glBindBufferOffsetEXT(DE_NULL) 2233 { 2234 } 2235 2236 gl3cts::TransformFeedback::CaptureVertexInterleaved::~CaptureVertexInterleaved(void) 2237 { 2238 } 2239 2240 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureVertexInterleaved::iterate(void) 2241 { 2242 /* Functions handler */ 2243 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2244 2245 /* Initializations. */ 2246 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0))); 2247 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback"); 2248 2249 bool is_ok = true; 2250 bool test_error = false; 2251 2252 try 2253 { 2254 if (is_ext_tf_1) 2255 { 2256 /* Extension query. */ 2257 m_glBindBufferOffsetEXT = 2258 (BindBufferOffsetEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glBindBufferOffsetEXT"); 2259 2260 if (DE_NULL == m_glBindBufferOffsetEXT) 2261 { 2262 throw 0; 2263 } 2264 } 2265 2266 if (is_at_least_gl_30 || is_ext_tf_1) 2267 { 2268 fetchLimits(); 2269 buildProgram(); 2270 createFramebuffer(); 2271 createTransformFeedbackBuffer(); 2272 createVertexArrayObject(); 2273 2274 gl.useProgram(m_program); 2275 2276 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 2277 2278 for (glw::GLint i_bind_case = 0; (i_bind_case < BIND_BUFFER_CASES_COUNT) && is_ok; ++i_bind_case) 2279 { 2280 if ((i_bind_case == BIND_BUFFER_OFFSET_CASE) && (DE_NULL == m_glBindBufferOffsetEXT)) 2281 { 2282 continue; 2283 } 2284 2285 bindBuffer((BindBufferCase)i_bind_case); 2286 2287 for (glw::GLuint i_primitive_case = 0; (i_primitive_case < s_primitive_cases_count) && is_ok; 2288 ++i_primitive_case) 2289 { 2290 draw(i_primitive_case); 2291 2292 is_ok = is_ok && checkFramebuffer(s_primitive_cases[i_primitive_case]); 2293 is_ok = is_ok && checkTransformFeedbackBuffer((BindBufferCase)i_bind_case, 2294 s_primitive_cases[i_primitive_case]); 2295 } 2296 } 2297 } 2298 } 2299 catch (...) 2300 { 2301 is_ok = false; 2302 test_error = true; 2303 } 2304 2305 /* Clean objects. */ 2306 clean(); 2307 2308 /* Result's setup. */ 2309 if (is_ok) 2310 { 2311 /* Log success. */ 2312 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Vertex have passed." 2313 << tcu::TestLog::EndMessage; 2314 2315 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2316 } 2317 else 2318 { 2319 if (test_error) 2320 { 2321 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 2322 } 2323 else 2324 { 2325 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2326 } 2327 } 2328 2329 return STOP; 2330 } 2331 2332 void gl3cts::TransformFeedback::CaptureVertexInterleaved::fetchLimits(void) 2333 { 2334 /* Functions handler */ 2335 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2336 2337 /* Fetching limits. */ 2338 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_transform_feedback_components); 2339 2340 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2341 2342 if (m_max_transform_feedback_components == 0) 2343 { 2344 throw 0; 2345 } 2346 2347 glw::GLint max_varyings_components = 0; 2348 2349 gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings_components); 2350 2351 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2352 2353 if (max_varyings_components == 0) 2354 { 2355 throw 0; 2356 } 2357 2358 if (m_max_transform_feedback_components > max_varyings_components) 2359 { 2360 m_max_transform_feedback_components = max_varyings_components; 2361 } 2362 } 2363 2364 void gl3cts::TransformFeedback::CaptureVertexInterleaved::buildProgram(void) 2365 { 2366 /* Functions handler */ 2367 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2368 2369 /* Preparing source code. */ 2370 std::string vertex_shader(s_vertex_shader_source_code_template); /* Storage for vertex shader source code. */ 2371 std::string transform_feedback_variable_declarations( 2372 ""); /* String to contain all custom outputs from vertex shader. */ 2373 std::string transform_feedback_variable_setters( 2374 ""); /* String containing all initializations of custom outputs from vertex shader. */ 2375 std::vector<std::string> transform_feedback_varyings(m_max_transform_feedback_components); /* Varyings array. */ 2376 std::vector<const glw::GLchar*> transform_feedback_varyings_c( 2377 m_max_transform_feedback_components); /* Varyings array in C form to pass to the GL. */ 2378 2379 glw::GLint user_defined_transform_feedback_interleaved_varyings_count = 2380 m_max_transform_feedback_components /* total max to be written by the shader */ 2381 / 4 /* components per vec4 */ 2382 - 1 /* gl_Position */; 2383 2384 glw::GLint all_transform_feedback_interleaved_varyings_count = 2385 user_defined_transform_feedback_interleaved_varyings_count + 1 /* gl_Position */; 2386 2387 /* Most of varyings is declarated output variables. */ 2388 for (glw::GLint i = 0; i < user_defined_transform_feedback_interleaved_varyings_count; ++i) 2389 { 2390 std::string varying = "result_"; 2391 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i)); 2392 2393 transform_feedback_varyings[i] = varying; 2394 2395 transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str(); 2396 2397 transform_feedback_variable_declarations.append("out vec4 "); 2398 transform_feedback_variable_declarations.append(varying); 2399 transform_feedback_variable_declarations.append(";\n"); 2400 2401 transform_feedback_variable_setters.append(" "); 2402 transform_feedback_variable_setters.append(varying); 2403 transform_feedback_variable_setters.append(" = vec4("); 2404 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4)); 2405 transform_feedback_variable_setters.append(".0, "); 2406 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 1)); 2407 transform_feedback_variable_setters.append(".0, "); 2408 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 2)); 2409 transform_feedback_variable_setters.append(".0, "); 2410 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 3)); 2411 transform_feedback_variable_setters.append(".0);\n"); 2412 } 2413 2414 /* Last four varying components are gl_Position components. */ 2415 transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count] = "gl_Position"; 2416 2417 transform_feedback_varyings_c[user_defined_transform_feedback_interleaved_varyings_count] = 2418 transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count].c_str(); 2419 2420 /* Preprocess vertex shader source code template. */ 2421 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 2422 vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations); 2423 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS", 2424 transform_feedback_variable_setters); 2425 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 2426 vertex_shader, "TEMPLATE_RASTERIZATION_EPSILON", 2427 gl3cts::TransformFeedback::Utilities::ftoa(s_rasterization_epsilon)); 2428 2429 /* Compile, link and check. */ 2430 m_program = gl3cts::TransformFeedback::Utilities::buildProgram( 2431 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader_source_code, 2432 &transform_feedback_varyings_c[0], all_transform_feedback_interleaved_varyings_count, m_attrib_type); 2433 2434 if (0 == m_program) 2435 { 2436 throw 0; 2437 } 2438 } 2439 2440 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createFramebuffer(void) 2441 { 2442 /* Functions handler */ 2443 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2444 2445 /* Setting clear color */ 2446 gl.clearColor(0.f, 0.f, 0.f, 1.f); 2447 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 2448 2449 /* Creating framebuffer */ 2450 gl.genFramebuffers(1, &m_framebuffer); 2451 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed."); 2452 2453 gl.genRenderbuffers(1, &m_renderbuffer); 2454 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed."); 2455 2456 gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); 2457 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); 2458 2459 gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer); 2460 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed."); 2461 2462 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32F, s_framebuffer_size, s_framebuffer_size); 2463 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed."); 2464 2465 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer); 2466 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed."); 2467 2468 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 2469 { 2470 throw 0; 2471 } 2472 2473 gl.viewport(0, 0, s_framebuffer_size, s_framebuffer_size); 2474 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed."); 2475 } 2476 2477 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createTransformFeedbackBuffer(void) 2478 { 2479 /* Functions handler */ 2480 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2481 2482 /* Creating xfb buffer */ 2483 gl.genBuffers(1, &m_buffer); 2484 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 2485 2486 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer); 2487 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 2488 2489 m_buffer_size = 2490 static_cast<glw::GLuint>(m_max_transform_feedback_components * m_max_vertices_drawn * sizeof(glw::GLfloat)); 2491 2492 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_size, NULL, GL_DYNAMIC_READ); 2493 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 2494 } 2495 2496 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createVertexArrayObject(void) 2497 { 2498 /* Functions handler */ 2499 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2500 2501 /* VAO Creations */ 2502 gl.genVertexArrays(1, &m_vertex_array_object); 2503 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 2504 2505 gl.bindVertexArray(m_vertex_array_object); 2506 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 2507 } 2508 2509 void gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(glw::GLuint primitive_case) 2510 { 2511 /* Functions handler */ 2512 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2513 2514 /* Draw */ 2515 gl.clear(GL_COLOR_BUFFER_BIT); 2516 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 2517 2518 gl.beginTransformFeedback(s_primitive_cases_xfb[primitive_case]); 2519 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedbac call failed."); 2520 2521 gl.drawElements(s_primitive_cases[primitive_case], s_element_indices_counts[primitive_case], GL_UNSIGNED_INT, 2522 s_element_indices[primitive_case]); 2523 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements call failed."); 2524 2525 gl.endTransformFeedback(); 2526 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedbac call failed."); 2527 } 2528 2529 bool gl3cts::TransformFeedback::CaptureVertexInterleaved::checkFramebuffer(glw::GLenum primitive_type UNUSED) 2530 { 2531 /* Functions handler */ 2532 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2533 2534 /* Fetch framebuffer. */ 2535 std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size); 2536 2537 if ((s_framebuffer_size > 0) && (s_framebuffer_size > 0)) 2538 { 2539 gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data()); 2540 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 2541 } 2542 2543 /* Check results. 2544 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */ 2545 for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i) 2546 { 2547 if (fabs(*i - 0.5f) > 0.0625f /* precision */) 2548 { 2549 return false; 2550 } 2551 } 2552 2553 return true; 2554 } 2555 2556 bool gl3cts::TransformFeedback::CaptureVertexInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED, 2557 glw::GLenum primitive_type) 2558 { 2559 /* Functions handler */ 2560 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2561 2562 /* Check */ 2563 glw::GLuint number_of_vertices = 0; 2564 2565 switch (primitive_type) 2566 { 2567 case GL_POINTS: 2568 number_of_vertices = 4; 2569 break; 2570 case GL_LINES: 2571 number_of_vertices = 4; 2572 break; 2573 case GL_LINE_LOOP: 2574 number_of_vertices = 8; 2575 break; 2576 case GL_LINE_STRIP: 2577 number_of_vertices = 6; 2578 break; 2579 case GL_TRIANGLES: 2580 number_of_vertices = 6; 2581 break; 2582 case GL_TRIANGLE_STRIP: 2583 number_of_vertices = 6; 2584 break; 2585 case GL_TRIANGLE_FAN: 2586 number_of_vertices = 6; 2587 break; 2588 default: 2589 throw 0; 2590 } 2591 2592 glw::GLfloat* results = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 2593 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed."); 2594 2595 bool is_ok = true; 2596 2597 for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j) 2598 { 2599 for (glw::GLint i = 0; i < m_max_transform_feedback_components - 4; ++i) 2600 { 2601 glw::GLfloat result = results[i + j * m_max_transform_feedback_components]; 2602 glw::GLfloat reference = (glw::GLfloat)(i); 2603 2604 if (fabs(result - reference) > 0.125 /* precision */) 2605 { 2606 is_ok = false; 2607 2608 break; 2609 } 2610 } 2611 2612 /* gl_Position */ 2613 glw::GLfloat result[4] = { results[(j + 1) * m_max_transform_feedback_components - 4], 2614 results[(j + 1) * m_max_transform_feedback_components - 3], 2615 results[(j + 1) * m_max_transform_feedback_components - 2], 2616 results[(j + 1) * m_max_transform_feedback_components - 1] }; 2617 2618 if ((fabs(fabs(result[0]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) || 2619 (fabs(fabs(result[1]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) || 2620 (fabs(result[2]) > 0.125 /* precision */) || (fabs(result[3] - 1.0) > 0.125 /* precision */)) 2621 { 2622 is_ok = false; 2623 2624 break; 2625 } 2626 } 2627 2628 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 2629 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 2630 2631 return is_ok; 2632 } 2633 2634 void gl3cts::TransformFeedback::CaptureVertexInterleaved::bindBuffer(BindBufferCase bind_case) 2635 { 2636 /* Functions handler */ 2637 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2638 2639 switch (bind_case) 2640 { 2641 case BIND_BUFFER_BASE_CASE: 2642 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer); 2643 break; 2644 case BIND_BUFFER_RANGE_CASE: 2645 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer, 0, m_buffer_size); 2646 break; 2647 case BIND_BUFFER_OFFSET_CASE: 2648 if (DE_NULL == m_glBindBufferOffsetEXT) 2649 { 2650 throw 0; 2651 } 2652 m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer, 0); 2653 break; 2654 default: 2655 throw 0; 2656 } 2657 } 2658 2659 void gl3cts::TransformFeedback::CaptureVertexInterleaved::clean(void) 2660 { 2661 /* Functions handler */ 2662 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2663 2664 if (m_program) 2665 { 2666 gl.deleteProgram(m_program); 2667 2668 m_program = 0; 2669 } 2670 2671 if (m_framebuffer) 2672 { 2673 gl.deleteFramebuffers(1, &m_framebuffer); 2674 2675 m_framebuffer = 0; 2676 } 2677 2678 if (m_renderbuffer) 2679 { 2680 gl.deleteRenderbuffers(1, &m_renderbuffer); 2681 2682 m_renderbuffer = 0; 2683 } 2684 2685 cleanBuffer(); 2686 2687 if (m_vertex_array_object) 2688 { 2689 gl.deleteVertexArrays(1, &m_vertex_array_object); 2690 2691 m_vertex_array_object = 0; 2692 } 2693 } 2694 2695 void gl3cts::TransformFeedback::CaptureVertexInterleaved::cleanBuffer(void) 2696 { 2697 /* Functions handler */ 2698 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2699 2700 if (m_buffer) 2701 { 2702 gl.deleteBuffers(1, &m_buffer); 2703 2704 m_buffer = 0; 2705 } 2706 } 2707 2708 const glw::GLchar* gl3cts::TransformFeedback::CaptureVertexInterleaved::s_vertex_shader_source_code_template = 2709 "#version 130\n" 2710 "\n" 2711 "TEMPLATE_INPUT_OUTPUT_DECLARATIONS" 2712 "\n" 2713 "void main()\n" 2714 "{\n" 2715 "TEMPLATE_OUTPUT_SETTERS" 2716 "\n" 2717 " vec4 position = vec4(0.0);\n" 2718 "\n" 2719 " /* Note: The points are moved 0.0625 from the borders to\n" 2720 " reduce non-XFB related rasterization problems. */\n" 2721 " switch(gl_VertexID)\n" 2722 " {\n" 2723 " case 0:\n" 2724 " position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 2725 "1.0);\n" 2726 " break;\n" 2727 " case 1:\n" 2728 " position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 2729 "1.0);\n" 2730 " break;\n" 2731 " case 2:\n" 2732 " position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 2733 "1.0);\n" 2734 " break;\n" 2735 " case 3:\n" 2736 " position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 2737 "1.0);\n" 2738 " break;\n" 2739 " }\n" 2740 "\n" 2741 " gl_Position = position;\n" 2742 "}\n"; 2743 2744 const glw::GLchar* gl3cts::TransformFeedback::CaptureVertexInterleaved::s_fragment_shader_source_code = 2745 "#version 130\n" 2746 "\n" 2747 "out vec4 color;\n" 2748 "\n" 2749 "void main()\n" 2750 "{\n" 2751 " color = vec4(0.5);\n" 2752 "}\n"; 2753 2754 const glw::GLuint 2755 gl3cts::TransformFeedback::CaptureVertexInterleaved::s_element_indices[][s_max_element_indices_count] = { 2756 { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, { 0, 1, 3, 2 }, { 0, 1, 3, 2 }, 2757 { 2, 0, 1, 2, 1, 3 }, { 0, 1, 2, 3 }, { 2, 0, 1, 3 } 2758 }; 2759 2760 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases_count = 2761 sizeof(s_element_indices) / sizeof(s_element_indices[0]); 2762 2763 const glw::GLenum gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases[] = { 2764 GL_POINTS, GL_LINES, GL_LINE_LOOP, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN 2765 }; 2766 2767 const glw::GLenum gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases_xfb[] = { 2768 GL_POINTS, GL_LINES, GL_LINES, GL_LINES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES 2769 }; 2770 2771 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_element_indices_counts[] = { 4, 4, 4, 4, 2772 6, 4, 4 }; 2773 2774 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_framebuffer_size = 2775 2; /* If you change this, update checkFramebuffer function according. */ 2776 2777 const glw::GLfloat gl3cts::TransformFeedback::CaptureVertexInterleaved::s_rasterization_epsilon = 0.0625; 2778 2779 /*-----------------------------------------------------------------------------------------------*/ 2780 2781 gl3cts::TransformFeedback::CaptureGeometryInterleaved::CaptureGeometryInterleaved(deqp::Context& context, 2782 const char* test_name, 2783 const char* test_description) 2784 : CaptureVertexInterleaved(context, test_name, test_description) 2785 { 2786 } 2787 2788 gl3cts::TransformFeedback::CaptureGeometryInterleaved::~CaptureGeometryInterleaved(void) 2789 { 2790 } 2791 2792 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureGeometryInterleaved::iterate(void) 2793 { 2794 /* Functions handler */ 2795 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2796 2797 /* Initializations. */ 2798 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0))); 2799 bool is_at_least_gl_32 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 2))); 2800 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback"); 2801 bool is_arb_gs_4 = m_context.getContextInfo().isExtensionSupported("GL_ARB_geometry_shader4"); 2802 2803 bool is_ok = true; 2804 bool test_error = false; 2805 2806 /* Tests. */ 2807 try 2808 { 2809 if ((is_at_least_gl_30 || is_ext_tf_1) && (is_at_least_gl_32 || is_arb_gs_4)) 2810 { 2811 fetchLimits(); 2812 createFramebuffer(); 2813 createTransformFeedbackBuffer(); 2814 createVertexArrayObject(); 2815 2816 for (glw::GLuint i_primitive_case = 0; 2817 (i_primitive_case < s_geometry_interleaved_primitive_cases_count) && is_ok; ++i_primitive_case) 2818 { 2819 buildProgram(i_primitive_case); 2820 2821 gl.useProgram(m_program); 2822 2823 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 2824 2825 for (glw::GLint i_bind_case = 0; (i_bind_case < BIND_BUFFER_CASES_COUNT) && is_ok; ++i_bind_case) 2826 { 2827 if ((i_bind_case == BIND_BUFFER_OFFSET_CASE) && (DE_NULL == m_glBindBufferOffsetEXT)) 2828 { 2829 continue; 2830 } 2831 2832 bindBuffer((BindBufferCase)i_bind_case); 2833 2834 draw(i_primitive_case); 2835 2836 is_ok = is_ok && checkFramebuffer(s_primitive_cases[i_primitive_case]); 2837 is_ok = is_ok && 2838 checkTransformFeedbackBuffer((BindBufferCase)i_bind_case, 2839 s_geometry_interleaved_primitive_cases_xfb[i_primitive_case]); 2840 } 2841 2842 gl.deleteProgram(m_program); 2843 2844 m_program = 0; 2845 2846 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram call failed."); 2847 } 2848 } 2849 } 2850 catch (...) 2851 { 2852 is_ok = false; 2853 test_error = true; 2854 } 2855 2856 /* Clean objects. */ 2857 clean(); 2858 2859 /* Result's setup. */ 2860 if (is_ok) 2861 { 2862 /* Log success. */ 2863 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Geometry have passed." 2864 << tcu::TestLog::EndMessage; 2865 2866 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2867 } 2868 else 2869 { 2870 if (test_error) 2871 { 2872 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 2873 } 2874 else 2875 { 2876 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2877 } 2878 } 2879 2880 return STOP; 2881 } 2882 2883 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::fetchLimits(void) 2884 { 2885 /* Functions handler */ 2886 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2887 2888 /* Fetching limits. */ 2889 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_transform_feedback_components); 2890 2891 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2892 2893 if (m_max_transform_feedback_components == 0) 2894 { 2895 throw 0; 2896 } 2897 2898 glw::GLint max_geometry_total_components = 0; 2899 2900 gl.getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &max_geometry_total_components); 2901 2902 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 2903 2904 if (max_geometry_total_components == 0) 2905 { 2906 throw 0; 2907 } 2908 2909 if (m_max_transform_feedback_components * 4 > max_geometry_total_components) 2910 { 2911 m_max_transform_feedback_components = max_geometry_total_components / 4; 2912 } 2913 } 2914 2915 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::buildProgram(glw::GLuint primitive_case) 2916 { 2917 /* Functions handler */ 2918 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2919 2920 /* Preparing source code. */ 2921 std::string geometry_shader(s_geometry_shader_source_code_template); /* Storage for vertex shader source code. */ 2922 std::string transform_feedback_variable_declarations( 2923 ""); /* String to contain all custom outputs from vertex shader. */ 2924 std::string transform_feedback_variable_setters( 2925 ""); /* String containing all initializations of custom outputs from vertex shader. */ 2926 std::vector<std::string> transform_feedback_varyings(m_max_transform_feedback_components); /* Varyings array. */ 2927 std::vector<const glw::GLchar*> transform_feedback_varyings_c( 2928 m_max_transform_feedback_components); /* Varyings array in C form to pass to the GL. */ 2929 2930 glw::GLint user_defined_transform_feedback_interleaved_varyings_count = 2931 m_max_transform_feedback_components /* total max to be written by the shader */ 2932 / 4 /* components per vec4 */ 2933 // / 4 /* number of vertices */ 2934 - 1 /* gl_Position */; 2935 2936 glw::GLint all_transform_feedback_interleaved_varyings_count = 2937 user_defined_transform_feedback_interleaved_varyings_count + 1 /* gl_Position */; 2938 2939 /* Most of varyings is declarated output variables. */ 2940 for (glw::GLint i = 0; i < user_defined_transform_feedback_interleaved_varyings_count; ++i) 2941 { 2942 /* Preparing variable name. */ 2943 std::string varying = "result_"; 2944 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i)); 2945 2946 transform_feedback_varyings[i] = varying; 2947 2948 transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str(); 2949 2950 /* Preparing variable declaration. */ 2951 transform_feedback_variable_declarations.append("out vec4 "); 2952 transform_feedback_variable_declarations.append(varying); 2953 transform_feedback_variable_declarations.append(";\n"); 2954 2955 /* Preparing variable setters. */ 2956 transform_feedback_variable_setters.append(" "); 2957 transform_feedback_variable_setters.append(varying); 2958 transform_feedback_variable_setters.append(" = vec4("); 2959 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4)); 2960 transform_feedback_variable_setters.append(".0, "); 2961 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 1)); 2962 transform_feedback_variable_setters.append(".0, "); 2963 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 2)); 2964 transform_feedback_variable_setters.append(".0, "); 2965 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 3)); 2966 transform_feedback_variable_setters.append(".0);\n"); 2967 } 2968 2969 /* Last four varying components are gl_Position components. */ 2970 transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */] = 2971 "gl_Position"; 2972 2973 transform_feedback_varyings_c[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */] = 2974 transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */] 2975 .c_str(); 2976 2977 /* Preprocess vertex shader source code template. */ 2978 geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 2979 geometry_shader, "TEMPLATE_PRIMITIVE_TYPE", s_geometry_interleaved_primitive_cases[primitive_case]); 2980 geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 2981 geometry_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations); 2982 geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(geometry_shader, "TEMPLATE_OUTPUT_SETTERS", 2983 transform_feedback_variable_setters); 2984 geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode( 2985 geometry_shader, "TEMPLATE_RASTERIZATION_EPSILON", 2986 gl3cts::TransformFeedback::Utilities::ftoa(s_rasterization_epsilon)); 2987 2988 /* Compile, link and check. */ 2989 m_program = gl3cts::TransformFeedback::Utilities::buildProgram( 2990 gl, m_context.getTestContext().getLog(), geometry_shader.c_str(), NULL, NULL, s_blank_vertex_shader_source_code, 2991 s_fragment_shader_source_code, &transform_feedback_varyings_c[0], 2992 all_transform_feedback_interleaved_varyings_count, m_attrib_type); 2993 2994 if (0 == m_program) 2995 { 2996 throw 0; 2997 } 2998 } 2999 3000 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(glw::GLuint primitive_case) 3001 { 3002 /* Functions handler */ 3003 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3004 3005 gl.clear(GL_COLOR_BUFFER_BIT); 3006 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 3007 3008 gl.beginTransformFeedback(s_geometry_interleaved_primitive_cases_xfb[primitive_case]); 3009 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 3010 3011 gl.drawArrays(GL_POINTS, 0, 1); 3012 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 3013 3014 gl.endTransformFeedback(); 3015 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedbac call failed."); 3016 } 3017 3018 const glw::GLchar* gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_shader_source_code_template = 3019 "#version 150\n" 3020 "\n" 3021 "layout(points) in;\n" 3022 "layout(TEMPLATE_PRIMITIVE_TYPE, max_vertices = 4) out;\n" 3023 "\n" 3024 "TEMPLATE_INPUT_OUTPUT_DECLARATIONS" 3025 "\n" 3026 "void main()\n" 3027 "{\n" 3028 " /* Note: The points are moved 0.0625 from the borders to\n" 3029 " reduce non-XFB related rasterization problems. */\n" 3030 "\n" 3031 " gl_Position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 3032 "1.0);\n" 3033 "TEMPLATE_OUTPUT_SETTERS" 3034 " EmitVertex();\n" 3035 "\n" 3036 " gl_Position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 3037 "1.0);\n" 3038 "TEMPLATE_OUTPUT_SETTERS" 3039 " EmitVertex();\n" 3040 "\n" 3041 " gl_Position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 3042 "1.0);\n" 3043 "TEMPLATE_OUTPUT_SETTERS" 3044 " EmitVertex();\n" 3045 "\n" 3046 " gl_Position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON, 0.0, " 3047 "1.0);\n" 3048 "TEMPLATE_OUTPUT_SETTERS" 3049 " EmitVertex();\n" 3050 "}\n"; 3051 3052 const glw::GLchar* gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_blank_vertex_shader_source_code = 3053 "#version 130\n" 3054 "\n" 3055 "void main()\n" 3056 "{\n" 3057 "}\n"; 3058 3059 const glw::GLchar* gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases[] = { 3060 "points", "line_strip", "triangle_strip" 3061 }; 3062 3063 const glw::GLenum gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases_xfb[] = 3064 { GL_POINTS, GL_LINES, GL_TRIANGLES }; 3065 3066 const glw::GLuint gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases_count = 3067 sizeof(s_geometry_interleaved_primitive_cases) / sizeof(s_geometry_interleaved_primitive_cases[0]); 3068 3069 /*-----------------------------------------------------------------------------------------------*/ 3070 3071 gl3cts::TransformFeedback::CaptureVertexSeparate::CaptureVertexSeparate(deqp::Context& context, const char* test_name, 3072 const char* test_description) 3073 : CaptureVertexInterleaved(context, test_name, test_description) 3074 , m_buffers(DE_NULL) 3075 , m_max_transform_feedback_separate_attribs(0) 3076 { 3077 m_attrib_type = GL_SEPARATE_ATTRIBS; 3078 } 3079 3080 void gl3cts::TransformFeedback::CaptureVertexSeparate::fetchLimits(void) 3081 { 3082 /* Functions handler */ 3083 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3084 3085 /* Fetching limits. */ 3086 glw::GLint max_transform_feedback_separate_components; 3087 3088 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components); 3089 3090 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 3091 3092 if (max_transform_feedback_separate_components < 4) 3093 { 3094 throw 0; 3095 } 3096 3097 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_max_transform_feedback_separate_attribs); 3098 3099 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 3100 3101 if (m_max_transform_feedback_separate_attribs == 0) 3102 { 3103 throw 0; 3104 } 3105 3106 m_max_transform_feedback_components = m_max_transform_feedback_separate_attribs * 4 /* vec4 is used */; 3107 3108 glw::GLint max_varyings_components = 0; 3109 3110 gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings_components); 3111 3112 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 3113 3114 if (max_varyings_components == 0) 3115 { 3116 throw 0; 3117 } 3118 3119 if (m_max_transform_feedback_components > max_varyings_components) 3120 { 3121 m_max_transform_feedback_components = max_varyings_components; 3122 } 3123 } 3124 3125 void gl3cts::TransformFeedback::CaptureVertexSeparate::createTransformFeedbackBuffer(void) 3126 { 3127 /* Functions handler */ 3128 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3129 3130 m_buffers = new glw::GLuint[m_max_transform_feedback_components]; 3131 3132 if (DE_NULL == m_buffers) 3133 { 3134 throw 0; 3135 } 3136 3137 gl.genBuffers(m_max_transform_feedback_separate_attribs, m_buffers); 3138 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 3139 3140 m_buffer_size = static_cast<glw::GLuint>(m_max_vertices_drawn * 4 /* vec4 */ * sizeof(glw::GLfloat)); 3141 3142 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i) 3143 { 3144 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[i]); 3145 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 3146 3147 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_size, NULL, GL_DYNAMIC_READ); 3148 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 3149 } 3150 } 3151 3152 void gl3cts::TransformFeedback::CaptureVertexSeparate::bindBuffer(BindBufferCase bind_case) 3153 { 3154 /* Functions handler */ 3155 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3156 3157 switch (bind_case) 3158 { 3159 case BIND_BUFFER_BASE_CASE: 3160 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i) 3161 { 3162 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i]); 3163 } 3164 break; 3165 case BIND_BUFFER_RANGE_CASE: 3166 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i) 3167 { 3168 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i], 0, m_buffer_size); 3169 } 3170 break; 3171 case BIND_BUFFER_OFFSET_CASE: 3172 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i) 3173 { 3174 m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i], 0); 3175 } 3176 break; 3177 default: 3178 throw 0; 3179 } 3180 } 3181 3182 void gl3cts::TransformFeedback::CaptureVertexSeparate::cleanBuffer(void) 3183 { 3184 /* Functions handler */ 3185 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3186 3187 if (DE_NULL != m_buffers) 3188 { 3189 gl.deleteBuffers(m_max_transform_feedback_separate_attribs, m_buffers); 3190 3191 delete[] m_buffers; 3192 3193 m_buffers = DE_NULL; 3194 } 3195 } 3196 3197 bool gl3cts::TransformFeedback::CaptureVertexSeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED, 3198 glw::GLenum primitive_type) 3199 { 3200 /* Functions handler */ 3201 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3202 3203 glw::GLuint number_of_vertices = 0; 3204 3205 switch (primitive_type) 3206 { 3207 case GL_POINTS: 3208 number_of_vertices = 4; 3209 break; 3210 case GL_LINES: 3211 number_of_vertices = 4; 3212 break; 3213 case GL_LINE_LOOP: 3214 number_of_vertices = 8; 3215 break; 3216 case GL_LINE_STRIP: 3217 number_of_vertices = 6; 3218 break; 3219 case GL_TRIANGLES: 3220 number_of_vertices = 6; 3221 break; 3222 case GL_TRIANGLE_STRIP: 3223 number_of_vertices = 6; 3224 break; 3225 case GL_TRIANGLE_FAN: 3226 number_of_vertices = 6; 3227 break; 3228 default: 3229 throw 0; 3230 } 3231 3232 bool is_ok = true; 3233 3234 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs - 1; ++i) 3235 { 3236 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[i]); 3237 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 3238 3239 glw::GLfloat* results = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 3240 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed."); 3241 3242 for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j) 3243 { 3244 for (glw::GLuint k = 0; k < 4 /* vec4 */; ++k) 3245 { 3246 glw::GLfloat result = results[j * 4 + k]; 3247 glw::GLfloat reference = (glw::GLfloat)(i * 4 + k); 3248 3249 if (fabs(result - reference) > 0.125 /* precision */) 3250 { 3251 is_ok = false; 3252 3253 break; 3254 } 3255 } 3256 } 3257 3258 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 3259 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 3260 } 3261 3262 /* gl_Position */ 3263 if (is_ok) 3264 { 3265 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[m_max_transform_feedback_separate_attribs - 1]); 3266 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 3267 3268 glw::GLfloat* results = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); 3269 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed."); 3270 3271 for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j) 3272 { 3273 glw::GLfloat result[4] = { results[j * 4], results[j * 4 + 1], results[j * 4 + 2], results[j * 4 + 3] }; 3274 3275 if ((fabs(fabs(result[0]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) || 3276 (fabs(fabs(result[1]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) || 3277 (fabs(result[2]) > 0.125 /* precision */) || (fabs(result[3] - 1.0) > 0.125 /* precision */)) 3278 { 3279 is_ok = false; 3280 3281 break; 3282 } 3283 } 3284 3285 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 3286 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 3287 } 3288 3289 return is_ok; 3290 } 3291 3292 /*-----------------------------------------------------------------------------------------------*/ 3293 3294 gl3cts::TransformFeedback::CaptureGeometrySeparate::CaptureGeometrySeparate(deqp::Context& context, 3295 const char* test_name, 3296 const char* test_description) 3297 : CaptureVertexInterleaved(context, test_name, test_description) 3298 , CaptureVertexSeparate(context, test_name, test_description) 3299 , CaptureGeometryInterleaved(context, test_name, test_description) 3300 , m_buffers(DE_NULL) 3301 , m_max_transform_feedback_separate_attribs(0) 3302 { 3303 } 3304 3305 /*-----------------------------------------------------------------------------------------------*/ 3306 3307 gl3cts::TransformFeedback::CheckGetXFBVarying::CheckGetXFBVarying(deqp::Context& context, const char* test_name, 3308 const char* test_description) 3309 : deqp::TestCase(context, test_name, test_description) 3310 , m_context(context) 3311 , m_max_xfb_interleaved_components(0) 3312 , m_max_xfb_separate_attributes(0) 3313 , m_max_xfb_separate_components(0) 3314 , m_max_varying_components(0) 3315 , m_max_varying_vectors(0) 3316 , m_max_geometry_total_output_components(0) 3317 { 3318 } 3319 3320 gl3cts::TransformFeedback::CheckGetXFBVarying::~CheckGetXFBVarying(void) 3321 { 3322 } 3323 3324 void gl3cts::TransformFeedback::CheckGetXFBVarying::fetchLimits(void) 3325 { 3326 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3327 3328 /* Fetching limits. */ 3329 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_xfb_interleaved_components); 3330 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_max_xfb_separate_attributes); 3331 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &m_max_xfb_separate_components); 3332 gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &m_max_varying_components); 3333 gl.getIntegerv(GL_MAX_VARYING_VECTORS, &m_max_varying_vectors); 3334 gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &m_max_geometry_total_output_components); 3335 3336 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 3337 } 3338 3339 glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::numberOfAttributes(glw::GLuint capture_way, 3340 glw::GLuint shader_case, 3341 glw::GLuint varying_type) 3342 { 3343 /* Setup limits of the case. */ 3344 const glw::GLuint max_total_components = 3345 ((s_shader_cases[shader_case].geometry_shader == DE_NULL) ? m_max_varying_components : 3346 m_max_geometry_total_output_components) - 3347 4 /* gl_Position is not captured */; 3348 3349 const glw::GLuint attribute_components = s_varying_types[varying_type].components_count; 3350 const glw::GLuint max_xfb_components = (s_capture_ways[capture_way] == GL_INTERLEAVED_ATTRIBS) ? 3351 m_max_xfb_interleaved_components : 3352 (attribute_components * m_max_xfb_separate_components); 3353 3354 if (s_capture_ways[capture_way] == GL_SEPARATE_ATTRIBS) 3355 { 3356 if (attribute_components > glw::GLuint(m_max_xfb_separate_components)) 3357 { 3358 return 0; 3359 } 3360 } 3361 3362 /* Setup number of attributes. */ 3363 glw::GLuint number_of_attributes = max_xfb_components / attribute_components; 3364 3365 if (s_capture_ways[capture_way] == GL_SEPARATE_ATTRIBS && 3366 number_of_attributes > glw::GLuint(m_max_xfb_separate_attributes)) 3367 { 3368 number_of_attributes = m_max_xfb_separate_attributes; 3369 } 3370 3371 /* Clamp to limits. */ 3372 if (number_of_attributes * attribute_components > max_total_components) 3373 { 3374 number_of_attributes = max_total_components / attribute_components; 3375 } 3376 3377 /* Vectors limit. */ 3378 if (attribute_components <= 4) 3379 { 3380 if (number_of_attributes > glw::GLuint(m_max_varying_vectors)) 3381 { 3382 number_of_attributes = m_max_varying_vectors; 3383 } 3384 } 3385 else 3386 { 3387 if (number_of_attributes > glw::GLuint(m_max_varying_vectors) / 4) 3388 { 3389 number_of_attributes = glw::GLuint(m_max_varying_vectors) / 4; 3390 } 3391 } 3392 3393 /* Return. */ 3394 return number_of_attributes; 3395 } 3396 3397 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CheckGetXFBVarying::iterate(void) 3398 { 3399 /* Functions handler */ 3400 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3401 3402 /* Initializations. */ 3403 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0))); 3404 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback"); 3405 3406 bool is_ok = true; 3407 bool test_error = false; 3408 3409 glw::GLuint program = 0; 3410 3411 /* Tests. */ 3412 try 3413 { 3414 if (is_at_least_gl_30 || is_ext_tf_1) 3415 { 3416 fetchLimits(); 3417 3418 for (glw::GLuint i = 0; (i < s_capture_ways_count) && is_ok; ++i) 3419 { 3420 for (glw::GLuint j = 0; (j < s_shader_cases_count) && is_ok; ++j) 3421 { 3422 for (glw::GLuint k = 0; (k < s_varying_types_count) && is_ok; ++k) 3423 { 3424 glw::GLuint n = numberOfAttributes(i, j, k); 3425 3426 if (n) 3427 { 3428 program = buildProgram(i, j, k, n); 3429 3430 is_ok = is_ok && (program != 0); 3431 3432 is_ok = is_ok && check(program, i, j, k, n); 3433 3434 gl.deleteProgram(program); 3435 3436 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram call failed."); 3437 3438 program = 0; 3439 } 3440 } 3441 } 3442 } 3443 } 3444 } 3445 catch (...) 3446 { 3447 is_ok = false; 3448 test_error = true; 3449 3450 if (program) 3451 { 3452 gl.deleteProgram(program); 3453 3454 program = 0; 3455 } 3456 } 3457 3458 /* Result's setup. */ 3459 if (is_ok) 3460 { 3461 /* Log success. */ 3462 m_context.getTestContext().getLog() << tcu::TestLog::Message 3463 << "Test checking Get Transform Feedback Varying have passed." 3464 << tcu::TestLog::EndMessage; 3465 3466 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3467 } 3468 else 3469 { 3470 if (test_error) 3471 { 3472 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 3473 } 3474 else 3475 { 3476 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 3477 } 3478 } 3479 3480 return STOP; 3481 } 3482 3483 glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::buildProgram(glw::GLuint capture_way, 3484 glw::GLuint shader_case, 3485 glw::GLuint varying_type, 3486 glw::GLuint number_of_attributes) 3487 { 3488 /* Functions handler */ 3489 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3490 3491 /* Preparing source code. */ 3492 std::string xfb_variable_declarations(""); 3493 std::string xfb_variable_setters(""); 3494 std::vector<std::string> xfb_varyings(number_of_attributes); 3495 std::vector<const glw::GLchar*> xfb_varyings_c(number_of_attributes); 3496 3497 /* Most of varyings is declarated output variables. */ 3498 for (glw::GLuint i = 0; i < number_of_attributes; ++i) 3499 { 3500 /* Varying name: result_# */ 3501 std::string varying = "result_"; 3502 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i)); 3503 3504 xfb_varyings[i] = varying; 3505 xfb_varyings_c[i] = xfb_varyings[i].c_str(); 3506 3507 /* Varying declaration: out TYPE result_#;*/ 3508 xfb_variable_declarations.append("out "); 3509 xfb_variable_declarations.append(s_varying_types[varying_type].name); 3510 xfb_variable_declarations.append(" "); 3511 xfb_variable_declarations.append(varying); 3512 xfb_variable_declarations.append(";\n"); 3513 3514 /* Varying setter: result_# = TYPE(#); */ 3515 xfb_variable_setters.append(" "); 3516 xfb_variable_setters.append(varying); 3517 xfb_variable_setters.append(" = "); 3518 xfb_variable_setters.append(s_varying_types[varying_type].name); 3519 xfb_variable_setters.append("("); 3520 xfb_variable_setters.append("2"); //gl3cts::TransformFeedback::Utilities::itoa(i)); 3521 if (s_varying_types[varying_type].float_component) 3522 { 3523 /* if varying is float varying setter is: result_# = TYPE(#.0); */ 3524 xfb_variable_setters.append(".0"); 3525 } 3526 xfb_variable_setters.append(");\n"); 3527 } 3528 3529 /* Preprocess vertex shader source code template. */ 3530 const glw::GLchar* vertex_shader = s_shader_cases[shader_case].vertex_shader; 3531 const glw::GLchar* geometry_shader = s_shader_cases[shader_case].geometry_shader; 3532 3533 std::string xfb_shader; 3534 3535 if (DE_NULL == s_shader_cases[shader_case].geometry_shader) 3536 { 3537 /* XFB tested in vertex shader. */ 3538 xfb_shader = vertex_shader; 3539 } 3540 else 3541 { 3542 /* XFB tested in geometry shader. */ 3543 xfb_shader = geometry_shader; 3544 } 3545 3546 /* Preprocess shader. */ 3547 xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_DECLARATIONS", 3548 xfb_variable_declarations); 3549 xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_SETTERS", 3550 xfb_variable_setters); 3551 3552 if (DE_NULL == s_shader_cases[shader_case].geometry_shader) 3553 { 3554 /* XFB tested in vertex shader. */ 3555 vertex_shader = xfb_shader.c_str(); 3556 } 3557 else 3558 { 3559 /* XFB tested in geometry shader. */ 3560 geometry_shader = xfb_shader.c_str(); 3561 } 3562 3563 /* Compile, link and check. */ 3564 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram( 3565 gl, m_context.getTestContext().getLog(), geometry_shader, NULL, NULL, vertex_shader, s_generic_fragment_shader, 3566 &xfb_varyings_c[0], number_of_attributes, s_capture_ways[capture_way]); 3567 3568 /* Check compilation status. */ 3569 if (0 == program) 3570 { 3571 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Building program has failed.\nVertex shader:\n" 3572 << vertex_shader << "Geometry shader:\n" 3573 << ((DE_NULL == geometry_shader) ? "" : geometry_shader) 3574 << "Fragment shader:\n" 3575 << s_generic_fragment_shader << tcu::TestLog::EndMessage; 3576 3577 throw 0; 3578 } 3579 3580 return program; 3581 } 3582 3583 bool gl3cts::TransformFeedback::CheckGetXFBVarying::check(glw::GLuint program, glw::GLuint capture_way, 3584 glw::GLuint shader_case UNUSED, glw::GLuint varying_type, 3585 glw::GLuint number_of_attributes) 3586 { 3587 /* Functions handler */ 3588 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3589 glw::GLuint max_length = 0; 3590 3591 /* Inspect glGetTransformFeedbackVarying. */ 3592 for (glw::GLuint i = 0; i < number_of_attributes; ++i) 3593 { 3594 const glw::GLsizei bufSize = 18; 3595 glw::GLsizei length = 0; 3596 glw::GLsizei size = 0; 3597 glw::GLenum type = GL_NONE; 3598 glw::GLchar name[18] = { 0 }; /* Size of bufSize. */ 3599 3600 gl.getTransformFeedbackVarying(program, i, bufSize, &length, &size, &type, name); 3601 3602 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbackVarying call failed."); 3603 3604 max_length = deMaxu32(max_length, glw::GLuint(length)); 3605 3606 /* Check name. */ 3607 if (length) 3608 { 3609 std::string varying = name; 3610 std::string varying_ref = "result_"; 3611 varying_ref.append(gl3cts::TransformFeedback::Utilities::itoa(i)); 3612 3613 if (0 != varying.compare(varying_ref)) 3614 { 3615 return false; 3616 } 3617 } 3618 else 3619 { 3620 return false; 3621 } 3622 3623 /* Check size. */ 3624 const glw::GLuint size_ref = 1; 3625 3626 if (size != size_ref) 3627 { 3628 return false; 3629 } 3630 3631 /* Check type. */ 3632 if (type != s_varying_types[varying_type].type) 3633 { 3634 return false; 3635 } 3636 } 3637 3638 /* Inspect glGetProgramiv. */ 3639 glw::GLint xfb_varyings = 0; 3640 glw::GLint xfb_mode = 0; 3641 glw::GLint xfb_varying_max_length = 0; 3642 3643 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &xfb_varyings); 3644 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, &xfb_mode); 3645 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &xfb_varying_max_length); 3646 3647 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed."); 3648 3649 if (glw::GLuint(xfb_varyings) != number_of_attributes) 3650 { 3651 return false; 3652 } 3653 3654 if (glw::GLenum(xfb_mode) != s_capture_ways[capture_way]) 3655 { 3656 return false; 3657 } 3658 3659 if (glw::GLuint(xfb_varying_max_length) < max_length) 3660 { 3661 return false; 3662 } 3663 3664 return true; 3665 } 3666 3667 const glw::GLchar* gl3cts::TransformFeedback::CheckGetXFBVarying::s_generic_fragment_shader = "#version 130\n" 3668 "\n" 3669 "out vec4 color;\n" 3670 "\n" 3671 "void main()\n" 3672 "{\n" 3673 " color = vec4(1.0);\n" 3674 "}\n"; 3675 3676 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::ShaderCase 3677 gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases[] = { { /* Vertex Shader. */ 3678 "#version 130\n" 3679 "\n" 3680 "TEMPLATE_OUTPUT_DECLARATIONS" 3681 "\n" 3682 "void main()\n" 3683 "{\n" 3684 " gl_Position = vec4(1.0);\n" 3685 "TEMPLATE_OUTPUT_SETTERS" 3686 "}\n", 3687 3688 /* Geometry Shader. */ 3689 NULL }, 3690 { /* Vertex Shader. */ 3691 "#version 130\n" 3692 "\n" 3693 "void main()\n" 3694 "{\n" 3695 "}\n", 3696 3697 /* Geometry Shader. */ 3698 "#version 150\n" 3699 "\n" 3700 "layout(points) in;\n" 3701 "layout(points, max_vertices = 1) out;\n" 3702 "\n" 3703 "TEMPLATE_OUTPUT_DECLARATIONS" 3704 "\n" 3705 "void main()\n" 3706 "{\n" 3707 " gl_Position = vec4(1.0);\n" 3708 "TEMPLATE_OUTPUT_SETTERS" 3709 " EmitVertex();\n" 3710 "}\n" } }; 3711 3712 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases_count = 3713 sizeof(s_shader_cases) / sizeof(s_shader_cases[0]); 3714 3715 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::VaryingType 3716 gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types[] = { 3717 /* type, name, #components, is component float */ 3718 { GL_FLOAT, "float", 1, true }, 3719 { GL_FLOAT_VEC2, "vec2", 2, true }, 3720 { GL_FLOAT_VEC3, "vec3", 3, true }, 3721 { GL_FLOAT_VEC4, "vec4", 4, true }, 3722 { GL_INT, "int", 1, false }, 3723 { GL_INT_VEC2, "ivec2", 2, false }, 3724 { GL_INT_VEC3, "ivec3", 3, false }, 3725 { GL_INT_VEC4, "ivec4", 4, false }, 3726 { GL_UNSIGNED_INT, "uint", 1, false }, 3727 { GL_UNSIGNED_INT_VEC2, "uvec2", 2, false }, 3728 { GL_UNSIGNED_INT_VEC3, "uvec3", 3, false }, 3729 { GL_UNSIGNED_INT_VEC4, "uvec4", 4, false }, 3730 { GL_FLOAT_MAT2, "mat2", 4, true }, 3731 { GL_FLOAT_MAT3, "mat3", 9, true }, 3732 { GL_FLOAT_MAT4, "mat4", 16, true } 3733 }; 3734 3735 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types_count = 3736 sizeof(s_varying_types) / sizeof(s_varying_types[0]); 3737 3738 const glw::GLenum gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways[] = { GL_INTERLEAVED_ATTRIBS, 3739 GL_SEPARATE_ATTRIBS }; 3740 3741 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways_count = 3742 sizeof(s_capture_ways) / sizeof(s_capture_ways[0]); 3743 3744 /*-----------------------------------------------------------------------------------------------*/ 3745 3746 gl3cts::TransformFeedback::QueryVertexInterleaved::QueryVertexInterleaved(deqp::Context& context, const char* test_name, 3747 const char* test_description) 3748 : CaptureVertexInterleaved(context, test_name, test_description), m_query_object(0) 3749 { 3750 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */ 3751 } 3752 3753 void gl3cts::TransformFeedback::QueryVertexInterleaved::createTransformFeedbackBuffer(void) 3754 { 3755 /* Functions handler */ 3756 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3757 3758 /* Create buffer object. */ 3759 gl3cts::TransformFeedback::CaptureVertexInterleaved::createTransformFeedbackBuffer(); 3760 3761 /* Create query object. */ 3762 gl.genQueries(1, &m_query_object); 3763 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed."); 3764 } 3765 3766 void gl3cts::TransformFeedback::QueryVertexInterleaved::draw(glw::GLuint primitive_case) 3767 { 3768 /* Functions handler */ 3769 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3770 3771 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object); 3772 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed."); 3773 3774 gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case); 3775 3776 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); 3777 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed."); 3778 } 3779 3780 bool gl3cts::TransformFeedback::QueryVertexInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED, 3781 glw::GLenum primitive_type) 3782 { 3783 /* Functions handler */ 3784 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3785 3786 glw::GLuint number_of_primitives; 3787 3788 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives); 3789 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed."); 3790 3791 /* expected result */ 3792 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */ 3793 3794 if (number_of_primitives_reference != number_of_primitives) 3795 { 3796 return false; 3797 } 3798 3799 return true; 3800 } 3801 3802 void gl3cts::TransformFeedback::QueryVertexInterleaved::clean(void) 3803 { 3804 /* Functions handler */ 3805 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3806 3807 /* Delete query object. */ 3808 gl.deleteQueries(1, &m_query_object); 3809 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed."); 3810 3811 /* Other */ 3812 gl3cts::TransformFeedback::CaptureVertexInterleaved::clean(); 3813 } 3814 3815 /*-----------------------------------------------------------------------------------------------*/ 3816 3817 gl3cts::TransformFeedback::QueryGeometryInterleaved::QueryGeometryInterleaved(deqp::Context& context, 3818 const char* test_name, 3819 const char* test_description) 3820 : CaptureVertexInterleaved(context, test_name, test_description) 3821 , CaptureGeometryInterleaved(context, test_name, test_description) 3822 { 3823 m_query_object = 0; 3824 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */ 3825 } 3826 3827 void gl3cts::TransformFeedback::QueryGeometryInterleaved::createTransformFeedbackBuffer(void) 3828 { 3829 /* Functions handler */ 3830 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3831 3832 /* Create buffer object. */ 3833 gl3cts::TransformFeedback::CaptureGeometryInterleaved::createTransformFeedbackBuffer(); 3834 3835 /* Create query object. */ 3836 gl.genQueries(1, &m_query_object); 3837 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed."); 3838 } 3839 3840 void gl3cts::TransformFeedback::QueryGeometryInterleaved::draw(glw::GLuint primitive_case) 3841 { 3842 /* Functions handler */ 3843 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3844 3845 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object); 3846 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed."); 3847 3848 gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case); 3849 3850 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); 3851 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed."); 3852 } 3853 3854 bool gl3cts::TransformFeedback::QueryGeometryInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED, 3855 glw::GLenum primitive_type) 3856 { 3857 /* Functions handler */ 3858 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3859 3860 glw::GLuint number_of_primitives; 3861 3862 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives); 3863 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed."); 3864 3865 /* expected result */ 3866 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */ 3867 3868 if (number_of_primitives_reference != number_of_primitives) 3869 { 3870 return false; 3871 } 3872 3873 return true; 3874 } 3875 3876 void gl3cts::TransformFeedback::QueryGeometryInterleaved::clean(void) 3877 { 3878 /* Functions handler */ 3879 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3880 3881 /* Delete query object. */ 3882 gl.deleteQueries(1, &m_query_object); 3883 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed."); 3884 3885 /* Other. */ 3886 gl3cts::TransformFeedback::CaptureGeometryInterleaved::clean(); 3887 } 3888 3889 /*-----------------------------------------------------------------------------------------------*/ 3890 3891 gl3cts::TransformFeedback::QueryVertexSeparate::QueryVertexSeparate(deqp::Context& context, const char* test_name, 3892 const char* test_description) 3893 : CaptureVertexInterleaved(context, test_name, test_description) 3894 , CaptureVertexSeparate(context, test_name, test_description) 3895 { 3896 m_query_object = 0; 3897 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */ 3898 } 3899 3900 void gl3cts::TransformFeedback::QueryVertexSeparate::createTransformFeedbackBuffer(void) 3901 { 3902 /* Functions handler */ 3903 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3904 3905 /* Create buffer object. */ 3906 gl3cts::TransformFeedback::CaptureVertexSeparate::createTransformFeedbackBuffer(); 3907 3908 /* Create query object. */ 3909 gl.genQueries(1, &m_query_object); 3910 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed."); 3911 } 3912 3913 void gl3cts::TransformFeedback::QueryVertexSeparate::draw(glw::GLuint primitive_case) 3914 { 3915 /* Functions handler */ 3916 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3917 3918 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object); 3919 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed."); 3920 3921 gl3cts::TransformFeedback::CaptureVertexSeparate::draw(primitive_case); 3922 3923 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); 3924 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed."); 3925 } 3926 3927 bool gl3cts::TransformFeedback::QueryVertexSeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED, 3928 glw::GLenum primitive_type) 3929 { 3930 /* Functions handler */ 3931 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3932 3933 glw::GLuint number_of_primitives; 3934 3935 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives); 3936 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed."); 3937 3938 /* expected result */ 3939 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */ 3940 3941 if (number_of_primitives_reference != number_of_primitives) 3942 { 3943 return false; 3944 } 3945 3946 return true; 3947 } 3948 3949 void gl3cts::TransformFeedback::QueryVertexSeparate::clean(void) 3950 { 3951 /* Functions handler */ 3952 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3953 3954 /* Delete query object. */ 3955 gl.deleteQueries(1, &m_query_object); 3956 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed."); 3957 3958 /* Other */ 3959 gl3cts::TransformFeedback::CaptureVertexSeparate::clean(); 3960 } 3961 3962 /*-----------------------------------------------------------------------------------------------*/ 3963 3964 gl3cts::TransformFeedback::QueryGeometrySeparate::QueryGeometrySeparate(deqp::Context& context, const char* test_name, 3965 const char* test_description) 3966 : CaptureVertexInterleaved(context, test_name, test_description) 3967 , CaptureVertexSeparate(context, test_name, test_description) 3968 , CaptureGeometrySeparate(context, test_name, test_description) 3969 { 3970 m_query_object = 0; 3971 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */ 3972 } 3973 3974 void gl3cts::TransformFeedback::QueryGeometrySeparate::createTransformFeedbackBuffer(void) 3975 { 3976 /* Functions handler */ 3977 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3978 3979 /* Create buffer object. */ 3980 gl3cts::TransformFeedback::CaptureGeometrySeparate::createTransformFeedbackBuffer(); 3981 3982 /* Create query object. */ 3983 gl.genQueries(1, &m_query_object); 3984 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed."); 3985 } 3986 3987 void gl3cts::TransformFeedback::QueryGeometrySeparate::draw(glw::GLuint primitive_case) 3988 { 3989 /* Functions handler */ 3990 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3991 3992 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object); 3993 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed."); 3994 3995 gl3cts::TransformFeedback::CaptureGeometrySeparate::draw(primitive_case); 3996 3997 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); 3998 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed."); 3999 } 4000 4001 bool gl3cts::TransformFeedback::QueryGeometrySeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED, 4002 glw::GLenum primitive_type) 4003 { 4004 /* Functions handler */ 4005 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4006 4007 glw::GLuint number_of_primitives; 4008 4009 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives); 4010 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed."); 4011 4012 /* expected result */ 4013 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */ 4014 4015 if (number_of_primitives_reference != number_of_primitives) 4016 { 4017 return false; 4018 } 4019 4020 return true; 4021 } 4022 4023 void gl3cts::TransformFeedback::QueryGeometrySeparate::clean(void) 4024 { 4025 /* Functions handler */ 4026 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4027 4028 /* Delete query object. */ 4029 gl.deleteQueries(1, &m_query_object); 4030 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed."); 4031 4032 /* Other */ 4033 gl3cts::TransformFeedback::CaptureGeometrySeparate::clean(); 4034 } 4035 4036 /*-----------------------------------------------------------------------------------------------*/ 4037 4038 gl3cts::TransformFeedback::DiscardVertex::DiscardVertex(deqp::Context& context, const char* test_name, 4039 const char* test_description) 4040 : CaptureVertexInterleaved(context, test_name, test_description) 4041 { 4042 } 4043 4044 void gl3cts::TransformFeedback::DiscardVertex::draw(glw::GLuint primitive_case) 4045 { 4046 /* Functions handler */ 4047 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4048 4049 /* Must clear before rasterizer discard */ 4050 gl.clear(GL_COLOR_BUFFER_BIT); 4051 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 4052 4053 gl.enable(GL_RASTERIZER_DISCARD); 4054 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 4055 4056 gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case); 4057 4058 gl.disable(GL_RASTERIZER_DISCARD); 4059 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 4060 } 4061 4062 bool gl3cts::TransformFeedback::DiscardVertex::checkFramebuffer(glw::GLuint primitive_case UNUSED) 4063 { 4064 /* Functions handler */ 4065 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4066 4067 /* Fetch framebuffer. */ 4068 std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size); 4069 4070 if ((s_framebuffer_size > 0) && (s_framebuffer_size > 0)) 4071 { 4072 gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data()); 4073 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 4074 } 4075 4076 /* Check results. 4077 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */ 4078 for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i) 4079 { 4080 if (fabs(*i) > 0.0625f /* precision */) 4081 { 4082 return false; 4083 } 4084 } 4085 4086 return true; 4087 } 4088 4089 /*-----------------------------------------------------------------------------------------------*/ 4090 4091 gl3cts::TransformFeedback::DiscardGeometry::DiscardGeometry(deqp::Context& context, const char* test_name, 4092 const char* test_description) 4093 : CaptureVertexInterleaved(context, test_name, test_description) 4094 , CaptureGeometryInterleaved(context, test_name, test_description) 4095 { 4096 } 4097 4098 void gl3cts::TransformFeedback::DiscardGeometry::draw(glw::GLuint primitive_case) 4099 { 4100 /* Functions handler */ 4101 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4102 4103 /* Must clear before rasterizer discard */ 4104 gl.clear(GL_COLOR_BUFFER_BIT); 4105 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 4106 4107 gl.enable(GL_RASTERIZER_DISCARD); 4108 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 4109 4110 gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case); 4111 4112 gl.disable(GL_RASTERIZER_DISCARD); 4113 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 4114 } 4115 4116 bool gl3cts::TransformFeedback::DiscardGeometry::checkFramebuffer(glw::GLuint primitive_case UNUSED) 4117 { 4118 /* Functions handler */ 4119 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4120 4121 /* Fetch framebuffer. */ 4122 std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size); 4123 4124 if ((s_framebuffer_size > 0) && (s_framebuffer_size > 0)) 4125 { 4126 gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data()); 4127 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 4128 } 4129 4130 /* Check results. 4131 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */ 4132 for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i) 4133 { 4134 if (fabs(*i) > 0.0625f /* precision */) 4135 { 4136 return false; 4137 } 4138 } 4139 4140 return true; 4141 } 4142 4143 /*-----------------------------------------------------------------------------------------------*/ 4144 4145 gl3cts::TransformFeedback::DrawXFB::DrawXFB(deqp::Context& context, const char* test_name, const char* test_description) 4146 : deqp::TestCase(context, test_name, test_description) 4147 , m_context(context) 4148 , m_program_id_xfb(0) 4149 , m_program_id_draw(0) 4150 , m_fbo_id(0) 4151 , m_rbo_id(0) 4152 , m_vao_id(0) 4153 { 4154 memset(m_xfb_id, 0, sizeof(m_xfb_id)); 4155 memset(m_bo_id, 0, sizeof(m_bo_id)); 4156 } 4157 4158 gl3cts::TransformFeedback::DrawXFB::~DrawXFB(void) 4159 { 4160 } 4161 4162 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFB::iterate(void) 4163 { 4164 /* Initializations. */ 4165 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 4166 bool is_arb_tf_2 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2"); 4167 4168 bool is_ok = true; 4169 bool test_error = false; 4170 4171 /* Tests. */ 4172 try 4173 { 4174 if (is_at_least_gl_40 || is_arb_tf_2) 4175 { 4176 for (glw::GLuint i = 0; (i < s_capture_modes_count) && is_ok; ++i) 4177 { 4178 prepare(s_capture_modes[i]); 4179 4180 bindVAO(m_vao_id); 4181 useProgram(m_program_id_xfb); 4182 4183 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j) 4184 { 4185 bindXFB(m_xfb_id[j]); 4186 bindBOForXFB(s_capture_modes[i], m_bo_id[j]); 4187 useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]); 4188 useGeometrySet(m_program_id_xfb, false); 4189 drawForCapture(true, true, false, false); 4190 4191 is_ok = is_ok && inspectXFBState(true, true); 4192 } 4193 4194 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j) 4195 { 4196 bindXFB(m_xfb_id[j]); 4197 useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]); 4198 useGeometrySet(m_program_id_xfb, true); 4199 drawForCapture(false, false, true, true); 4200 4201 is_ok = is_ok && inspectXFBState(false, false); 4202 } 4203 4204 useProgram(m_program_id_draw); 4205 4206 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j) 4207 { 4208 bindXFB(m_xfb_id[j]); 4209 bindBOForDraw(m_program_id_draw, s_capture_modes[i], m_bo_id[j]); 4210 drawToFramebuffer(m_xfb_id[j]); 4211 4212 is_ok = 4213 is_ok && checkFramebuffer(s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]); 4214 } 4215 4216 clean(); 4217 } 4218 } 4219 } 4220 catch (...) 4221 { 4222 is_ok = false; 4223 test_error = true; 4224 clean(); 4225 } 4226 4227 /* Result's setup. */ 4228 if (is_ok) 4229 { 4230 /* Log success. */ 4231 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have passed." 4232 << tcu::TestLog::EndMessage; 4233 4234 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4235 } 4236 else 4237 { 4238 if (test_error) 4239 { 4240 /* Log error. */ 4241 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have approached error." 4242 << tcu::TestLog::EndMessage; 4243 4244 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 4245 } 4246 else 4247 { 4248 /* Log fail. */ 4249 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have failed." 4250 << tcu::TestLog::EndMessage; 4251 4252 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4253 } 4254 } 4255 4256 return STOP; 4257 } 4258 4259 void gl3cts::TransformFeedback::DrawXFB::prepare(glw::GLenum capture_mode) 4260 { 4261 /* Functions handler */ 4262 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4263 4264 /* Prepare programs. */ 4265 m_program_id_xfb = gl3cts::TransformFeedback::Utilities::buildProgram( 4266 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_xfb, s_fragment_shader, 4267 s_xfb_varyings, s_xfb_varyings_count, capture_mode); 4268 4269 if (0 == m_program_id_xfb) 4270 { 4271 throw 0; 4272 } 4273 4274 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(), 4275 NULL, NULL, NULL, s_vertex_shader_draw, 4276 s_fragment_shader, NULL, 0, capture_mode); 4277 4278 if (0 == m_program_id_draw) 4279 { 4280 throw 0; 4281 } 4282 4283 /* Prepare transform feedbacks. */ 4284 gl.genTransformFeedbacks(s_xfb_count, m_xfb_id); 4285 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 4286 4287 /* Prepare buffer objects. */ 4288 gl.genBuffers(s_xfb_count, m_bo_id); 4289 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 4290 4291 for (glw::GLuint i = 0; i < s_xfb_count; ++i) 4292 { 4293 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]); 4294 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4295 4296 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_capture_size, NULL, GL_DYNAMIC_COPY); 4297 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 4298 } 4299 4300 /* Prepare framebuffer. */ 4301 gl.clearColor(0.f, 0.f, 0.f, 1.f); 4302 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 4303 4304 gl.genFramebuffers(1, &m_fbo_id); 4305 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed."); 4306 4307 gl.genRenderbuffers(1, &m_rbo_id); 4308 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed."); 4309 4310 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 4311 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); 4312 4313 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id); 4314 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed."); 4315 4316 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, s_view_size, s_view_size); 4317 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed."); 4318 4319 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id); 4320 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed."); 4321 4322 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 4323 { 4324 throw 0; 4325 } 4326 4327 gl.viewport(0, 0, s_view_size, s_view_size); 4328 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed."); 4329 4330 /* Create empty Vertex Array Object */ 4331 gl.genVertexArrays(1, &m_vao_id); 4332 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 4333 } 4334 4335 void gl3cts::TransformFeedback::DrawXFB::bindXFB(glw::GLuint xfb_id) 4336 { 4337 /* Functions handler */ 4338 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4339 4340 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb_id); 4341 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed."); 4342 } 4343 4344 void gl3cts::TransformFeedback::DrawXFB::bindVAO(glw::GLuint vao_id) 4345 { 4346 /* Functions handler */ 4347 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4348 4349 gl.bindVertexArray(vao_id); 4350 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 4351 } 4352 4353 void gl3cts::TransformFeedback::DrawXFB::bindBOForXFB(glw::GLenum capture_mode, glw::GLuint bo_id) 4354 { 4355 /* Functions handler */ 4356 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4357 4358 switch (capture_mode) 4359 { 4360 case GL_INTERLEAVED_ATTRIBS: 4361 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id); 4362 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 4363 break; 4364 case GL_SEPARATE_ATTRIBS: 4365 for (glw::GLuint i = 0; i < s_xfb_varyings_count; ++i) 4366 { 4367 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, bo_id, i * s_capture_size / s_xfb_varyings_count, 4368 (i + 1) * s_capture_size / s_xfb_varyings_count); 4369 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed."); 4370 } 4371 break; 4372 default: 4373 throw 0; 4374 }; 4375 } 4376 4377 void gl3cts::TransformFeedback::DrawXFB::bindBOForDraw(glw::GLuint program_id, glw::GLenum capture_mode, 4378 glw::GLuint bo_id) 4379 { 4380 /* Functions handler */ 4381 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4382 4383 gl.bindBuffer(GL_ARRAY_BUFFER, bo_id); 4384 4385 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4386 4387 glw::GLuint position_location = gl.getAttribLocation(program_id, "position"); 4388 glw::GLuint color_location = gl.getAttribLocation(program_id, "color"); 4389 4390 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 4391 4392 glw::GLvoid* color_offset = (capture_mode == GL_INTERLEAVED_ATTRIBS) ? 4393 (glw::GLvoid*)(4 /* components */ * sizeof(glw::GLfloat)) : 4394 (glw::GLvoid*)(4 /* components */ * 6 /* vertices */ * sizeof(glw::GLfloat)); 4395 4396 glw::GLuint stride = 4397 static_cast<glw::GLuint>((capture_mode == GL_INTERLEAVED_ATTRIBS) ? 4398 (4 /* components */ * 2 /* position and color */ * sizeof(glw::GLfloat)) : 4399 (4 /* components */ * sizeof(glw::GLfloat))); 4400 4401 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, stride, NULL); 4402 gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, stride, color_offset); 4403 4404 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); 4405 4406 gl.enableVertexAttribArray(position_location); 4407 gl.enableVertexAttribArray(color_location); 4408 4409 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 4410 } 4411 4412 void gl3cts::TransformFeedback::DrawXFB::useProgram(glw::GLuint program_id) 4413 { 4414 /* Functions handler */ 4415 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4416 4417 gl.useProgram(program_id); 4418 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 4419 } 4420 4421 void gl3cts::TransformFeedback::DrawXFB::useColour(glw::GLuint program_id, glw::GLfloat r, glw::GLfloat g, 4422 glw::GLfloat b, glw::GLfloat a) 4423 { 4424 /* Functions handler */ 4425 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4426 4427 glw::GLint location = gl.getUniformLocation(program_id, "color"); 4428 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed."); 4429 4430 gl.uniform4f(location, r, g, b, a); 4431 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed."); 4432 } 4433 4434 void gl3cts::TransformFeedback::DrawXFB::useGeometrySet(glw::GLuint program_id, bool invert_sign) 4435 { 4436 /* Functions handler */ 4437 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4438 4439 glw::GLint location = gl.getUniformLocation(program_id, "invert_sign"); 4440 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed."); 4441 4442 gl.uniform1f(location, invert_sign ? -1.f : 1.f); 4443 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed."); 4444 } 4445 4446 void gl3cts::TransformFeedback::DrawXFB::clean() 4447 { 4448 /* Functions handler */ 4449 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4450 4451 gl.useProgram(0); 4452 4453 if (m_program_id_xfb) 4454 { 4455 gl.deleteProgram(m_program_id_xfb); 4456 4457 m_program_id_xfb = 0; 4458 } 4459 4460 if (m_program_id_draw) 4461 { 4462 gl.deleteProgram(m_program_id_draw); 4463 4464 m_program_id_draw = 1; 4465 } 4466 4467 for (glw::GLuint i = 0; i < s_xfb_count; ++i) 4468 { 4469 if (m_xfb_id[i]) 4470 { 4471 gl.deleteTransformFeedbacks(1, &m_xfb_id[i]); 4472 4473 m_xfb_id[i] = 0; 4474 } 4475 } 4476 4477 for (glw::GLuint i = 0; i < s_xfb_count; ++i) 4478 { 4479 if (m_bo_id[i]) 4480 { 4481 gl.deleteBuffers(1, &m_bo_id[i]); 4482 4483 m_bo_id[i] = 0; 4484 } 4485 } 4486 4487 if (m_vao_id) 4488 { 4489 gl.deleteVertexArrays(1, &m_vao_id); 4490 4491 m_vao_id = 0; 4492 } 4493 4494 if (m_fbo_id) 4495 { 4496 gl.deleteFramebuffers(1, &m_fbo_id); 4497 4498 m_fbo_id = 0; 4499 } 4500 4501 if (m_rbo_id) 4502 { 4503 gl.deleteRenderbuffers(1, &m_rbo_id); 4504 4505 m_rbo_id = 0; 4506 } 4507 } 4508 4509 void gl3cts::TransformFeedback::DrawXFB::drawForCapture(bool begin_xfb, bool pause_xfb, bool resume_xfb, bool end_xfb) 4510 { 4511 /* Functions handler */ 4512 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4513 4514 gl.enable(GL_RASTERIZER_DISCARD); 4515 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 4516 4517 if (begin_xfb) 4518 { 4519 gl.beginTransformFeedback(GL_POINTS); 4520 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 4521 } 4522 4523 if (resume_xfb) 4524 { 4525 gl.resumeTransformFeedback(); 4526 GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback call failed."); 4527 } 4528 4529 gl.drawArrays(GL_POINTS, 0, 3); 4530 4531 if (pause_xfb) 4532 { 4533 gl.pauseTransformFeedback(); 4534 GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed."); 4535 } 4536 4537 if (end_xfb) 4538 { 4539 gl.endTransformFeedback(); 4540 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 4541 } 4542 4543 gl.disable(GL_RASTERIZER_DISCARD); 4544 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 4545 } 4546 4547 void gl3cts::TransformFeedback::DrawXFB::drawToFramebuffer(glw::GLuint xfb_id) 4548 { 4549 /* Functions handler */ 4550 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4551 4552 gl.clearColor(0.f, 0.f, 0.f, 0.f); 4553 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 4554 4555 gl.clear(GL_COLOR_BUFFER_BIT); 4556 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 4557 4558 gl.drawTransformFeedback(GL_TRIANGLES, xfb_id); 4559 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed."); 4560 } 4561 4562 bool gl3cts::TransformFeedback::DrawXFB::checkFramebuffer(glw::GLfloat r, glw::GLfloat g, glw::GLfloat b, 4563 glw::GLfloat a) 4564 { 4565 /* Functions handler */ 4566 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4567 4568 /* Number of pixels. */ 4569 const glw::GLuint number_of_pixels = s_view_size * s_view_size; 4570 4571 /* Fetch framebuffer. */ 4572 std::vector<glw::GLubyte> pixels(number_of_pixels * 4 /* components */); 4573 4574 if ((s_view_size > 0) && (s_view_size > 0)) 4575 { 4576 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); 4577 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 4578 } 4579 4580 /* Convert color to integer. */ 4581 glw::GLubyte ir = (glw::GLubyte)(255.f * r); 4582 glw::GLubyte ig = (glw::GLubyte)(255.f * g); 4583 glw::GLubyte ib = (glw::GLubyte)(255.f * b); 4584 glw::GLubyte ia = (glw::GLubyte)(255.f * a); 4585 4586 /* Check results. */ 4587 for (glw::GLuint i = 0; i < number_of_pixels; ++i) 4588 { 4589 if ((pixels[i * 4 /* components */] != ir) || (pixels[i * 4 /* components */ + 1] != ig) || 4590 (pixels[i * 4 /* components */ + 2] != ib) || (pixels[i * 4 /* components */ + 3] != ia)) 4591 { 4592 return false; 4593 } 4594 } 4595 4596 return true; 4597 } 4598 4599 bool gl3cts::TransformFeedback::DrawXFB::inspectXFBState(bool shall_be_paused, bool shall_be_active) 4600 { 4601 /* Functions handler */ 4602 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4603 4604 glw::GLint is_paused = 0; 4605 glw::GLint is_active = 0; 4606 4607 gl.getIntegerv(GL_TRANSFORM_FEEDBACK_PAUSED, &is_paused); 4608 gl.getIntegerv(GL_TRANSFORM_FEEDBACK_ACTIVE, &is_active); 4609 4610 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 4611 4612 if ((is_paused == -1) || (is_active == -1)) 4613 { 4614 throw 0; 4615 } 4616 4617 if (shall_be_paused ^ (is_paused == GL_TRUE)) 4618 { 4619 return false; 4620 } 4621 4622 if (shall_be_active ^ (is_active == GL_TRUE)) 4623 { 4624 return false; 4625 } 4626 4627 return true; 4628 } 4629 4630 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_xfb = 4631 "#version 130\n" 4632 "\n" 4633 "uniform vec4 color;\n" 4634 "uniform float invert_sign;\n" 4635 "out vec4 colour;\n" 4636 "\n" 4637 "void main()\n" 4638 "{\n" 4639 " switch(gl_VertexID)\n" 4640 " {\n" 4641 " case 0:\n" 4642 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 4643 " break;\n" 4644 " case 1:\n" 4645 " gl_Position = vec4(-1.0 * invert_sign, 1.0, 0.0, 1.0);\n" 4646 " break;\n" 4647 " case 2:\n" 4648 " gl_Position = vec4( 1.0, 1.0 * invert_sign, 0.0, 1.0);\n" 4649 " break;\n" 4650 " }\n" 4651 "\n" 4652 " colour = color;\n" 4653 "}\n"; 4654 4655 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_draw = "#version 130\n" 4656 "\n" 4657 "in vec4 color;\n" 4658 "in vec4 position;\n" 4659 "out vec4 colour;\n" 4660 "\n" 4661 "void main()\n" 4662 "{\n" 4663 " gl_Position = position;\n" 4664 " colour = color;\n" 4665 "}\n"; 4666 4667 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_fragment_shader = "#version 130\n" 4668 "\n" 4669 "in vec4 colour;\n" 4670 "out vec4 pixel;\n" 4671 "\n" 4672 "void main()\n" 4673 "{\n" 4674 " pixel = colour;\n" 4675 "}\n"; 4676 4677 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_xfb_varyings[s_xfb_varyings_count] = { "gl_Position", 4678 "colour" }; 4679 4680 const glw::GLenum gl3cts::TransformFeedback::DrawXFB::s_capture_modes[] = { GL_INTERLEAVED_ATTRIBS, 4681 GL_SEPARATE_ATTRIBS }; 4682 const glw::GLuint gl3cts::TransformFeedback::DrawXFB::s_capture_modes_count = 4683 sizeof(s_capture_modes) / sizeof(s_capture_modes[0]); 4684 4685 const glw::GLfloat gl3cts::TransformFeedback::DrawXFB::s_colours[s_xfb_count][4] = { { 1.f, 0.f, 0.f, 1.f }, 4686 { 0.f, 1.f, 0.f, 1.f }, 4687 { 0.f, 0.f, 1.f, 1.f } }; 4688 4689 /*-----------------------------------------------------------------------------------------------*/ 4690 4691 gl3cts::TransformFeedback::DrawXFBFeedback::DrawXFBFeedback(deqp::Context& context, const char* test_name, 4692 const char* test_description) 4693 : deqp::TestCase(context, test_name, test_description) 4694 , m_context(context) 4695 , m_program_id(0) 4696 , m_xfb_id(0) 4697 , m_source_bo_index(0) 4698 { 4699 memset(m_bo_id, 1, sizeof(m_bo_id)); 4700 memset(m_bo_id, 1, sizeof(m_vao_id)); 4701 } 4702 4703 gl3cts::TransformFeedback::DrawXFBFeedback::~DrawXFBFeedback(void) 4704 { 4705 } 4706 4707 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBFeedback::iterate(void) 4708 { 4709 /* Initializations. */ 4710 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 4711 bool is_arb_tf_2 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2"); 4712 4713 bool is_ok = true; 4714 bool test_error = false; 4715 4716 /* Tests. */ 4717 try 4718 { 4719 if (is_at_least_gl_40 || is_arb_tf_2) 4720 { 4721 prepareAndBind(); 4722 draw(true); 4723 swapBuffers(); 4724 draw(false); 4725 swapBuffers(); 4726 draw(false); 4727 4728 is_ok = is_ok && check(); 4729 } 4730 } 4731 catch (...) 4732 { 4733 is_ok = false; 4734 test_error = true; 4735 } 4736 4737 /* Clean GL objects. */ 4738 clean(); 4739 4740 /* Result's setup. */ 4741 if (is_ok) 4742 { 4743 /* Log success. */ 4744 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have passed." 4745 << tcu::TestLog::EndMessage; 4746 4747 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4748 } 4749 else 4750 { 4751 if (test_error) 4752 { 4753 /* Log error. */ 4754 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have approached error." 4755 << tcu::TestLog::EndMessage; 4756 4757 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 4758 } 4759 else 4760 { 4761 /* Log fail. */ 4762 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have failed." 4763 << tcu::TestLog::EndMessage; 4764 4765 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 4766 } 4767 } 4768 4769 return STOP; 4770 } 4771 4772 void gl3cts::TransformFeedback::DrawXFBFeedback::prepareAndBind() 4773 { 4774 /* Functions handler */ 4775 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4776 4777 /* Prepare programs. */ 4778 m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(), NULL, 4779 NULL, NULL, s_vertex_shader, s_fragment_shader, 4780 &s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS); 4781 4782 if (0 == m_program_id) 4783 { 4784 throw 0; 4785 } 4786 4787 gl.useProgram(m_program_id); 4788 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 4789 4790 /* Prepare transform feedbacks. */ 4791 gl.genTransformFeedbacks(1, &m_xfb_id); 4792 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 4793 4794 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id); 4795 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed."); 4796 4797 /* Prepare buffer objects. */ 4798 gl.genBuffers(s_bo_count, m_bo_id); 4799 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 4800 4801 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[0]); 4802 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4803 4804 gl.bufferData(GL_ARRAY_BUFFER, s_bo_size, s_initial_data, GL_DYNAMIC_COPY); 4805 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 4806 4807 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[1]); 4808 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4809 4810 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); 4811 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 4812 4813 /* Setup vertex arrays. */ 4814 gl.genVertexArrays(s_bo_count, m_vao_id); 4815 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 4816 4817 glw::GLuint position_location = gl.getAttribLocation(m_program_id, "position"); 4818 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 4819 4820 for (glw::GLuint i = 0; i < 2; ++i) 4821 { 4822 gl.bindVertexArray(m_vao_id[i]); 4823 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 4824 4825 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[i]); 4826 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4827 4828 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL); 4829 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); 4830 4831 gl.enableVertexAttribArray(position_location); 4832 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 4833 } 4834 4835 gl.bindBuffer(GL_ARRAY_BUFFER, 0); 4836 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4837 4838 gl.bindVertexArray(m_vao_id[0]); 4839 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 4840 } 4841 4842 void gl3cts::TransformFeedback::DrawXFBFeedback::swapBuffers() 4843 { 4844 /* Functions handler */ 4845 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4846 4847 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[m_source_bo_index]); 4848 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 4849 4850 m_source_bo_index = (m_source_bo_index + 1) % 2; 4851 4852 gl.bindVertexArray(m_vao_id[(m_source_bo_index)]); 4853 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 4854 } 4855 4856 void gl3cts::TransformFeedback::DrawXFBFeedback::draw(bool is_first_draw) 4857 { 4858 /* Functions handler */ 4859 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4860 4861 gl.enable(GL_RASTERIZER_DISCARD); 4862 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 4863 4864 gl.beginTransformFeedback(GL_POINTS); 4865 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 4866 4867 if (is_first_draw) 4868 { 4869 gl.drawArrays(GL_POINTS, 0, 1); 4870 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 4871 } 4872 else 4873 { 4874 gl.drawTransformFeedback(GL_POINTS, m_xfb_id); 4875 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed."); 4876 } 4877 4878 gl.endTransformFeedback(); 4879 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 4880 4881 gl.disable(GL_RASTERIZER_DISCARD); 4882 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 4883 } 4884 4885 bool gl3cts::TransformFeedback::DrawXFBFeedback::check() 4886 { 4887 /* Functions handler */ 4888 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4889 4890 glw::GLfloat* results = 4891 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT); 4892 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed."); 4893 4894 bool is_ok = false; 4895 4896 if (results) 4897 { 4898 if ((results[0] == 8.f) && (results[1] == 16.f) && (results[2] == 24.f) && (results[3] == 32.f)) 4899 { 4900 is_ok = true; 4901 } 4902 4903 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 4904 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 4905 } 4906 4907 return is_ok; 4908 } 4909 4910 void gl3cts::TransformFeedback::DrawXFBFeedback::clean() 4911 { 4912 /* Functions handler */ 4913 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4914 4915 gl.useProgram(0); 4916 4917 if (m_program_id) 4918 { 4919 gl.deleteProgram(m_program_id); 4920 4921 m_program_id = 0; 4922 } 4923 4924 if (m_xfb_id) 4925 { 4926 gl.deleteTransformFeedbacks(1, &m_xfb_id); 4927 4928 m_xfb_id = 0; 4929 } 4930 4931 for (glw::GLuint i = 0; i < s_bo_count; ++i) 4932 { 4933 if (m_bo_id[i]) 4934 { 4935 gl.deleteBuffers(1, &m_bo_id[i]); 4936 4937 m_bo_id[i] = 0; 4938 } 4939 } 4940 4941 for (glw::GLuint i = 0; i < s_bo_count; ++i) 4942 { 4943 if (m_vao_id[i]) 4944 { 4945 gl.deleteVertexArrays(1, &m_vao_id[i]); 4946 4947 m_vao_id[i] = 0; 4948 } 4949 } 4950 } 4951 4952 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_vertex_shader = "#version 130\n" 4953 "\n" 4954 "in vec4 position;\n" 4955 "\n" 4956 "void main()\n" 4957 "{\n" 4958 " gl_Position = position * 2.0;\n" 4959 "}\n"; 4960 4961 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_fragment_shader = "#version 130\n" 4962 "\n" 4963 "out vec4 pixel;\n" 4964 "\n" 4965 "void main()\n" 4966 "{\n" 4967 " pixel = vec4(1.0);\n" 4968 "}\n"; 4969 4970 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_xfb_varying = "gl_Position"; 4971 4972 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_attrib = "position"; 4973 4974 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBFeedback::s_initial_data[] = { 1.f, 2.f, 3.f, 4.f }; 4975 4976 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_draw_vertex_count = 4977 sizeof(s_initial_data) / sizeof(s_initial_data[0]) / 4 /* components */; 4978 4979 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_bo_size = sizeof(s_initial_data); 4980 4981 /*-----------------------------------------------------------------------------------------------*/ 4982 4983 gl3cts::TransformFeedback::CaptureSpecialInterleaved::CaptureSpecialInterleaved(deqp::Context& context, 4984 const char* test_name, 4985 const char* test_description) 4986 : deqp::TestCase(context, test_name, test_description) 4987 , m_context(context) 4988 , m_program_id(0) 4989 , m_vao_id(0) 4990 , m_xfb_id(0) 4991 { 4992 memset(m_bo_id, 0, sizeof(m_bo_id)); 4993 } 4994 4995 gl3cts::TransformFeedback::CaptureSpecialInterleaved::~CaptureSpecialInterleaved(void) 4996 { 4997 } 4998 4999 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureSpecialInterleaved::iterate(void) 5000 { 5001 /* Initializations. */ 5002 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 5003 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3"); 5004 5005 bool is_ok = true; 5006 bool test_error = false; 5007 5008 /* Tests. */ 5009 try 5010 { 5011 if (is_at_least_gl_40 || is_arb_tf_3) 5012 { 5013 prepareAndBind(); 5014 draw(); 5015 5016 is_ok = is_ok && check(); 5017 } 5018 } 5019 catch (...) 5020 { 5021 is_ok = false; 5022 test_error = true; 5023 } 5024 5025 /* Clean GL objects. */ 5026 clean(); 5027 5028 /* Result's setup. */ 5029 if (is_ok) 5030 { 5031 /* Log success. */ 5032 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Special Interleaved have passed." 5033 << tcu::TestLog::EndMessage; 5034 5035 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5036 } 5037 else 5038 { 5039 if (test_error) 5040 { 5041 /* Log error. */ 5042 m_context.getTestContext().getLog() << tcu::TestLog::Message 5043 << "Capture Special Interleaved have approached error." 5044 << tcu::TestLog::EndMessage; 5045 5046 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 5047 } 5048 else 5049 { 5050 /* Log fail. */ 5051 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Special Interleaved have failed." 5052 << tcu::TestLog::EndMessage; 5053 5054 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5055 } 5056 } 5057 5058 return STOP; 5059 } 5060 5061 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::prepareAndBind() 5062 { 5063 /* Functions handler */ 5064 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5065 5066 /* Prepare programs. */ 5067 m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram( 5068 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader, s_fragment_shader, s_xfb_varyings, 5069 s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS); 5070 5071 if (0 == m_program_id) 5072 { 5073 throw 0; 5074 } 5075 5076 gl.useProgram(m_program_id); 5077 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 5078 5079 /* Prepare transform feedbacks. */ 5080 gl.genTransformFeedbacks(1, &m_xfb_id); 5081 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 5082 5083 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id); 5084 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed."); 5085 5086 /* Create empty Vertex Array Object */ 5087 gl.genVertexArrays(1, &m_vao_id); 5088 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 5089 5090 gl.bindVertexArray(m_vao_id); 5091 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 5092 5093 /* Prepare buffer objects. */ 5094 gl.genBuffers(s_bo_ids_count, m_bo_id); 5095 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 5096 5097 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i) 5098 { 5099 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]); 5100 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5101 5102 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */ 5103 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 5104 5105 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]); 5106 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 5107 } 5108 } 5109 5110 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::draw() 5111 { 5112 /* Functions handler */ 5113 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5114 5115 gl.enable(GL_RASTERIZER_DISCARD); 5116 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 5117 5118 gl.beginTransformFeedback(GL_POINTS); 5119 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 5120 5121 gl.drawArrays(GL_POINTS, 0, 1); 5122 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 5123 5124 gl.endTransformFeedback(); 5125 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 5126 5127 gl.disable(GL_RASTERIZER_DISCARD); 5128 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 5129 } 5130 5131 bool gl3cts::TransformFeedback::CaptureSpecialInterleaved::check() 5132 { 5133 /* Functions handler */ 5134 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5135 5136 bool is_ok = true; 5137 5138 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[0]); 5139 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5140 5141 glw::GLfloat* results = 5142 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT); 5143 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed."); 5144 5145 if ((results[0] != 1.0) || (results[1] != 2.0) || (results[2] != 3.0) || (results[3] != 4.0) || 5146 /* gl_SkipComponents4 here */ 5147 (results[8] != 5.0) || (results[9] != 6.0) || (results[10] != 7.0) || (results[11] != 8.0)) 5148 { 5149 is_ok = false; 5150 } 5151 5152 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 5153 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 5154 5155 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[1]); 5156 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5157 5158 results = (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT); 5159 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed."); 5160 5161 if ((results[0] != 9.0) || (results[1] != 10.0) || (results[2] != 11.0) || (results[3] != 12.0) || 5162 /* gl_SkipComponents4 here */ 5163 (results[8] != 13.0) || (results[9] != 14.0) || (results[10] != 15.0) || (results[11] != 16.0)) 5164 { 5165 is_ok = false; 5166 } 5167 5168 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 5169 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed."); 5170 5171 return is_ok; 5172 } 5173 5174 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::clean() 5175 { 5176 /* Functions handler */ 5177 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5178 5179 gl.useProgram(0); 5180 5181 if (m_program_id) 5182 { 5183 gl.deleteProgram(m_program_id); 5184 5185 m_program_id = 0; 5186 } 5187 5188 if (m_xfb_id) 5189 { 5190 gl.deleteTransformFeedbacks(1, &m_xfb_id); 5191 5192 m_xfb_id = 0; 5193 } 5194 5195 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i) 5196 { 5197 if (m_bo_id[i]) 5198 { 5199 gl.deleteBuffers(1, &m_bo_id[i]); 5200 5201 m_bo_id[i] = 0; 5202 } 5203 } 5204 5205 if (m_vao_id) 5206 { 5207 gl.deleteVertexArrays(1, &m_vao_id); 5208 5209 m_vao_id = 0; 5210 } 5211 } 5212 5213 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_vertex_shader = 5214 "#version 130\n" 5215 "\n" 5216 "out vec4 variable_1;\n" 5217 "out vec4 variable_2;\n" 5218 "out vec4 variable_3;\n" 5219 "out vec4 variable_4;\n" 5220 "\n" 5221 "void main()\n" 5222 "{\n" 5223 " variable_1 = vec4(1.0, 2.0, 3.0, 4.0);\n" 5224 " variable_2 = vec4(5.0, 6.0, 7.0, 8.0);\n" 5225 " variable_3 = vec4(9.0, 10.0, 11.0, 12.0);\n" 5226 " variable_4 = vec4(13.0, 14.0, 15.0, 16.0);\n" 5227 "\n" 5228 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" 5229 "}\n"; 5230 5231 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_fragment_shader = "#version 130\n" 5232 "\n" 5233 "out vec4 pixel;\n" 5234 "\n" 5235 "void main()\n" 5236 "{\n" 5237 " pixel = vec4(1.0);\n" 5238 "}\n"; 5239 5240 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings[] = 5241 { "variable_1", "gl_SkipComponents4", "variable_2", "gl_NextBuffer", 5242 "variable_3", "gl_SkipComponents4", "variable_4" }; 5243 5244 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings_count = 5245 sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]); 5246 5247 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_bo_size = 5248 3 /*number of variables / empty places */ * 4 /* vec4 */ 5249 * sizeof(glw::GLfloat); 5250 5251 /*-----------------------------------------------------------------------------------------------*/ 5252 5253 gl3cts::TransformFeedback::DrawXFBStream::DrawXFBStream(deqp::Context& context, const char* test_name, 5254 const char* test_description) 5255 : deqp::TestCase(context, test_name, test_description) 5256 , m_context(context) 5257 , m_program_id_generate(0) 5258 , m_program_id_draw(0) 5259 , m_vao_id(0) 5260 , m_xfb_id(0) 5261 , m_fbo_id(0) 5262 , m_rbo_id(0) 5263 { 5264 memset(m_bo_id, 0, sizeof(m_bo_id)); 5265 memset(m_qo_id, 0, sizeof(m_qo_id)); 5266 } 5267 5268 gl3cts::TransformFeedback::DrawXFBStream::~DrawXFBStream(void) 5269 { 5270 } 5271 5272 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStream::iterate(void) 5273 { 5274 /* Functions handler */ 5275 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5276 5277 /* Initializations. */ 5278 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 5279 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3"); 5280 bool is_arb_gpu_shader5 = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"); 5281 5282 glw::GLint max_vertex_streams = 0; 5283 5284 bool is_ok = true; 5285 bool test_error = false; 5286 5287 /* Tests. */ 5288 try 5289 { 5290 if (is_at_least_gl_40 || (is_arb_tf_3 && is_arb_gpu_shader5)) 5291 { 5292 gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams); 5293 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed."); 5294 5295 if (max_vertex_streams >= 2) 5296 { 5297 prepareObjects(); 5298 5299 useProgram(m_program_id_generate); 5300 5301 drawForXFB(); 5302 5303 is_ok = is_ok && inspectQueries(); 5304 5305 useProgram(m_program_id_draw); 5306 5307 setupVertexArray(m_bo_id[0]); 5308 5309 drawForFramebuffer(0); 5310 5311 setupVertexArray(m_bo_id[1]); 5312 5313 drawForFramebuffer(1); 5314 5315 is_ok = is_ok && check(); 5316 } 5317 } 5318 } 5319 catch (...) 5320 { 5321 is_ok = false; 5322 test_error = true; 5323 } 5324 5325 /* Clean GL objects. */ 5326 clean(); 5327 5328 /* Result's setup. */ 5329 if (is_ok) 5330 { 5331 /* Log success. */ 5332 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have passed." 5333 << tcu::TestLog::EndMessage; 5334 5335 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5336 } 5337 else 5338 { 5339 if (test_error) 5340 { 5341 /* Log error. */ 5342 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have approached error." 5343 << tcu::TestLog::EndMessage; 5344 5345 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 5346 } 5347 else 5348 { 5349 /* Log fail. */ 5350 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have failed." 5351 << tcu::TestLog::EndMessage; 5352 5353 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5354 } 5355 } 5356 5357 return STOP; 5358 } 5359 5360 void gl3cts::TransformFeedback::DrawXFBStream::prepareObjects() 5361 { 5362 /* Functions handler */ 5363 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5364 5365 /* Prepare programs. */ 5366 m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram( 5367 gl, m_context.getTestContext().getLog(), s_geometry_shader, NULL, NULL, s_vertex_shader_blank, 5368 s_fragment_shader, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS); 5369 5370 if (0 == m_program_id_generate) 5371 { 5372 throw 0; 5373 } 5374 5375 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram( 5376 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_pass, s_fragment_shader, NULL, 0, 5377 GL_INTERLEAVED_ATTRIBS); 5378 5379 if (0 == m_program_id_draw) 5380 { 5381 throw 0; 5382 } 5383 5384 /* Prepare transform feedbacks. */ 5385 gl.genTransformFeedbacks(1, &m_xfb_id); 5386 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 5387 5388 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id); 5389 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed."); 5390 5391 /* Create empty Vertex Array Object */ 5392 gl.genVertexArrays(1, &m_vao_id); 5393 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 5394 5395 gl.bindVertexArray(m_vao_id); 5396 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 5397 5398 /* Prepare buffer objects. */ 5399 gl.genBuffers(s_bo_ids_count, m_bo_id); 5400 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 5401 5402 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i) 5403 { 5404 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]); 5405 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5406 5407 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */ 5408 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 5409 5410 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]); 5411 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 5412 } 5413 5414 /* Generate queries */ 5415 gl.genQueries(s_qo_ids_count, m_qo_id); 5416 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed."); 5417 5418 /* Prepare framebuffer. */ 5419 gl.clearColor(0.f, 0.f, 0.f, 1.f); 5420 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 5421 5422 gl.genFramebuffers(1, &m_fbo_id); 5423 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed."); 5424 5425 gl.genRenderbuffers(1, &m_rbo_id); 5426 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed."); 5427 5428 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 5429 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); 5430 5431 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id); 5432 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed."); 5433 5434 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size); 5435 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed."); 5436 5437 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id); 5438 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed."); 5439 5440 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 5441 { 5442 throw 0; 5443 } 5444 5445 gl.viewport(0, 0, s_view_size, s_view_size); 5446 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed."); 5447 } 5448 5449 void gl3cts::TransformFeedback::DrawXFBStream::setupVertexArray(glw::GLuint bo_id) 5450 { 5451 /* Functions handler */ 5452 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5453 5454 gl.bindBuffer(GL_ARRAY_BUFFER, bo_id); 5455 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5456 5457 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position"); 5458 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 5459 5460 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL); 5461 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); 5462 5463 gl.enableVertexAttribArray(position_location); 5464 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 5465 } 5466 5467 void gl3cts::TransformFeedback::DrawXFBStream::useProgram(glw::GLuint program_id) 5468 { 5469 /* Functions handler */ 5470 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5471 5472 gl.useProgram(program_id); 5473 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 5474 } 5475 5476 void gl3cts::TransformFeedback::DrawXFBStream::drawForXFB() 5477 { 5478 /* Functions handler */ 5479 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5480 5481 gl.enable(GL_RASTERIZER_DISCARD); 5482 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 5483 5484 gl.beginTransformFeedback(GL_POINTS); 5485 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 5486 5487 gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 0, m_qo_id[0]); 5488 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed."); 5489 5490 gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 1, m_qo_id[1]); 5491 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed."); 5492 5493 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0, m_qo_id[2]); 5494 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed."); 5495 5496 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1, m_qo_id[3]); 5497 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed."); 5498 5499 gl.drawArrays(GL_POINTS, 0, 1); 5500 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 5501 5502 gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 0); 5503 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed."); 5504 5505 gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 1); 5506 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed."); 5507 5508 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0); 5509 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed."); 5510 5511 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1); 5512 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed."); 5513 5514 gl.endTransformFeedback(); 5515 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 5516 5517 gl.disable(GL_RASTERIZER_DISCARD); 5518 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 5519 } 5520 5521 void gl3cts::TransformFeedback::DrawXFBStream::drawForFramebuffer(glw::GLuint stream) 5522 { 5523 /* Functions handler */ 5524 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5525 5526 gl.drawTransformFeedbackStream(GL_TRIANGLES, m_xfb_id, stream); 5527 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedbackStream call failed."); 5528 } 5529 5530 bool gl3cts::TransformFeedback::DrawXFBStream::inspectQueries() 5531 { 5532 /* Functions handler */ 5533 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5534 5535 glw::GLint generated_primitives_to_stream_0 = 0; 5536 glw::GLint generated_primitives_to_stream_1 = 0; 5537 5538 gl.getQueryObjectiv(m_qo_id[0], GL_QUERY_RESULT, &generated_primitives_to_stream_0); 5539 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed."); 5540 5541 gl.getQueryObjectiv(m_qo_id[1], GL_QUERY_RESULT, &generated_primitives_to_stream_1); 5542 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed."); 5543 5544 glw::GLint primitives_written_to_xfb_to_stream_0 = 0; 5545 glw::GLint primitives_written_to_xfb_to_stream_1 = 0; 5546 5547 gl.getQueryObjectiv(m_qo_id[2], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_0); 5548 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed."); 5549 5550 gl.getQueryObjectiv(m_qo_id[3], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_1); 5551 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed."); 5552 5553 if ((generated_primitives_to_stream_0 == 3) && (generated_primitives_to_stream_1 == 3) && 5554 (primitives_written_to_xfb_to_stream_0 == 3) && (primitives_written_to_xfb_to_stream_1 == 3)) 5555 { 5556 return true; 5557 } 5558 5559 return false; 5560 } 5561 5562 bool gl3cts::TransformFeedback::DrawXFBStream::check() 5563 { 5564 /* Functions handler */ 5565 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5566 5567 /* Number of pixels. */ 5568 const glw::GLuint number_of_pixels = s_view_size * s_view_size; 5569 5570 /* Fetch framebuffer. */ 5571 std::vector<glw::GLfloat> pixels(number_of_pixels); 5572 5573 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]); 5574 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 5575 5576 /* Check results. */ 5577 for (glw::GLuint i = 0; i < number_of_pixels; ++i) 5578 { 5579 if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */) 5580 { 5581 return false; 5582 } 5583 } 5584 5585 return true; 5586 } 5587 5588 void gl3cts::TransformFeedback::DrawXFBStream::clean() 5589 { 5590 /* Functions handler */ 5591 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5592 5593 gl.useProgram(0); 5594 5595 if (m_program_id_generate) 5596 { 5597 gl.deleteProgram(m_program_id_generate); 5598 5599 m_program_id_generate = 0; 5600 } 5601 5602 if (m_program_id_draw) 5603 { 5604 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position"); 5605 5606 gl.disableVertexAttribArray(position_location); 5607 5608 gl.deleteProgram(m_program_id_draw); 5609 5610 m_program_id_draw = 0; 5611 } 5612 5613 if (m_xfb_id) 5614 { 5615 gl.deleteTransformFeedbacks(1, &m_xfb_id); 5616 5617 m_xfb_id = 0; 5618 } 5619 5620 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i) 5621 { 5622 if (m_bo_id[i]) 5623 { 5624 gl.deleteBuffers(1, &m_bo_id[i]); 5625 5626 m_bo_id[i] = 0; 5627 } 5628 } 5629 5630 if (m_vao_id) 5631 { 5632 gl.deleteVertexArrays(1, &m_vao_id); 5633 5634 m_vao_id = 0; 5635 } 5636 5637 if (m_fbo_id) 5638 { 5639 gl.deleteFramebuffers(1, &m_fbo_id); 5640 5641 m_fbo_id = 0; 5642 } 5643 5644 if (m_rbo_id) 5645 { 5646 gl.deleteRenderbuffers(1, &m_rbo_id); 5647 5648 m_rbo_id = 0; 5649 } 5650 } 5651 5652 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_blank = "#version 130\n" 5653 "\n" 5654 "void main()\n" 5655 "{\n" 5656 "}\n"; 5657 5658 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_pass = "#version 130\n" 5659 "\n" 5660 "in vec4 position;\n" 5661 "\n" 5662 "void main()\n" 5663 "{\n" 5664 " gl_Position = position;\n" 5665 "}\n"; 5666 5667 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_geometry_shader = 5668 "#version 400\n" 5669 "\n" 5670 "layout(points) in;\n" 5671 "layout(points, max_vertices = 6) out;\n" 5672 "\n" 5673 "layout(stream = 1) out vec4 position;\n" 5674 "\n" 5675 "void main()\n" 5676 "{\n" 5677 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 5678 " EmitStreamVertex(0);\n" 5679 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n" 5680 " EmitStreamVertex(0);\n" 5681 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 5682 " EmitStreamVertex(0);\n" 5683 "\n" 5684 " position = vec4( 1.0, -1.0, 0.0, 1.0);\n" 5685 " EmitStreamVertex(1);\n" 5686 " position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 5687 " EmitStreamVertex(1);\n" 5688 " position = vec4( 1.0, 1.0, 0.0, 1.0);\n" 5689 " EmitStreamVertex(1);\n" 5690 "}\n"; 5691 5692 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_fragment_shader = "#version 130\n" 5693 "\n" 5694 "out vec4 pixel;\n" 5695 "\n" 5696 "void main()\n" 5697 "{\n" 5698 " pixel = vec4(1.0);\n" 5699 "}\n"; 5700 5701 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings[] = { "gl_Position", "gl_NextBuffer", 5702 "position" }; 5703 5704 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings_count = 5705 sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]); 5706 5707 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_bo_size = 5708 3 /* triangles */ * 4 /* vec4 */ * sizeof(glw::GLfloat); 5709 5710 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_view_size = 2; 5711 5712 /*-----------------------------------------------------------------------------------------------*/ 5713 5714 gl3cts::TransformFeedback::DrawXFBInstanced::DrawXFBInstanced(deqp::Context& context, const char* test_name, 5715 const char* test_description) 5716 : deqp::TestCase(context, test_name, test_description) 5717 , m_context(context) 5718 , m_program_id_generate(0) 5719 , m_program_id_draw(0) 5720 , m_vao_id(0) 5721 , m_xfb_id(0) 5722 , m_bo_id_xfb(0) 5723 , m_bo_id_uniform(0) 5724 , m_fbo_id(0) 5725 , m_rbo_id(0) 5726 , m_glGetUniformBlockIndex(DE_NULL) 5727 , m_glUniformBlockBinding(DE_NULL) 5728 { 5729 } 5730 5731 gl3cts::TransformFeedback::DrawXFBInstanced::~DrawXFBInstanced(void) 5732 { 5733 } 5734 5735 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBInstanced::iterate(void) 5736 { 5737 /* Initializations. */ 5738 bool is_at_least_gl_42 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2))); 5739 bool is_at_least_gl_31 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1))); 5740 bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced"); 5741 bool is_arb_ubo = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object"); 5742 5743 bool is_ok = true; 5744 bool test_error = false; 5745 5746 if (is_arb_ubo) 5747 { 5748 m_glGetUniformBlockIndex = 5749 (GetUniformBlockIndex_ProcAddress)m_context.getRenderContext().getProcAddress("glGetUniformBlockIndex"); 5750 5751 m_glUniformBlockBinding = 5752 (UniformBlockBinding_ProcAddress)m_context.getRenderContext().getProcAddress("glUniformBlockBinding"); 5753 5754 if (DE_NULL == m_glGetUniformBlockIndex || DE_NULL == m_glUniformBlockBinding) 5755 { 5756 throw 0; 5757 } 5758 } 5759 5760 try 5761 { 5762 if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_tf_instanced)) 5763 { 5764 prepareObjects(); 5765 drawForXFB(); 5766 drawInstanced(); 5767 5768 is_ok = is_ok && check(); 5769 } 5770 } 5771 catch (...) 5772 { 5773 is_ok = false; 5774 test_error = true; 5775 } 5776 5777 /* Clean GL objects */ 5778 clean(); 5779 5780 /* Result's setup. */ 5781 if (is_ok) 5782 { 5783 /* Log success. */ 5784 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have passed." 5785 << tcu::TestLog::EndMessage; 5786 5787 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5788 } 5789 else 5790 { 5791 if (test_error) 5792 { 5793 /* Log error. */ 5794 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have approached error." 5795 << tcu::TestLog::EndMessage; 5796 5797 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 5798 } 5799 else 5800 { 5801 /* Log fail. */ 5802 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have failed." 5803 << tcu::TestLog::EndMessage; 5804 5805 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 5806 } 5807 } 5808 5809 return STOP; 5810 } 5811 5812 void gl3cts::TransformFeedback::DrawXFBInstanced::prepareObjects() 5813 { 5814 /* Functions handler */ 5815 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5816 5817 /* Prepare programs. */ 5818 m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram( 5819 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_generate, s_fragment_shader, 5820 &s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS); 5821 5822 if (0 == m_program_id_generate) 5823 { 5824 throw 0; 5825 } 5826 5827 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram( 5828 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader, NULL, 0, 5829 GL_INTERLEAVED_ATTRIBS); 5830 5831 if (0 == m_program_id_draw) 5832 { 5833 throw 0; 5834 } 5835 5836 /* Prepare transform feedbacks. */ 5837 gl.genTransformFeedbacks(1, &m_xfb_id); 5838 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 5839 5840 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id); 5841 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed."); 5842 5843 /* Create empty Vertex Array Object */ 5844 gl.genVertexArrays(1, &m_vao_id); 5845 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 5846 5847 gl.bindVertexArray(m_vao_id); 5848 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 5849 5850 /* Prepare xfb buffer object. */ 5851 gl.genBuffers(1, &m_bo_id_xfb); 5852 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 5853 5854 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb); 5855 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5856 5857 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */ 5858 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 5859 5860 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb); 5861 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 5862 5863 /* Prepare uniform buffer object. */ 5864 gl.genBuffers(1, &m_bo_id_uniform); 5865 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 5866 5867 gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform); 5868 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5869 5870 gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */ 5871 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 5872 5873 gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform); 5874 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 5875 5876 glw::GLuint uniform_index = m_glGetUniformBlockIndex(m_program_id_draw, s_uniform); 5877 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed."); 5878 5879 if (GL_INVALID_INDEX == uniform_index) 5880 { 5881 throw 0; 5882 } 5883 5884 m_glUniformBlockBinding(m_program_id_draw, uniform_index, 0); 5885 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed."); 5886 5887 /* Prepare framebuffer. */ 5888 gl.clearColor(0.f, 0.f, 0.f, 1.f); 5889 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 5890 5891 gl.genFramebuffers(1, &m_fbo_id); 5892 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed."); 5893 5894 gl.genRenderbuffers(1, &m_rbo_id); 5895 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed."); 5896 5897 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 5898 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); 5899 5900 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id); 5901 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed."); 5902 5903 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size); 5904 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed."); 5905 5906 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id); 5907 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed."); 5908 5909 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 5910 { 5911 throw 0; 5912 } 5913 5914 gl.viewport(0, 0, s_view_size, s_view_size); 5915 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed."); 5916 } 5917 5918 void gl3cts::TransformFeedback::DrawXFBInstanced::drawForXFB() 5919 { 5920 /* Functions handler */ 5921 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5922 5923 gl.useProgram(m_program_id_generate); 5924 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 5925 5926 gl.enable(GL_RASTERIZER_DISCARD); 5927 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 5928 5929 gl.beginTransformFeedback(GL_POINTS); 5930 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 5931 5932 gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */); 5933 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 5934 5935 gl.endTransformFeedback(); 5936 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 5937 5938 gl.disable(GL_RASTERIZER_DISCARD); 5939 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 5940 } 5941 5942 void gl3cts::TransformFeedback::DrawXFBInstanced::drawInstanced() 5943 { 5944 /* Functions handler */ 5945 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5946 5947 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb); 5948 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 5949 5950 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position"); 5951 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 5952 5953 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL); 5954 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); 5955 5956 gl.enableVertexAttribArray(position_location); 5957 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 5958 5959 gl.clear(GL_COLOR_BUFFER_BIT); 5960 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 5961 5962 gl.useProgram(m_program_id_draw); 5963 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 5964 5965 gl.drawTransformFeedbackInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 4); 5966 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 5967 } 5968 5969 bool gl3cts::TransformFeedback::DrawXFBInstanced::check() 5970 { 5971 /* Functions handler */ 5972 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5973 5974 /* Number of pixels. */ 5975 const glw::GLuint number_of_pixels = s_view_size * s_view_size; 5976 5977 /* Fetch framebuffer. */ 5978 std::vector<glw::GLfloat> pixels(number_of_pixels); 5979 5980 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]); 5981 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 5982 5983 /* Check results. */ 5984 for (glw::GLuint i = 0; i < number_of_pixels; ++i) 5985 { 5986 if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */) 5987 { 5988 return false; 5989 } 5990 } 5991 5992 return true; 5993 } 5994 5995 void gl3cts::TransformFeedback::DrawXFBInstanced::clean() 5996 { 5997 /* Functions handler */ 5998 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5999 6000 gl.useProgram(0); 6001 6002 if (m_program_id_generate) 6003 { 6004 gl.deleteProgram(m_program_id_generate); 6005 6006 m_program_id_generate = 0; 6007 } 6008 6009 if (m_program_id_draw) 6010 { 6011 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position"); 6012 6013 gl.disableVertexAttribArray(position_location); 6014 6015 gl.deleteProgram(m_program_id_draw); 6016 6017 m_program_id_draw = 0; 6018 } 6019 6020 if (m_xfb_id) 6021 { 6022 gl.deleteTransformFeedbacks(1, &m_xfb_id); 6023 6024 m_xfb_id = 0; 6025 } 6026 6027 if (m_bo_id_xfb) 6028 { 6029 gl.deleteBuffers(1, &m_bo_id_xfb); 6030 6031 m_bo_id_xfb = 0; 6032 } 6033 6034 if (m_bo_id_uniform) 6035 { 6036 gl.deleteBuffers(1, &m_bo_id_uniform); 6037 6038 m_bo_id_uniform = 0; 6039 } 6040 6041 if (m_vao_id) 6042 { 6043 gl.deleteVertexArrays(1, &m_vao_id); 6044 6045 m_vao_id = 0; 6046 } 6047 6048 if (m_fbo_id) 6049 { 6050 gl.deleteFramebuffers(1, &m_fbo_id); 6051 6052 m_fbo_id = 0; 6053 } 6054 6055 if (m_rbo_id) 6056 { 6057 gl.deleteRenderbuffers(1, &m_rbo_id); 6058 6059 m_rbo_id = 0; 6060 } 6061 } 6062 6063 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_generate = 6064 "#version 140\n" 6065 "\n" 6066 "void main()\n" 6067 "{\n" 6068 " switch(gl_VertexID % 4)\n" 6069 " {\n" 6070 " case 0:\n" 6071 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 6072 " break;\n" 6073 " case 1:\n" 6074 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n" 6075 " break;\n" 6076 " case 2:\n" 6077 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 6078 " break;\n" 6079 " case 3:\n" 6080 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n" 6081 " break;\n" 6082 " }\n" 6083 "}\n"; 6084 6085 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_draw = 6086 "#version 140\n" 6087 "\n" 6088 "uniform MatrixBlock\n" 6089 "{\n" 6090 " mat4 transformation_0;\n" 6091 " mat4 transformation_1;\n" 6092 " mat4 transformation_2;\n" 6093 " mat4 transformation_3;\n" 6094 "};\n" 6095 "\n" 6096 "in vec4 position;\n" 6097 "\n" 6098 "void main()\n" 6099 "{\n" 6100 " switch(gl_InstanceID % 4)\n" 6101 " {\n" 6102 " case 0:\n" 6103 " gl_Position = position * transformation_0;\n" 6104 " break;\n" 6105 " case 1:\n" 6106 " gl_Position = position * transformation_1;\n" 6107 " break;\n" 6108 " case 2:\n" 6109 " gl_Position = position * transformation_2;\n" 6110 " break;\n" 6111 " case 3:\n" 6112 " gl_Position = position * transformation_3;\n" 6113 " break;\n" 6114 " }\n" 6115 "}\n"; 6116 6117 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_fragment_shader = "#version 130\n" 6118 "\n" 6119 "out vec4 pixel;\n" 6120 "\n" 6121 "void main()\n" 6122 "{\n" 6123 " pixel = vec4(1.0);\n" 6124 "}\n"; 6125 6126 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_xfb_varying = "gl_Position"; 6127 6128 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_uniform = "MatrixBlock"; 6129 6130 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_xfb_size = 6131 4 /* vertex count */ * 4 /* vec4 components */ 6132 * sizeof(glw::GLfloat) /* data type size */; 6133 6134 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_data[] = { 6135 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, 6136 6137 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, 6138 6139 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, 6140 6141 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 6142 }; 6143 6144 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data); 6145 6146 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_view_size = 4; 6147 6148 /*-----------------------------------------------------------------------------------------------*/ 6149 6150 gl3cts::TransformFeedback::DrawXFBStreamInstanced::DrawXFBStreamInstanced(deqp::Context& context, const char* test_name, 6151 const char* test_description) 6152 : deqp::TestCase(context, test_name, test_description) 6153 , m_context(context) 6154 , m_program_id_generate(0) 6155 , m_program_id_draw(0) 6156 , m_vao_id(0) 6157 , m_xfb_id(0) 6158 , m_bo_id_xfb_position(0) 6159 , m_bo_id_xfb_color(0) 6160 , m_bo_id_uniform(0) 6161 , m_fbo_id(0) 6162 , m_rbo_id(0) 6163 , m_glGetUniformBlockIndex(DE_NULL) 6164 , m_glUniformBlockBinding(DE_NULL) 6165 { 6166 } 6167 6168 gl3cts::TransformFeedback::DrawXFBStreamInstanced::~DrawXFBStreamInstanced(void) 6169 { 6170 } 6171 6172 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStreamInstanced::iterate(void) 6173 { 6174 /* Initializations. */ 6175 bool is_at_least_gl_31 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1))); 6176 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0))); 6177 bool is_at_least_gl_42 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2))); 6178 bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced"); 6179 bool is_arb_ubo = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object"); 6180 bool is_arb_gpu_shader5 = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"); 6181 6182 bool is_ok = true; 6183 bool test_error = false; 6184 6185 if (is_arb_ubo) 6186 { 6187 m_glGetUniformBlockIndex = 6188 (GetUniformBlockIndex_ProcAddress)m_context.getRenderContext().getProcAddress("glGetUniformBlockIndex"); 6189 6190 m_glUniformBlockBinding = 6191 (UniformBlockBinding_ProcAddress)m_context.getRenderContext().getProcAddress("glUniformBlockBinding"); 6192 6193 if (DE_NULL == m_glGetUniformBlockIndex || DE_NULL == m_glUniformBlockBinding) 6194 { 6195 throw 0; 6196 } 6197 } 6198 6199 /* Test. */ 6200 try 6201 { 6202 if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_gpu_shader5 && is_arb_tf_instanced) || 6203 (is_at_least_gl_40 && is_arb_tf_instanced)) 6204 { 6205 prepareObjects(); 6206 drawForXFB(); 6207 drawStreamInstanced(); 6208 6209 is_ok = is_ok && check(); 6210 } 6211 } 6212 catch (...) 6213 { 6214 is_ok = false; 6215 test_error = true; 6216 } 6217 6218 /* Clean GL objects */ 6219 clean(); 6220 6221 /* Result's setup. */ 6222 if (is_ok) 6223 { 6224 /* Log success. */ 6225 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream Instanced have passed." 6226 << tcu::TestLog::EndMessage; 6227 6228 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 6229 } 6230 else 6231 { 6232 if (test_error) 6233 { 6234 /* Log error. */ 6235 m_context.getTestContext().getLog() << tcu::TestLog::Message 6236 << "Draw XFB Stream Instanced have approached error." 6237 << tcu::TestLog::EndMessage; 6238 6239 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 6240 } 6241 else 6242 { 6243 /* Log fail. */ 6244 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream Instanced have failed." 6245 << tcu::TestLog::EndMessage; 6246 6247 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 6248 } 6249 } 6250 6251 return STOP; 6252 } 6253 6254 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::prepareObjects() 6255 { 6256 /* Functions handler */ 6257 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6258 6259 /* Prepare programs. */ 6260 m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram( 6261 gl, m_context.getTestContext().getLog(), s_geometry_shader_generate, NULL, NULL, s_vertex_shader_blank, 6262 s_fragment_shader_blank, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS); 6263 6264 if (0 == m_program_id_generate) 6265 { 6266 throw 0; 6267 } 6268 6269 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram( 6270 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader_draw, NULL, 6271 0, GL_INTERLEAVED_ATTRIBS); 6272 6273 if (0 == m_program_id_draw) 6274 { 6275 throw 0; 6276 } 6277 6278 /* Prepare transform feedbacks. */ 6279 gl.genTransformFeedbacks(1, &m_xfb_id); 6280 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed."); 6281 6282 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id); 6283 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed."); 6284 6285 /* Create empty Vertex Array Object */ 6286 gl.genVertexArrays(1, &m_vao_id); 6287 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 6288 6289 gl.bindVertexArray(m_vao_id); 6290 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 6291 6292 /* Prepare xfb buffer objects. */ 6293 gl.genBuffers(1, &m_bo_id_xfb_position); 6294 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 6295 6296 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_position); 6297 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 6298 6299 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */ 6300 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 6301 6302 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb_position); 6303 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 6304 6305 gl.genBuffers(1, &m_bo_id_xfb_color); 6306 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 6307 6308 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_color); 6309 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 6310 6311 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */ 6312 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 6313 6314 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, m_bo_id_xfb_color); 6315 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 6316 6317 /* Prepare uniform buffer object. */ 6318 gl.genBuffers(1, &m_bo_id_uniform); 6319 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed."); 6320 6321 gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform); 6322 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 6323 6324 gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */ 6325 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed."); 6326 6327 gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform); 6328 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed."); 6329 6330 glw::GLuint uniform_index = m_glGetUniformBlockIndex(m_program_id_draw, s_uniform); 6331 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed."); 6332 6333 if (GL_INVALID_INDEX == uniform_index) 6334 { 6335 throw 0; 6336 } 6337 6338 m_glUniformBlockBinding(m_program_id_draw, uniform_index, 0); 6339 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed."); 6340 6341 /* Prepare framebuffer. */ 6342 gl.clearColor(0.f, 0.f, 0.f, 1.f); 6343 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 6344 6345 gl.genFramebuffers(1, &m_fbo_id); 6346 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed."); 6347 6348 gl.genRenderbuffers(1, &m_rbo_id); 6349 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed."); 6350 6351 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 6352 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); 6353 6354 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id); 6355 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed."); 6356 6357 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size); 6358 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed."); 6359 6360 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id); 6361 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed."); 6362 6363 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 6364 { 6365 throw 0; 6366 } 6367 6368 gl.viewport(0, 0, s_view_size, s_view_size); 6369 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed."); 6370 } 6371 6372 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawForXFB() 6373 { 6374 /* Functions handler */ 6375 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6376 6377 gl.useProgram(m_program_id_generate); 6378 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 6379 6380 gl.enable(GL_RASTERIZER_DISCARD); 6381 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); 6382 6383 gl.beginTransformFeedback(GL_POINTS); 6384 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); 6385 6386 gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */); 6387 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 6388 6389 gl.endTransformFeedback(); 6390 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); 6391 6392 gl.disable(GL_RASTERIZER_DISCARD); 6393 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); 6394 } 6395 6396 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawStreamInstanced() 6397 { 6398 /* Functions handler */ 6399 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6400 6401 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_position); 6402 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 6403 6404 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position"); 6405 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 6406 6407 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL); 6408 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); 6409 6410 gl.enableVertexAttribArray(position_location); 6411 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 6412 6413 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_color); 6414 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); 6415 6416 glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color"); 6417 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed."); 6418 6419 gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, 0, NULL); 6420 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed."); 6421 6422 gl.enableVertexAttribArray(color_location); 6423 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed."); 6424 6425 gl.useProgram(m_program_id_draw); 6426 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); 6427 6428 gl.drawTransformFeedbackStreamInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 0, 4); 6429 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); 6430 } 6431 6432 bool gl3cts::TransformFeedback::DrawXFBStreamInstanced::check() 6433 { 6434 /* Functions handler */ 6435 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6436 6437 /* Number of pixels. */ 6438 const glw::GLuint number_of_pixels = s_view_size * s_view_size; 6439 6440 /* Fetch framebuffer. */ 6441 std::vector<glw::GLfloat> pixels(number_of_pixels); 6442 6443 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]); 6444 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed."); 6445 6446 /* Check results. */ 6447 for (glw::GLuint i = 0; i < number_of_pixels; ++i) 6448 { 6449 if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */) 6450 { 6451 return false; 6452 } 6453 } 6454 6455 return true; 6456 } 6457 6458 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::clean() 6459 { 6460 /* Functions handler */ 6461 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 6462 6463 gl.useProgram(0); 6464 6465 if (m_program_id_generate) 6466 { 6467 gl.deleteProgram(m_program_id_generate); 6468 6469 m_program_id_generate = 0; 6470 } 6471 6472 if (m_program_id_draw) 6473 { 6474 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position"); 6475 6476 gl.disableVertexAttribArray(position_location); 6477 6478 glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color"); 6479 6480 gl.disableVertexAttribArray(color_location); 6481 6482 gl.deleteProgram(m_program_id_draw); 6483 6484 m_program_id_draw = 0; 6485 } 6486 6487 if (m_xfb_id) 6488 { 6489 gl.deleteTransformFeedbacks(1, &m_xfb_id); 6490 6491 m_xfb_id = 0; 6492 } 6493 6494 if (m_bo_id_xfb_position) 6495 { 6496 gl.deleteBuffers(1, &m_bo_id_xfb_position); 6497 6498 m_bo_id_xfb_position = 0; 6499 } 6500 6501 if (m_bo_id_xfb_color) 6502 { 6503 gl.deleteBuffers(1, &m_bo_id_xfb_color); 6504 6505 m_bo_id_xfb_position = 0; 6506 } 6507 6508 if (m_bo_id_uniform) 6509 { 6510 gl.deleteBuffers(1, &m_bo_id_uniform); 6511 6512 m_bo_id_uniform = 0; 6513 } 6514 6515 if (m_vao_id) 6516 { 6517 gl.deleteVertexArrays(1, &m_vao_id); 6518 6519 m_vao_id = 0; 6520 } 6521 6522 if (m_fbo_id) 6523 { 6524 gl.deleteFramebuffers(1, &m_fbo_id); 6525 6526 m_fbo_id = 0; 6527 } 6528 6529 if (m_rbo_id) 6530 { 6531 gl.deleteRenderbuffers(1, &m_rbo_id); 6532 6533 m_rbo_id = 0; 6534 } 6535 } 6536 6537 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_blank = "#version 140\n" 6538 "\n" 6539 "void main()\n" 6540 "{\n" 6541 "}\n"; 6542 6543 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_geometry_shader_generate = 6544 "#version 400\n" 6545 "\n" 6546 "layout(points) in;\n" 6547 "layout(points, max_vertices = 8) out;\n" 6548 "\n" 6549 "layout(stream = 1) out vec4 color;\n" 6550 "\n" 6551 "void main()\n" 6552 "{\n" 6553 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 6554 " EmitStreamVertex(0);\n" 6555 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n" 6556 " EmitStreamVertex(0);\n" 6557 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 6558 " EmitStreamVertex(0);\n" 6559 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n" 6560 " EmitStreamVertex(0);\n" 6561 "\n" 6562 " color = vec4(1.0, 1.0, 1.0, 1.0);\n" 6563 " EmitStreamVertex(1);\n" 6564 " color = vec4(1.0, 1.0, 1.0, 1.0);\n" 6565 " EmitStreamVertex(1);\n" 6566 " color = vec4(1.0, 1.0, 1.0, 1.0);\n" 6567 " EmitStreamVertex(1);\n" 6568 " color = vec4(1.0, 1.0, 1.0, 1.0);\n" 6569 " EmitStreamVertex(1);\n" 6570 "}\n"; 6571 6572 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_draw = 6573 "#version 140\n" 6574 "\n" 6575 "uniform MatrixBlock\n" 6576 "{\n" 6577 " mat4 transformation_0;\n" 6578 " mat4 transformation_1;\n" 6579 " mat4 transformation_2;\n" 6580 " mat4 transformation_3;\n" 6581 "};\n" 6582 "\n" 6583 "in vec4 position;\n" 6584 "in vec4 color;\n" 6585 "out vec4 colour;\n" 6586 "\n" 6587 "void main()\n" 6588 "{\n" 6589 " switch(gl_InstanceID % 4)\n" 6590 " {\n" 6591 " case 0:\n" 6592 " gl_Position = position * transformation_0;\n" 6593 " break;\n" 6594 " case 1:\n" 6595 " gl_Position = position * transformation_1;\n" 6596 " break;\n" 6597 " case 2:\n" 6598 " gl_Position = position * transformation_2;\n" 6599 " break;\n" 6600 " case 3:\n" 6601 " gl_Position = position * transformation_3;\n" 6602 " break;\n" 6603 " }\n" 6604 " colour = color;\n" 6605 "}\n"; 6606 6607 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_blank = 6608 "#version 130\n" 6609 "\n" 6610 "out vec4 pixel;\n" 6611 "\n" 6612 "void main()\n" 6613 "{\n" 6614 " pixel = vec4(1.0);\n" 6615 "}\n"; 6616 6617 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_draw = "#version 130\n" 6618 "\n" 6619 "in vec4 colour;\n" 6620 "out vec4 pixel;\n" 6621 "\n" 6622 "void main()\n" 6623 "{\n" 6624 " pixel = colour;\n" 6625 "}\n"; 6626 6627 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings[] = { "gl_Position", 6628 "gl_NextBuffer", "color" }; 6629 6630 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings_count = 6631 sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]); 6632 6633 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_uniform = "MatrixBlock"; 6634 6635 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_xfb_size = 6636 4 /* vertex count */ * 4 /* vec4 components */ 6637 * sizeof(glw::GLfloat) /* data type size */; 6638 6639 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_data[] = { 6640 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, 6641 6642 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, 6643 6644 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, 6645 6646 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 6647 }; 6648 6649 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data); 6650 6651 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_view_size = 4; 6652 6653 /*-----------------------------------------------------------------------------------------------*/ 6654 6655 glw::GLuint gl3cts::TransformFeedback::Utilities::buildProgram( 6656 glw::Functions const& gl, tcu::TestLog& log, glw::GLchar const* const geometry_shader_source, 6657 glw::GLchar const* const tessellation_control_shader_source, 6658 glw::GLchar const* const tessellation_evaluation_shader_source, glw::GLchar const* const vertex_shader_source, 6659 glw::GLchar const* const fragment_shader_source, glw::GLchar const* const* const transform_feedback_varyings, 6660 glw::GLsizei const transform_feedback_varyings_count, glw::GLenum const transform_feedback_varyings_mode, 6661 bool const do_not_detach, glw::GLint* linking_status) 6662 { 6663 glw::GLuint program = 0; 6664 6665 struct Shader 6666 { 6667 glw::GLchar const* const source; 6668 glw::GLenum const type; 6669 glw::GLuint id; 6670 } shader[] = { { geometry_shader_source, GL_GEOMETRY_SHADER, 0 }, 6671 { tessellation_control_shader_source, GL_TESS_CONTROL_SHADER, 0 }, 6672 { tessellation_evaluation_shader_source, GL_TESS_EVALUATION_SHADER, 0 }, 6673 { vertex_shader_source, GL_VERTEX_SHADER, 0 }, 6674 { fragment_shader_source, GL_FRAGMENT_SHADER, 0 } }; 6675 6676 glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]); 6677 6678 try 6679 { 6680 /* Create program. */ 6681 program = gl.createProgram(); 6682 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed."); 6683 6684 /* Shader compilation. */ 6685 6686 for (glw::GLuint i = 0; i < shader_count; ++i) 6687 { 6688 if (DE_NULL != shader[i].source) 6689 { 6690 shader[i].id = gl.createShader(shader[i].type); 6691 6692 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed."); 6693 6694 gl.attachShader(program, shader[i].id); 6695 6696 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed."); 6697 6698 gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL); 6699 6700 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed."); 6701 6702 gl.compileShader(shader[i].id); 6703 6704 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed."); 6705 6706 glw::GLint status = GL_FALSE; 6707 6708 gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status); 6709 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed."); 6710 6711 if (GL_FALSE == status) 6712 { 6713 glw::GLint log_size = 0; 6714 gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size); 6715 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed."); 6716 6717 glw::GLchar* log_text = new glw::GLchar[log_size]; 6718 6719 gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]); 6720 6721 log << tcu::TestLog::Message << "Shader compilation has failed.\n" 6722 << "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n" 6723 << "Shader compilation error log:\n" 6724 << log_text << "\n" 6725 << "Shader source code:\n" 6726 << shader[i].source << "\n" 6727 << tcu::TestLog::EndMessage; 6728 6729 delete[] log_text; 6730 6731 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed."); 6732 6733 throw 0; 6734 } 6735 } 6736 } 6737 6738 /* Link. */ 6739 if (transform_feedback_varyings_count) 6740 { 6741 gl.transformFeedbackVaryings(program, transform_feedback_varyings_count, transform_feedback_varyings, 6742 transform_feedback_varyings_mode); 6743 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed."); 6744 } 6745 6746 gl.linkProgram(program); 6747 6748 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed."); 6749 6750 glw::GLint status = GL_FALSE; 6751 6752 gl.getProgramiv(program, GL_LINK_STATUS, &status); 6753 6754 if (DE_NULL != linking_status) 6755 { 6756 *linking_status = status; 6757 } 6758 6759 if (GL_TRUE == status) 6760 { 6761 if (!do_not_detach) 6762 { 6763 for (glw::GLuint i = 0; i < shader_count; ++i) 6764 { 6765 if (shader[i].id) 6766 { 6767 gl.detachShader(program, shader[i].id); 6768 6769 GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed."); 6770 } 6771 } 6772 } 6773 } 6774 else 6775 { 6776 glw::GLint log_size = 0; 6777 6778 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &log_size); 6779 6780 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed."); 6781 6782 glw::GLchar* log_text = new glw::GLchar[log_size]; 6783 6784 gl.getProgramInfoLog(program, log_size, NULL, &log_text[0]); 6785 6786 log << tcu::TestLog::Message << "Program linkage has failed due to:\n" 6787 << log_text << "\n" 6788 << tcu::TestLog::EndMessage; 6789 6790 delete[] log_text; 6791 6792 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed."); 6793 6794 throw 0; 6795 } 6796 } 6797 catch (...) 6798 { 6799 if (program) 6800 { 6801 gl.deleteProgram(program); 6802 6803 program = 0; 6804 } 6805 } 6806 6807 for (glw::GLuint i = 0; i < shader_count; ++i) 6808 { 6809 if (0 != shader[i].id) 6810 { 6811 gl.deleteShader(shader[i].id); 6812 6813 shader[i].id = 0; 6814 } 6815 } 6816 6817 return program; 6818 } 6819 6820 /** @brief Substitute key with value within source code. 6821 * 6822 * @param [in] source Source code to be prerocessed. 6823 * @param [in] key Key to be substituted. 6824 * @param [in] value Value to be inserted. 6825 * 6826 * @return Resulting string. 6827 */ 6828 std::string gl3cts::TransformFeedback::Utilities::preprocessCode(std::string source, std::string key, std::string value) 6829 { 6830 std::string destination = source; 6831 6832 while (true) 6833 { 6834 /* Find token in source code. */ 6835 size_t position = destination.find(key, 0); 6836 6837 /* No more occurences of this key. */ 6838 if (position == std::string::npos) 6839 { 6840 break; 6841 } 6842 6843 /* Replace token with sub_code. */ 6844 destination.replace(position, key.size(), value); 6845 } 6846 6847 return destination; 6848 } 6849 6850 /** @brief Convert an integer to a string. 6851 * 6852 * @param [in] i Integer to be converted. 6853 * 6854 * @return String representing integer. 6855 */ 6856 std::string gl3cts::TransformFeedback::Utilities::itoa(glw::GLint i) 6857 { 6858 std::stringstream stream; 6859 6860 stream << i; 6861 6862 return stream.str(); 6863 } 6864 6865 /** @brief Convert an float to a string. 6866 * 6867 * @param [in] f Float to be converted. 6868 * 6869 * @return String representing integer. 6870 */ 6871 std::string gl3cts::TransformFeedback::Utilities::ftoa(glw::GLfloat f) 6872 { 6873 std::stringstream stream; 6874 6875 stream << f; 6876 6877 return stream.str(); 6878 } 6879