1 #ifndef _ESEXTCGEOMETRYSHADERLIMITS_HPP 2 #define _ESEXTCGEOMETRYSHADERLIMITS_HPP 3 /*------------------------------------------------------------------------- 4 * OpenGL Conformance Test Suite 5 * ----------------------------- 6 * 7 * Copyright (c) 2014-2016 The Khronos Group Inc. 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 */ /*! 22 * \file 23 * \brief 24 */ /*-------------------------------------------------------------------*/ 25 26 /*! 27 * \file esextcGeometryShaderLimits.hpp 28 * \brief Geometry Shader Limits (Test Group 16) 29 */ /*-------------------------------------------------------------------*/ 30 31 #include "../esextcTestCaseBase.hpp" 32 33 #include <vector> 34 35 namespace glcts 36 { 37 /** Parent class for geometry shader Test Group 16 tests 38 * based on fetching result via transfrom feedback. 39 **/ 40 class GeometryShaderLimitsTransformFeedbackBase : public TestCaseBase 41 { 42 public: 43 /* Public methods */ 44 virtual void deinit(void); 45 virtual IterateResult iterate(void); 46 47 protected: 48 /* Protected methods */ 49 GeometryShaderLimitsTransformFeedbackBase(Context& context, const ExtParameters& extParams, const char* name, 50 const char* description); 51 52 virtual ~GeometryShaderLimitsTransformFeedbackBase() 53 { 54 } 55 56 void initTest(void); 57 58 /* Methods to be overriden by inheriting test cases */ 59 virtual void clean() = 0; 60 61 virtual void getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names, 62 glw::GLuint& out_n_captured_varyings) = 0; 63 64 virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, 65 glw::GLuint& out_n_fragment_shader_parts, 66 const glw::GLchar* const*& out_geometry_shader_parts, 67 glw::GLuint& out_n_geometry_shader_parts, 68 const glw::GLchar* const*& out_vertex_shader_parts, 69 glw::GLuint& out_n_vertex_shader_parts) = 0; 70 71 virtual void getTransformFeedbackBufferSize(glw::GLuint& out_buffer_size) = 0; 72 virtual void prepareProgramInput() = 0; 73 virtual bool verifyResult(const void* data) = 0; 74 75 /* Protected fields */ 76 /* Program and shader ids */ 77 glw::GLuint m_fragment_shader_id; 78 glw::GLuint m_geometry_shader_id; 79 glw::GLuint m_program_object_id; 80 glw::GLuint m_vertex_shader_id; 81 82 /* Buffer object used in transform feedback */ 83 glw::GLuint m_buffer_object_id; 84 85 /* Vertex array object */ 86 glw::GLuint m_vertex_array_object_id; 87 88 private: 89 /* Private fields */ 90 /* Shaders' code */ 91 const glw::GLchar* const* m_fragment_shader_parts; 92 const glw::GLchar* const* m_geometry_shader_parts; 93 const glw::GLchar* const* m_vertex_shader_parts; 94 95 glw::GLuint m_n_fragment_shader_parts; 96 glw::GLuint m_n_geometry_shader_parts; 97 glw::GLuint m_n_vertex_shader_parts; 98 99 /* Names of varyings */ 100 const glw::GLchar* const* m_captured_varyings_names; 101 glw::GLuint m_n_captured_varyings; 102 103 /* Size of buffer used by transform feedback */ 104 glw::GLuint m_buffer_size; 105 }; 106 107 /** Parent class for geometry shader Test Group 16 tests 108 * based on fetching result via rendering to texture. 109 **/ 110 class GeometryShaderLimitsRenderingBase : public TestCaseBase 111 { 112 public: 113 /* Public methods */ 114 virtual void deinit(void); 115 virtual IterateResult iterate(void); 116 117 protected: 118 /* Protected methods */ 119 GeometryShaderLimitsRenderingBase(Context& context, const ExtParameters& extParams, const char* name, 120 const char* description); 121 122 virtual ~GeometryShaderLimitsRenderingBase() 123 { 124 } 125 126 void initTest(void); 127 128 /* Methods to be overriden by child test cases */ 129 virtual void clean() = 0; 130 131 virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices) = 0; 132 133 virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, 134 glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width, 135 glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size) = 0; 136 137 virtual void getRequiredPointSize(glw::GLfloat& out_point_size) = 0; 138 139 virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, 140 glw::GLuint& out_n_fragment_shader_parts, 141 const glw::GLchar* const*& out_geometry_shader_parts, 142 glw::GLuint& out_n_geometry_shader_parts, 143 const glw::GLchar* const*& out_vertex_shader_parts, 144 glw::GLuint& out_n_vertex_shader_parts) = 0; 145 146 virtual void prepareProgramInput() = 0; 147 virtual bool verifyResult(const void* data) = 0; 148 149 /* Protected fields */ 150 /* Program and shader ids */ 151 glw::GLuint m_fragment_shader_id; 152 glw::GLuint m_geometry_shader_id; 153 glw::GLuint m_program_object_id; 154 glw::GLuint m_vertex_shader_id; 155 156 /* Framebuffer object id */ 157 glw::GLuint m_framebuffer_object_id; 158 glw::GLuint m_color_texture_id; 159 160 /* Vertex array object */ 161 glw::GLuint m_vertex_array_object_id; 162 163 private: 164 /* Private fields */ 165 /* Shaders' code */ 166 const glw::GLchar* const* m_fragment_shader_parts; 167 const glw::GLchar* const* m_geometry_shader_parts; 168 const glw::GLchar* const* m_vertex_shader_parts; 169 170 glw::GLuint m_n_fragment_shader_parts; 171 glw::GLuint m_n_geometry_shader_parts; 172 glw::GLuint m_n_vertex_shader_parts; 173 174 /* Framebuffer dimensions */ 175 glw::GLenum m_texture_format; 176 glw::GLuint m_texture_height; 177 glw::GLuint m_texture_pixel_size; 178 glw::GLenum m_texture_read_format; 179 glw::GLenum m_texture_read_type; 180 glw::GLuint m_texture_width; 181 }; 182 183 /** Implementation of test case 16.1. Test description follows: 184 * 185 * Make sure it is possible to use as many uniform components as defined 186 * by GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 187 * 188 * Category: API; 189 * Functional Test. 190 * 191 * 1. Create a fragment, geometry and vertex shader objects: 192 * 193 * - Vertex shader code can be boilerplate; 194 * - Geometry shader code should define 195 * floor(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT / 4) uniform ivec4 196 * variables. It should take points as input and output, a maximum of 197 * 1 vertex will be written by the shader. In main(), the shader should 198 * set output int variable named result to a sum of all the vectors' 199 * components and emit a vertex. 200 * - Fragment shader code can be boilerplate. 201 * 202 * 2. The program object consisting of these shader objects is expected to 203 * link successfully. 204 * 205 * 3. Configure the uniforms to use subsequently increasing values, starting 206 * from 1 for R component of first vector, 2 for G component of that vector, 207 * 5 for first component of second vector, and so on. 208 * 209 * 4. Configure transform feedback object to capture output from result. 210 * Draw a single point. The test succeeds if first component of the result 211 * vector contains a valid value (bearing potentially minor precision issues 212 * in mind) 213 **/ 214 class GeometryShaderMaxUniformComponentsTest : public GeometryShaderLimitsTransformFeedbackBase 215 { 216 public: 217 /* Public methods */ 218 GeometryShaderMaxUniformComponentsTest(Context& context, const ExtParameters& extParams, const char* name, 219 const char* description); 220 221 virtual ~GeometryShaderMaxUniformComponentsTest() 222 { 223 } 224 225 protected: 226 /* Overriden from GeometryShaderLimitsTransformFeedbackBase */ 227 virtual void clean(); 228 229 virtual void getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names, 230 glw::GLuint& out_n_captured_varyings); 231 232 virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, 233 glw::GLuint& out_n_fragment_shader_parts, 234 const glw::GLchar* const*& out_geometry_shader_parts, 235 glw::GLuint& out_n_geometry_shader_parts, 236 const glw::GLchar* const*& out_vertex_shader_parts, 237 glw::GLuint& out_n_vertex_shader_parts); 238 239 virtual void getTransformFeedbackBufferSize(glw::GLuint& out_buffer_size); 240 virtual void prepareProgramInput(); 241 virtual bool verifyResult(const void* data); 242 243 private: 244 /* Private fields */ 245 /* Shaders' code */ 246 static const glw::GLchar* const m_fragment_shader_code; 247 static const glw::GLchar* const m_geometry_shader_code_preamble; 248 static const glw::GLchar* const m_geometry_shader_code_number_of_uniforms; 249 static const glw::GLchar* const m_geometry_shader_code_body; 250 static const glw::GLchar* const m_vertex_shader_code; 251 252 const glw::GLchar* m_geometry_shader_parts[4]; 253 254 /* String used to store number of uniform vectors */ 255 std::string m_max_uniform_vectors_string; 256 257 /* Varying names */ 258 static const glw::GLchar* const m_captured_varyings_names; 259 260 /* Buffer size */ 261 static const glw::GLuint m_buffer_size; 262 263 /* Max uniform components and vectors */ 264 glw::GLint m_max_uniform_components; 265 glw::GLint m_max_uniform_vectors; 266 267 /* Uniform location */ 268 glw::GLint m_uniform_location; 269 270 /* Uniform data */ 271 std::vector<glw::GLint> m_uniform_data; 272 }; 273 274 /** Implementation of test case 16.2. Test description follows: 275 * 276 * Make sure it is possible to use as many uniform blocks as defined by 277 * GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT 278 * 279 * Category: API; 280 * Functional Test. 281 * 282 * Slightly modify test case 16.1 to use a similar idea to test if the 283 * value reported for the property by the implementation is reliable: 284 * 285 * - Test case 16.1's ivec4s take form of as many uniform blocks as needed, 286 * each hosting a single int. 287 * - The result value to be calculated in the geometry shader is a sum of 288 * all ints, stored in output int result variable. 289 **/ 290 class GeometryShaderMaxUniformBlocksTest : public GeometryShaderLimitsTransformFeedbackBase 291 { 292 public: 293 /* Public methods */ 294 GeometryShaderMaxUniformBlocksTest(Context& context, const ExtParameters& extParams, const char* name, 295 const char* description); 296 297 virtual ~GeometryShaderMaxUniformBlocksTest() 298 { 299 } 300 301 protected: 302 /* Overriden from GeometryShaderLimitsTransformFeedbackBase */ 303 virtual void clean(); 304 305 virtual void getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names, 306 glw::GLuint& out_n_captured_varyings); 307 308 virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, 309 glw::GLuint& out_n_fragment_shader_parts, 310 const glw::GLchar* const*& out_geometry_shader_parts, 311 glw::GLuint& out_n_geometry_shader_parts, 312 const glw::GLchar* const*& out_vertex_shader_parts, 313 glw::GLuint& out_n_vertex_shader_parts); 314 315 virtual void getTransformFeedbackBufferSize(glw::GLuint& out_buffer_size); 316 virtual void prepareProgramInput(); 317 virtual bool verifyResult(const void* data); 318 319 private: 320 /* Private type */ 321 struct _uniform_block 322 { 323 glw::GLuint buffer_object_id; 324 glw::GLint data; 325 }; 326 327 /* Private fields */ 328 /* Shaders' code */ 329 static const glw::GLchar* const m_fragment_shader_code; 330 static const glw::GLchar* const m_geometry_shader_code_preamble; 331 static const glw::GLchar* const m_geometry_shader_code_number_of_uniforms; 332 static const glw::GLchar* const m_geometry_shader_code_body_str; 333 static const glw::GLchar* const m_geometry_shader_code_body_end; 334 static const glw::GLchar* const m_vertex_shader_code; 335 336 const glw::GLchar* m_geometry_shader_parts[6]; 337 338 /* String used to store uniform blocks accesses */ 339 std::string m_uniform_block_access_string; 340 341 /* String used to store number of uniform blocks */ 342 std::string m_max_uniform_blocks_string; 343 344 /* Varying names */ 345 static const glw::GLchar* const m_captured_varyings_names; 346 347 /* Buffer size */ 348 static const glw::GLuint m_buffer_size; 349 350 /* Max uniform blocks */ 351 glw::GLint m_max_uniform_blocks; 352 353 /* Uniform blocks data */ 354 std::vector<_uniform_block> m_uniform_blocks; 355 }; 356 357 /** Implementation of test case 16.3. Test description follows: 358 * 359 * Make sure it is possible to use as many input components as defined by 360 * GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT 361 * 362 * Category: API. 363 * 364 * Create a program object, attach a fragment, geometry and a vertex shader to it: 365 * 366 * - Fragment shader can be boilerplate; 367 * - Vertex shader should define exactly 368 * (GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT / 4) ivec4 output variables. 369 * Each of the variables should be assigned a vector value of 370 * (n, n+1, n+2, n+3) where n corresponds to "index" of the variable, 371 * assuming the very first output variable has an "index" of 1. 372 * - Geometry shader should define exactly 373 * (GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT / 4) vec4 input variables. It 374 * should accept input point geometry and output a maximum of 1 point. 375 * It should sum up all components read from input variables and store them 376 * in output int variable called result.. 377 * 378 * The test should then configure the program object to capture values of 379 * "result" variable using transform feedback and link the program object. 380 * 381 * The test should now generate and bind a vertex array object, and then 382 * draw a single point. Test succeeds if the value stored in a buffer object 383 * configured for transform feedback storage is valid. 384 **/ 385 class GeometryShaderMaxInputComponentsTest : public GeometryShaderLimitsTransformFeedbackBase 386 { 387 public: 388 /* Public methods */ 389 GeometryShaderMaxInputComponentsTest(Context& context, const ExtParameters& extParams, const char* name, 390 const char* description); 391 392 virtual ~GeometryShaderMaxInputComponentsTest() 393 { 394 } 395 396 protected: 397 /* Overriden from GeometryShaderLimitsTransformFeedbackBase */ 398 virtual void clean(); 399 400 virtual void getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names, 401 glw::GLuint& out_n_captured_varyings); 402 403 virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, 404 glw::GLuint& out_n_fragment_shader_parts, 405 const glw::GLchar* const*& out_geometry_shader_parts, 406 glw::GLuint& out_n_geometry_shader_parts, 407 const glw::GLchar* const*& out_vertex_shader_parts, 408 glw::GLuint& out_n_vertex_shader_parts); 409 410 virtual void getTransformFeedbackBufferSize(glw::GLuint& out_buffer_size); 411 virtual void prepareProgramInput(); 412 virtual bool verifyResult(const void* data); 413 414 private: 415 /* Private fields */ 416 /* Shaders' code */ 417 static const glw::GLchar* const m_fragment_shader_code; 418 static const glw::GLchar* const m_geometry_shader_code_preamble; 419 static const glw::GLchar* const m_geometry_shader_code_number_of_uniforms; 420 static const glw::GLchar* const m_geometry_shader_code_body; 421 static const glw::GLchar* const m_vertex_shader_code_preamble; 422 static const glw::GLchar* const m_vertex_shader_code_number_of_uniforms; 423 static const glw::GLchar* const m_vertex_shader_code_body; 424 425 const glw::GLchar* m_geometry_shader_parts[4]; 426 const glw::GLchar* m_vertex_shader_parts[4]; 427 428 /* Max input components and vectors */ 429 glw::GLint m_max_geometry_input_components; 430 glw::GLint m_max_geometry_input_vectors; 431 432 /* String used to store number of geometry input vectors */ 433 std::string m_max_geometry_input_vectors_string; 434 435 /* Varying names */ 436 static const glw::GLchar* const m_captured_varyings_names; 437 438 /* Buffer size */ 439 static const glw::GLuint m_buffer_size; 440 }; 441 442 /** Implementation of test case 16.4. Test description follows: 443 * 444 * Make sure it is possible to use as many total output components as 445 * defined by GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT. 446 * 447 * Category: API. 448 * 449 * Let n_points be equal to: 450 * 451 * (GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT / GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT) 452 * 453 * Create a fragment, geometry and vertex shader objects: 454 * 455 * - Vertex shader code can be boilerplate; 456 * - Geometry shader code should define: 457 * 458 * floor(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT / 4) 459 * 460 * output ivec4 variables. It should take points as input and output, 461 * a maximum of n_points vertices will be written. In main(), for each 462 * vertex, the shader should set gl_Position to: 463 * 464 * (-1 + (2 * vertex id + 1) / (2 * max vertices) * 2, 0, 0, 1) 465 * 466 * where (vertex id) corresponds to index of about-to-be-emitted vertices, 467 * assuming the indexing starts from 0. 468 * Each vertex should store subsequently increasing, unique values to 469 * components of the output variables. 470 * Geometry shader should emit as many vertices as specified. For each 471 * output point, point size should be set to 2. 472 * - Fragment shader code should take all aforementioned varyings as input 473 * variables, read them, and store result int fragment as sum of all 474 * components for all vectors passed from the geometry shader. 475 * 476 * For rendering, the test should use a framebuffer object, to which 477 * a GL_R32I-based 2D texture object of resolution: 478 * 479 * (2*n_points, 2) 480 * 481 * has been attached to color attachment 0. 482 * 483 * The test should link the program (no linking error should be reported) 484 * and then activate it. Having bound a vertex array object, it should then 485 * draw n_points points. 486 * 487 * The test passes, if the texture attached to color attachment 0 consists 488 * of 2x2 quads filled with the same value, that can be considered valid in 489 * light of the description above. 490 * The program object consisting of these shader objects is expected to link 491 * successfully. 492 **/ 493 class GeometryShaderMaxOutputComponentsTest : public GeometryShaderLimitsRenderingBase 494 { 495 public: 496 /* Public methods */ 497 GeometryShaderMaxOutputComponentsTest(Context& context, const ExtParameters& extParams, const char* name, 498 const char* description); 499 500 virtual ~GeometryShaderMaxOutputComponentsTest() 501 { 502 } 503 504 protected: 505 /* Methods overriden from GeometryShaderLimitsRenderingBase */ 506 virtual void clean(); 507 508 virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices); 509 510 virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, 511 glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width, 512 glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size); 513 514 virtual void getRequiredPointSize(glw::GLfloat& out_point_size); 515 516 virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, 517 glw::GLuint& out_n_fragment_shader_parts, 518 const glw::GLchar* const*& out_geometry_shader_parts, 519 glw::GLuint& out_n_geometry_shader_parts, 520 const glw::GLchar* const*& out_vertex_shader_parts, 521 glw::GLuint& out_n_vertex_shader_parts); 522 523 virtual void prepareProgramInput(); 524 virtual bool verifyResult(const void* data); 525 526 private: 527 /* Private methods */ 528 void prepareFragmentShader(std::string& out_shader_code) const; 529 void prepareGeometryShader(std::string& out_shader_code) const; 530 531 /* Private fields */ 532 /* Shaders' code */ 533 static const glw::GLchar* const m_common_shader_code_gs_fs_out; 534 static const glw::GLchar* const m_common_shader_code_number_of_points; 535 static const glw::GLchar* const m_common_shader_code_gs_fs_out_definitions; 536 static const glw::GLchar* const m_fragment_shader_code_preamble; 537 static const glw::GLchar* const m_fragment_shader_code_flat_in_ivec4; 538 static const glw::GLchar* const m_fragment_shader_code_sum; 539 static const glw::GLchar* const m_fragment_shader_code_body_begin; 540 static const glw::GLchar* const m_fragment_shader_code_body_end; 541 static const glw::GLchar* const m_geometry_shader_code_preamble; 542 static const glw::GLchar* const m_geometry_shader_code_layout; 543 static const glw::GLchar* const m_geometry_shader_code_flat_out_ivec4; 544 static const glw::GLchar* const m_geometry_shader_code_assignment; 545 static const glw::GLchar* const m_geometry_shader_code_body_begin; 546 static const glw::GLchar* const m_geometry_shader_code_body_end; 547 static const glw::GLchar* const m_vertex_shader_code; 548 549 /* Storage for prepared fragment and geometry shader */ 550 std::string m_fragment_shader_code; 551 const glw::GLchar* m_fragment_shader_code_c_str; 552 std::string m_geometry_shader_code; 553 const glw::GLchar* m_geometry_shader_code_c_str; 554 555 /* Framebuffer dimensions */ 556 glw::GLuint m_texture_width; 557 static const glw::GLuint m_texture_height; 558 static const glw::GLuint m_texture_pixel_size; 559 static const glw::GLuint m_point_size; 560 561 /* Max number of output components */ 562 glw::GLint m_max_output_components; 563 glw::GLint m_max_output_vectors; 564 glw::GLint m_max_total_output_components; 565 glw::GLint m_n_available_vectors; 566 glw::GLint m_n_output_points; 567 }; 568 569 /** Implementation of test case 16.5. Test description follows: 570 * 571 * Make sure it possible to request as many output vertices as report for 572 * GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT. Requesting support for larger amount 573 * of output vertices should cause the linking process to fail. 574 * 575 * Category: API; 576 * Negative Test. 577 * 578 * Create two program objects and one boilerplate fragment & one boilerplate 579 * vertex shader objects. 580 * Also create two boilerplate geometry shader objects where: 581 * 582 * a) The first geometry shader object can output up to 583 * GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT vertices. 584 * b) The other geometry shader object can output up to 585 * (GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT+1) vertices. 586 * 587 * 1) Program object A should be attached fragment and vertex shader 588 * objects, as well as geometry shader A. This program object should 589 * link successfully. 590 * 2) Program object B should be attached fragment and vertex shader objects, 591 * as well as geometry shader B. This program object should fail to link. 592 **/ 593 class GeometryShaderMaxOutputVerticesTest : public TestCaseBase 594 { 595 public: 596 /* Public methods */ 597 GeometryShaderMaxOutputVerticesTest(Context& context, const ExtParameters& extParams, const char* name, 598 const char* description); 599 600 virtual ~GeometryShaderMaxOutputVerticesTest() 601 { 602 } 603 604 virtual IterateResult iterate(void); 605 606 private: 607 /* Private fields */ 608 /* Shaders' code */ 609 static const glw::GLchar* const m_fragment_shader_code; 610 static const glw::GLchar* const m_geometry_shader_code_preamble; 611 static const glw::GLchar* const m_geometry_shader_code_body; 612 static const glw::GLchar* const m_vertex_shader_code; 613 }; 614 615 /** Implementation of test case 16.6. Test description follows: 616 * 617 * Make sure it is possible to use as many output components as defined by 618 * GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT 619 * 620 * Category: API. 621 * 622 * Modify test case 16.4, so that: 623 * 624 * * n_points is always 1; 625 **/ 626 class GeometryShaderMaxOutputComponentsSinglePointTest : public GeometryShaderLimitsRenderingBase 627 { 628 public: 629 /* Public methods */ 630 GeometryShaderMaxOutputComponentsSinglePointTest(Context& context, const ExtParameters& extParams, const char* name, 631 const char* description); 632 633 virtual ~GeometryShaderMaxOutputComponentsSinglePointTest() 634 { 635 } 636 637 protected: 638 /* Methods overriden from GeometryShaderLimitsRenderingBase */ 639 virtual void clean(); 640 641 virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices); 642 643 virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, 644 glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width, 645 glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size); 646 647 virtual void getRequiredPointSize(glw::GLfloat& out_point_size); 648 649 virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, 650 glw::GLuint& out_n_fragment_shader_parts, 651 const glw::GLchar* const*& out_geometry_shader_parts, 652 glw::GLuint& out_n_geometry_shader_parts, 653 const glw::GLchar* const*& out_vertex_shader_parts, 654 glw::GLuint& out_n_vertex_shader_parts); 655 656 virtual void prepareProgramInput(); 657 virtual bool verifyResult(const void* data); 658 659 private: 660 /* Private methods */ 661 void prepareFragmentShader(std::string& out_shader_code) const; 662 void prepareGeometryShader(std::string& out_shader_code) const; 663 664 /* Private fields */ 665 /* Shaders' code */ 666 static const glw::GLchar* const m_common_shader_code_gs_fs_out; 667 static const glw::GLchar* const m_common_shader_code_gs_fs_out_definitions; 668 static const glw::GLchar* const m_fragment_shader_code_preamble; 669 static const glw::GLchar* const m_fragment_shader_code_flat_in_ivec4; 670 static const glw::GLchar* const m_fragment_shader_code_sum; 671 static const glw::GLchar* const m_fragment_shader_code_body_begin; 672 static const glw::GLchar* const m_fragment_shader_code_body_end; 673 static const glw::GLchar* const m_geometry_shader_code_preamble; 674 static const glw::GLchar* const m_geometry_shader_code_flat_out_ivec4; 675 static const glw::GLchar* const m_geometry_shader_code_assignment; 676 static const glw::GLchar* const m_geometry_shader_code_body_begin; 677 static const glw::GLchar* const m_geometry_shader_code_body_end; 678 static const glw::GLchar* const m_vertex_shader_code; 679 680 /* Storage for prepared fragment and geometry shader */ 681 std::string m_fragment_shader_code; 682 std::string m_geometry_shader_code; 683 684 const glw::GLchar* m_fragment_shader_code_c_str; 685 const glw::GLchar* m_geometry_shader_code_c_str; 686 687 /* Framebuffer dimensions */ 688 static const glw::GLuint m_texture_width; 689 static const glw::GLuint m_texture_height; 690 static const glw::GLuint m_texture_pixel_size; 691 static const glw::GLuint m_point_size; 692 693 /* Max number of output components */ 694 glw::GLint m_max_output_components; 695 glw::GLint m_max_output_vectors; 696 glw::GLint m_n_available_vectors; 697 }; 698 699 /** Implementation of test case 16.7. Test description follows: 700 * 701 * Make sure that it is possible to access as many texture image units from 702 * a geometry shader as reported by GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 703 * 704 * Category: API; 705 * Functional Test. 706 * 707 * Create as many texture objects as reported by 708 * GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT. Each texture should be made an 709 * immutable GL_R32I 2D texture, have 1x1 resolution and be filled with 710 * subsequently increasing intensities (starting from 1, delta: 2). Let's 711 * name these textures "source textures" for the purpose of this test case. 712 * 713 * Create a program object and a fragment/geometry/vertex shader object. 714 * Behavior of the shaders should be as follows: 715 * 716 * 1) Vertex shader should take gl_VertexID and calculate an unique 2D 717 * location, that will later be used to render a 2x2 quad. The calculations 718 * should take quad size into account, note the quads must not overlap. The 719 * result location should be passed to geometry shader by storing it in an 720 * output variable. The shader should also store the vertex id in a 721 * flat-interpolated int output variable called vertex_id. 722 * 723 * 2) Geometry shader should accept points as input types and should emit 724 * triangle strips with a maximum of 4 output vertices. For each output 725 * geometry's vertex, two values should be written: 726 * 727 * * gl_Position obviously; 728 * * color (stored as flat-interpolated integer); 729 * 730 * The shader should define as many 2D samplers as reported for the tested 731 * property. In geometry shader's entry-point, the aforementioned 2D 732 * location should be used to calculate vertices of a quad the shader will 733 * emit (built using a triangle strip). Geometry shader should also write 734 * a result of the following computation to an output color variable: 735 * 736 * sum(i=0..n_samplers)( (vertex_id == i) * (result of sampling 2D texture 737 * at (0,0) using a sampler bound to texture unit i) ); 738 * 739 * 3) Fragment shader should take the color as passed by geometry shader 740 * and write it to output result variable. 741 * 742 * These shader objects should then be compiled, attached to the program 743 * object. The program object should be linked. Each sampler uniform should 744 * be assigned a consecutive texture unit index, starting from 0. 745 * 746 * A framebuffer object should then be created, as well as a 2D GL_R32I 747 * texture of resolution: 748 * 749 * (GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT*2, 2) 750 * 751 * The texture should be attached to the FBO's color attachment. 752 * 753 * A vertex array object should be created and bound. 754 * 755 * "Source textures" are next bound to corresponding texture units, and the 756 * FBO should be made a draw framebuffer. The program object should be made 757 * current and exactly GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT points should 758 * be drawn. 759 * 760 * Next, bind the FBO to GL_READ_FRAMEBUFFER target, read the data, and make 761 * sure that consequent 2x2 quads are of expected intensities (epsilon to 762 * consider: +-1). 763 **/ 764 class GeometryShaderMaxTextureUnitsTest : public GeometryShaderLimitsRenderingBase 765 { 766 public: 767 /* Public methods */ 768 GeometryShaderMaxTextureUnitsTest(Context& context, const ExtParameters& extParams, const char* name, 769 const char* description); 770 771 virtual ~GeometryShaderMaxTextureUnitsTest() 772 { 773 } 774 775 protected: 776 /* Methods overriden from GeometryShaderLimitsRenderingBase */ 777 virtual void clean(); 778 779 virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices); 780 781 virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, 782 glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width, 783 glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size); 784 785 virtual void getRequiredPointSize(glw::GLfloat& out_point_size); 786 787 virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, 788 glw::GLuint& out_n_fragment_shader_parts, 789 const glw::GLchar* const*& out_geometry_shader_parts, 790 glw::GLuint& out_n_geometry_shader_parts, 791 const glw::GLchar* const*& out_vertex_shader_parts, 792 glw::GLuint& out_n_vertex_shader_parts); 793 794 virtual void prepareProgramInput(); 795 virtual bool verifyResult(const void* data); 796 797 private: 798 /* Private types */ 799 struct _texture_data 800 { 801 glw::GLuint texture_id; 802 glw::GLint data; 803 }; 804 typedef std::vector<_texture_data> textureContainer; 805 806 /* Private fields */ 807 /* Shaders' code */ 808 static const glw::GLchar* const m_fragment_shader_code; 809 static const glw::GLchar* const m_geometry_shader_code_preamble; 810 static const glw::GLchar* const m_geometry_shader_code_body; 811 static const glw::GLchar* const m_vertex_shader_code_preamble; 812 static const glw::GLchar* const m_vertex_shader_code_body; 813 814 /* Storage for vertex and geometry shader parts */ 815 const glw::GLchar* m_geometry_shader_parts[3]; 816 const glw::GLchar* m_vertex_shader_parts[3]; 817 818 /* Framebuffer dimensions */ 819 glw::GLuint m_texture_width; 820 static const glw::GLuint m_texture_height; 821 static const glw::GLuint m_texture_pixel_size; 822 static const glw::GLuint m_point_size; 823 824 /* Max number of texture units */ 825 glw::GLint m_max_texture_units; 826 std::string m_max_texture_units_string; 827 828 /* Texture units */ 829 textureContainer m_textures; 830 }; 831 832 /** Implementation of test case 16.8. Test description follows: 833 * 834 * Make sure it is possible to use as many geometry shader invocations as 835 * defined by GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT. Verify invocation 836 * count defaults to 1 if no number of invocations is defined in the 837 * geometry shader. 838 * 839 * Category: API. 840 * 841 * Create a program object and: 842 * 843 * - A boilerplate vertex shader object; 844 * - A geometry shader object that: 845 * 846 * 1) takes points on input; 847 * 2) outputs a maximum of 3 vertices making up triangles; 848 * 3) uses exactly GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT invocations; 849 * 4) let: 850 * 851 * dx = 2.0 / GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT. 852 * 853 * Emit 3 vertices: 854 * 855 * 4a) (-1+dx*(gl_InvocationID), -1.001, 0, 1) 856 * 4b) (-1+dx*(gl_InvocationID), 1.001, 0, 1) 857 * 4c) (-1+dx*(gl_InvocationID+1), 1.001, 0, 1) 858 * 859 * - A fragment shader object that always sets green color for rasterized 860 * fragments. 861 * 862 * Compile the shaders, attach them to the program object, link the program 863 * object. 864 * 865 * Generate a texture object of type GL_RGBA8 type and of resolution: 866 * 867 * (GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT*9)x9 868 * 869 * Generate a FBO and attach the texture object to its color attachment. 870 * 871 * Bind the FBO to GL_FRAMEBUFFER target and clear the attachments with red 872 * color. 873 * 874 * Generate a vertex array object, bind it. 875 * 876 * Use the program object and issue a draw call for a single point. 877 * 878 * Read back texture object data. The test succeeds if correct amount of 879 * triangles was rendered at expected locations. To test this: : 880 * 881 * * Let n = (GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT - 1); 882 * * Let (x1, y1) = ((n) * 9, 0); 883 * * Let (x2, y2) = ((n) * 9, 0); 884 * * Let (x3, y3) = ((n + 1) * 9 - 1, 9 - 1); 885 * * Triangle rendered in last invocation is described by vertices at 886 * coordinates (x_i, y_i) where i e {1, 2, 3}. 887 * * Centroid of this triangle is defined by (x', y') where: 888 * 889 * x' = floor( (x1 + x2 + x3) / 3); 890 * y' = floor( (y1 + y2 + y3) / 3); 891 * 892 * * Pixel at (x', y') should be set to (0, 255, 0, 0) (allowed epsilon: 0) 893 * * Pixel at (n*9-1, 9) should be set to red color (allowed epsilon: 0) 894 * 895 * Repeat this test for a geometry shader with no number of invocations 896 * defined, in which case only one triangle should be rendered. 897 **/ 898 class GeometryShaderMaxInvocationsTest : public TestCaseBase 899 { 900 public: 901 /* Public methods */ 902 GeometryShaderMaxInvocationsTest(Context& context, const ExtParameters& extParams, const char* name, 903 const char* description); 904 905 virtual ~GeometryShaderMaxInvocationsTest() 906 { 907 } 908 909 virtual void deinit(void); 910 virtual IterateResult iterate(void); 911 912 private: 913 /* Private methods */ 914 void initTest(void); 915 916 /* Verification of results */ 917 bool verifyResultOfMultipleInvocationsPass(unsigned char* result_image); 918 bool verifyResultOfSingleInvocationPass(unsigned char* result_image); 919 920 /* Private fields */ 921 /* Program and shader ids for multiple GS invocations */ 922 glw::GLuint m_fragment_shader_id_for_multiple_invocations_pass; 923 glw::GLuint m_geometry_shader_id_for_multiple_invocations_pass; 924 glw::GLuint m_program_object_id_for_multiple_invocations_pass; 925 glw::GLuint m_vertex_shader_id_for_multiple_invocations_pass; 926 927 /* Program and shader ids for single GS invocation */ 928 glw::GLuint m_fragment_shader_id_for_single_invocation_pass; 929 glw::GLuint m_geometry_shader_id_for_single_invocation_pass; 930 glw::GLuint m_program_object_id_for_single_invocation_pass; 931 glw::GLuint m_vertex_shader_id_for_single_invocation_pass; 932 933 /* Shaders' code */ 934 static const glw::GLchar* const m_fragment_shader_code; 935 static const glw::GLchar* const m_geometry_shader_code_preamble; 936 static const glw::GLchar* const m_geometry_shader_code_layout; 937 static const glw::GLchar* const m_geometry_shader_code_layout_invocations; 938 static const glw::GLchar* const m_geometry_shader_code_body; 939 static const glw::GLchar* const m_vertex_shader_code; 940 941 const glw::GLchar* m_geometry_shader_parts_for_multiple_invocations_pass[16]; 942 const glw::GLchar* m_geometry_shader_parts_for_single_invocation_pass[16]; 943 944 /* Max GS invocations */ 945 glw::GLint m_max_geometry_shader_invocations; 946 947 /* String used to store maximum number of GS invocations */ 948 std::string m_max_geometry_shader_invocations_string; 949 950 /* Framebuffer */ 951 glw::GLuint m_framebuffer_object_id; 952 glw::GLuint m_color_texture_id; 953 954 /* Framebuffer dimensions */ 955 glw::GLuint m_texture_width; 956 static const glw::GLuint m_triangle_edge_length; 957 static const glw::GLuint m_texture_height; 958 static const glw::GLuint m_texture_pixel_size; 959 960 /* Vertex array object */ 961 glw::GLuint m_vertex_array_object_id; 962 }; 963 964 /** Implementation of test case 16.9. Test description follows: 965 * 966 * Make sure it is possible to use up to GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 967 * texture image units in three different stages, with an assumption that 968 * each access to the same texture unit from a different stage counts as 969 * a separate texture unit access. 970 * 971 * Category: API; 972 * Functional Test. 973 * 974 * Create max(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, 975 * GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT, GL_MAX_TEXTURE_IMAGE_UNITS) 976 * immutable texture objects. Each texture should use GL_R32UI internal 977 * format, have 1x1 resolution and contain an unique intensity equal to 978 * index of the texture, where first texture object created is considered 979 * to have index equal to 1. 980 * 981 * We want each stage to use at least one texture unit. Use the following 982 * calculations to determine how many samplers should be defined for each 983 * stage: 984 * 985 * 1) Vertex stage: n_vertex_smpl = max(1, 986 * min(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - 2, 987 * GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS) ). 988 * 2) Fragment stage: n_frag_smpl = max(1, 989 * min(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - n_vertex_smpl - 1, 990 * GL_MAX_TEXTURE_IMAGE_UNITS) ) 991 * 3) Geometry shader: n_geom_smpl = max(1, 992 * min(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - n_vertex_smpl - n_frag_smpl, 993 * GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT) ) 994 * 995 * Create a program object and fragment, geometry and vertex shader objects: 996 * 997 * - Vertex shader object should define exactly n_vertex_smpl 2D texture 998 * samplers named samplerX where X stands for texture unit index that 999 * will be accessed. It should set gl_Position to: 1000 * 1001 * (-1 + gl_VertexID / GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, -1, 0, 1) 1002 * 1003 * Vertex shader should define int output variable out_vs_vertexid storing 1004 * gl_VertexID value, and an output integer variable out_vs_vertex that 1005 * should be written result of the following computation: 1006 * 1007 * sum(i=0..n_vertex_smpl)( (gl_VertexID == i) * (value sampled from the 1008 * texture sampler samplerX)) where: X = i; 1009 * 1010 * - Geometry shader object should define exactly n_geom_smpl 2D texture 1011 * samplers named samplerX where X stands for texture unit index that 1012 * will be accessed. The geometry shader should define int input variables 1013 * out_vs_vertexid, out_vs_vertex and int output variables: 1014 * 1015 * * out_gs_vertexid - set to the value of out_vs_vertexid; 1016 * * out_gs_vertex - set to the value of out_vs_vertex; 1017 * * out_geometry that should be written result of the following computation: 1018 * 1019 * sum(i=0..n_geom_smpl)( (out_vs_vertexid == i) * (value sampled from the 1020 * texture sampler samplerX)) where: X = i; 1021 * 1022 * The geometry shader should emit exactly one point at position configured 1023 * by vertex shader. The geometry shader should take points as input. 1024 * 1025 * - Fragment shader object should define exactly n_frag_smpl 2D texture 1026 * samplers named samplerX where X stands for texture unit index that 1027 * will be accessed. The fragment shader should define int input variables 1028 * out_gs_vertexid, out_gs_vertex and out_geometry. It should define 1029 * a single int output variable result which should be written result of 1030 * the following computation: 1031 * 1032 * if (out_gs_vertex == out_geometry) 1033 * { 1034 * set to sum(i=0..n_frag_smpl)(out_gs_vertex_id == i) * (value sampled 1035 * from the texture sampler samplerX)) where: X = i; 1036 * } 1037 * else 1038 * { 1039 * set to 0. 1040 * } 1041 * 1042 * The shaders should be attached to the program object and compiled. The 1043 * program object should be linked. 1044 * 1045 * Assume: 1046 * 1047 * min_texture_image_units = min( 1048 * GL_MAX_TEXTURE_IMAGE_UNITS, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, 1049 * GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT); 1050 * 1051 * A framebuffer object should be created, along with a 2D texture object of 1052 * min_texture_image_units x 1 resolution. The texture object should be 1053 * attached to color attachment point of the FBO. Bind the framebuffer object 1054 * to GL_DRAW_FRAMEBUFFER target. 1055 * 1056 * A vertex array object should be created and bound. 1057 * 1058 * Configure the program object's uniform samplers to use consecutive texture 1059 * image units. Bind the texture objects we created at the beginning to these 1060 * texture units. Draw exactly min_texture_image_units points. 1061 * 1062 * Bind the FBO to GL_READ_FRAMEBUFFER. Read the rendered data and make sure 1063 * the result values form a (1, 2, ... min_texture_image_units) set. 1064 **/ 1065 class GeometryShaderMaxCombinedTextureUnitsTest : public GeometryShaderLimitsRenderingBase 1066 { 1067 public: 1068 /* Public methods */ 1069 GeometryShaderMaxCombinedTextureUnitsTest(Context& context, const ExtParameters& extParams, const char* name, 1070 const char* description); 1071 1072 virtual ~GeometryShaderMaxCombinedTextureUnitsTest() 1073 { 1074 } 1075 1076 protected: 1077 /* Methods overriden from GeometryShaderLimitsRenderingBase */ 1078 virtual void clean(); 1079 1080 virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices); 1081 1082 virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, 1083 glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width, 1084 glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size); 1085 1086 virtual void getRequiredPointSize(glw::GLfloat& out_point_size); 1087 1088 virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, 1089 glw::GLuint& out_n_fragment_shader_parts, 1090 const glw::GLchar* const*& out_geometry_shader_parts, 1091 glw::GLuint& out_n_geometry_shader_parts, 1092 const glw::GLchar* const*& out_vertex_shader_parts, 1093 glw::GLuint& out_n_vertex_shader_parts); 1094 1095 virtual void prepareProgramInput(); 1096 virtual bool verifyResult(const void* data); 1097 1098 private: 1099 /* Private types */ 1100 struct _texture_data 1101 { 1102 glw::GLuint texture_id; 1103 glw::GLuint data; 1104 }; 1105 typedef std::vector<_texture_data> textureContainer; 1106 1107 /* Private fields */ 1108 /* Shaders' code */ 1109 static const glw::GLchar* const m_fragment_shader_code_preamble; 1110 static const glw::GLchar* const m_fragment_shader_code_body; 1111 static const glw::GLchar* const m_geometry_shader_code_preamble; 1112 static const glw::GLchar* const m_geometry_shader_code_body; 1113 static const glw::GLchar* const m_vertex_shader_code_preamble; 1114 static const glw::GLchar* const m_vertex_shader_code_body; 1115 1116 /* Storage for vertex and geometry shader parts */ 1117 const glw::GLchar* m_fragment_shader_parts[3]; 1118 const glw::GLchar* m_geometry_shader_parts[3]; 1119 const glw::GLchar* m_vertex_shader_parts[3]; 1120 1121 /* Framebuffer dimensions */ 1122 glw::GLuint m_texture_width; 1123 static const glw::GLuint m_texture_height; 1124 static const glw::GLuint m_texture_pixel_size; 1125 static const glw::GLuint m_point_size; 1126 1127 /* Max number of texture units */ 1128 glw::GLint m_max_combined_texture_units; 1129 glw::GLint m_max_fragment_texture_units; 1130 glw::GLint m_max_geometry_texture_units; 1131 glw::GLint m_max_vertex_texture_units; 1132 glw::GLint m_min_texture_units; 1133 glw::GLint m_n_fragment_texture_units; 1134 glw::GLint m_n_geometry_texture_units; 1135 glw::GLint m_n_texture_units; 1136 glw::GLint m_n_vertex_texture_units; 1137 std::string m_n_fragment_texture_units_string; 1138 std::string m_n_geometry_texture_units_string; 1139 std::string m_n_vertex_texture_units_string; 1140 1141 /* Texture units */ 1142 textureContainer m_textures; 1143 }; 1144 1145 } /* glcts */ 1146 1147 #endif // _ESEXTCGEOMETRYSHADERLIMITS_HPP 1148