1 #ifndef _ESEXTCGEOMETRYSHADERRENDERING_HPP 2 #define _ESEXTCGEOMETRYSHADERRENDERING_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 #include "../esextcTestCaseBase.hpp" 27 28 namespace glcts 29 { 30 31 /** Supported geometry shader output layout qualifiers */ 32 typedef enum 33 { 34 /* points */ 35 SHADER_OUTPUT_TYPE_POINTS, 36 /* lines */ 37 SHADER_OUTPUT_TYPE_LINE_STRIP, 38 /* triangles */ 39 SHADER_OUTPUT_TYPE_TRIANGLE_STRIP, 40 41 /* Always last */ 42 SHADER_OUTPUT_TYPE_COUNT 43 } _shader_output_type; 44 45 /** Implements Geometry Shader conformance test group 1. 46 * 47 * Note that actual testing is handled by classes implementing GeometryShaderRenderingCase 48 * interface. This class implements DEQP CTS test case interface, meaning it is only 49 * responsible for executing the test and reporting the results back to CTS. 50 * 51 **/ 52 class GeometryShaderRendering : public TestCaseGroupBase 53 { 54 public: 55 /* Public methods */ 56 GeometryShaderRendering(Context &context, const ExtParameters &extParams, const char *name, 57 const char *description); 58 ~GeometryShaderRendering()59 virtual ~GeometryShaderRendering() 60 { 61 } 62 63 virtual void init(void); 64 65 private: 66 /* Private type definitions */ 67 typedef enum 68 { 69 /* points */ 70 SHADER_INPUT_POINTS, 71 72 /* lines */ 73 SHADER_INPUT_LINES, 74 75 /* lines_with_adjacency */ 76 SHADER_INPUT_LINES_WITH_ADJACENCY, 77 78 /* triangles */ 79 SHADER_INPUT_TRIANGLES, 80 81 /* triangles_with_adjacency */ 82 SHADER_INPUT_TRIANGLES_WITH_ADJACENCY, 83 84 /* Always last */ 85 SHADER_INPUT_UNKNOWN 86 } _shader_input; 87 88 /* Private methods */ 89 const char *getTestName(_shader_input input, _shader_output_type output_type, glw::GLenum drawcall_mode); 90 }; 91 92 /* Defines an interface that all test case classes must implement. 93 * 94 * Base implementation initializes GLES objects later used in the specific test 95 * and fills them with content, as reported by actual test case implementations. 96 * 97 * Instances matching this interface are used by GeometryShaderRendering class 98 * to execute a set of all the tests as defined in the test specification. 99 */ 100 class GeometryShaderRenderingCase : public TestCaseBase 101 { 102 public: 103 /* Public type definitions */ 104 /** Supported draw call types. */ 105 typedef enum 106 { 107 /* glDrawArrays() */ 108 DRAW_CALL_TYPE_GL_DRAW_ARRAYS, 109 110 /* glDrawArraysInstanced() */ 111 DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED, 112 113 /* glDrawElements() */ 114 DRAW_CALL_TYPE_GL_DRAW_ELEMENTS, 115 116 /* glDrawElementsInstanced() */ 117 DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED, 118 119 /* glDrawRangeElements() */ 120 DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS 121 122 } _draw_call_type; 123 124 /* Public methods */ 125 GeometryShaderRenderingCase(Context &Context, const ExtParameters &extParams, const char *name, 126 const char *description); 127 ~GeometryShaderRenderingCase()128 virtual ~GeometryShaderRenderingCase() 129 { 130 } 131 132 virtual void deinit(); 133 void executeTest(_draw_call_type type); 134 virtual IterateResult iterate(); 135 136 protected: 137 /* Protected methods */ 138 void initTest(); 139 virtual unsigned int getAmountOfDrawInstances() = 0; 140 virtual unsigned int getAmountOfElementsPerInstance() = 0; 141 virtual unsigned int getAmountOfVerticesPerInstance() = 0; 142 virtual glw::GLenum getDrawCallMode() = 0; 143 virtual std::string getFragmentShaderCode() = 0; 144 virtual std::string getGeometryShaderCode() = 0; 145 virtual glw::GLuint getRawArraysDataBufferSize(bool instanced) = 0; 146 virtual const void *getRawArraysDataBuffer(bool instanced) = 0; 147 virtual void getRenderTargetSize(unsigned int n_instances, unsigned int *out_width, unsigned int *out_height) = 0; 148 virtual glw::GLuint getUnorderedArraysDataBufferSize(bool instanced) = 0; 149 virtual const void *getUnorderedArraysDataBuffer(bool instanced) = 0; 150 virtual glw::GLuint getUnorderedElementsDataBufferSize(bool instanced) = 0; 151 virtual const void *getUnorderedElementsDataBuffer(bool instanced) = 0; 152 virtual glw::GLenum getUnorderedElementsDataType() = 0; 153 virtual glw::GLubyte getUnorderedElementsMaxIndex() = 0; 154 virtual glw::GLubyte getUnorderedElementsMinIndex() = 0; 155 virtual std::string getVertexShaderCode() = 0; 156 virtual void verify(_draw_call_type drawcall_type, unsigned int instance_id, const unsigned char *data) = 0; 157 setUniformsBeforeDrawCall(_draw_call_type)158 virtual void setUniformsBeforeDrawCall(_draw_call_type /*drawcall_type*/) 159 { 160 } 161 162 /* Protected variables */ 163 deqp::Context &m_context; 164 glw::GLuint m_instanced_raw_arrays_bo_id; 165 glw::GLuint m_instanced_unordered_arrays_bo_id; 166 glw::GLuint m_instanced_unordered_elements_bo_id; 167 glw::GLuint m_noninstanced_raw_arrays_bo_id; 168 glw::GLuint m_noninstanced_unordered_arrays_bo_id; 169 glw::GLuint m_noninstanced_unordered_elements_bo_id; 170 glw::GLuint m_fs_id; 171 glw::GLuint m_gs_id; 172 glw::GLuint m_po_id; 173 glw::GLuint m_renderingTargetSize_uniform_location; 174 glw::GLuint m_singleRenderingTargetSize_uniform_location; 175 glw::GLuint m_vao_id; 176 glw::GLuint m_vs_id; 177 178 glw::GLuint m_fbo_id; 179 glw::GLuint m_read_fbo_id; 180 glw::GLuint m_to_id; 181 182 glw::GLuint m_instanced_fbo_id; 183 glw::GLuint m_instanced_read_fbo_id; 184 glw::GLuint m_instanced_to_id; 185 }; 186 187 /** Implements Geometry Shader conformance test group 1, 'points' input primitive type case. 188 * Test specification for this case follows: 189 * 190 * All sub-tests assume point size & line width of 1 pixel, which is the 191 * minimum maximum value for both properties in GLES 3.0. 192 * 193 * Let (R, G, B, A) be the color of the input point that is to be amplified. 194 * Color buffer should be cleared with (0, 0, 0, 0) prior to executing each 195 * of the scenarios. 196 * 197 * 1.1. If "points" output primitive type is used: 198 * 199 * The geometry shader should emit 9 points in total for a single input. 200 * Each point should be assigned a size of 1. The points should be 201 * positioned, so that they tightly surround the "input" point from left / 202 * right / top / left sides, as well as from top-left / top-right / 203 * bottom-left / bottom-right corners but do *not* overlap in screen-space. 204 * 205 * Additional points should also use (R, G, B, A) color. 206 * 207 * The test should draw 8 points (one after another, assume a horizontal 208 * delta of 2 pixels) of varying colors to a 2D texture of resolution 38x3. 209 * Test succeeds if centers of all emitted points have colors different than 210 * the background color. 211 * 212 * 1.2. If "lines" output primitive type is used: 213 * 214 * The geometry shader should draw outlines (built of line segments) of 215 * three quads nested within each other, as depicted below: 216 * 217 * 1 1 1 1 1 1 1 218 * 1 2 2 2 2 2 1 219 * 1 2 3 3 3 2 1 220 * 1 2 3 * 3 2 1 221 * 1 2 3 3 3 2 1 222 * 1 2 2 2 2 2 1 223 * 1 1 1 1 1 1 1 224 * 225 * where each number corresponds to index of the quad and * indicates 226 * position of the input point which is not drawn. 227 * 228 * Each quad should be drawn with (R, G, B, A) color. 229 * The test should draw 8 points (one after another) of varying colors to 230 * a 2D texture of resolution 54x7. Test succeeds if all pixels making up 231 * the central quad 2 have valid colors. 232 * 233 * 1.3. If "triangles" output primitive type is used: 234 * 235 * The geometry shader should generate 2 triangle primitives for a single 236 * input point: 237 * 238 * * A) (Bottom-left corner, top-left corner, bottom-right corner), use 239 * (R, 0, 0, 0) color; 240 * * B) (Bottom-right corner, top-left corner, top-right corner), use 241 * (0, G, 0, 0) color; 242 * 243 * The test should draw 8 points (one after another) of varying colors to 244 * a 2D texture of resolution of resolution 48x6. Test succeeds if centers 245 * of the rendered triangles have valid colors. 246 * 247 **/ 248 class GeometryShaderRenderingPointsCase : public GeometryShaderRenderingCase 249 { 250 public: 251 /* Public methods */ 252 GeometryShaderRenderingPointsCase(Context &context, const ExtParameters &extParams, const char *name, 253 glw::GLenum drawcall_mode, _shader_output_type output_type); 254 255 virtual ~GeometryShaderRenderingPointsCase(); 256 257 protected: 258 /* GeometryShaderRenderingCase interface implementation */ 259 unsigned int getAmountOfDrawInstances(); 260 unsigned int getAmountOfElementsPerInstance(); 261 unsigned int getAmountOfVerticesPerInstance(); 262 glw::GLenum getDrawCallMode(); 263 std::string getFragmentShaderCode(); 264 std::string getGeometryShaderCode(); 265 glw::GLuint getRawArraysDataBufferSize(bool instanced); 266 const void *getRawArraysDataBuffer(bool instanced); 267 void getRenderTargetSize(unsigned int n_instances, unsigned int *out_width, unsigned int *out_height); 268 glw::GLuint getUnorderedArraysDataBufferSize(bool instanced); 269 const void *getUnorderedArraysDataBuffer(bool instanced); 270 glw::GLuint getUnorderedElementsDataBufferSize(bool instanced); 271 const void *getUnorderedElementsDataBuffer(bool instanced); 272 glw::GLenum getUnorderedElementsDataType(); 273 glw::GLubyte getUnorderedElementsMaxIndex(); 274 glw::GLubyte getUnorderedElementsMinIndex(); 275 std::string getVertexShaderCode(); 276 void verify(_draw_call_type drawcall_type, unsigned int instance_id, const unsigned char *data); 277 278 private: 279 /* Private variables */ 280 _shader_output_type m_output_type; 281 282 float *m_raw_array_data; 283 float *m_unordered_array_data; 284 unsigned char *m_unordered_elements_data; 285 }; 286 287 /** Implements Geometry Shader conformance test group 1, 'lines' and 288 * 'lines_adjacency' input primitive type cases. 289 * 290 * Test specification for this case follows: 291 * 292 * Assume a point size of 1 pixel and line width of 1 pixel, where 293 * appropriate. 294 * Let (R, G, B, A) be the color of start point of the input line and 295 * (R', G', B', A') be the color of end point of the input line. 296 * 297 * 2.1. If "points" output primitive type is used: 298 * 299 * The geometry shader should generate 8 points for a single input line segment, 300 * where each point consists of 9 sub-points tightly forming a quad (with 301 * the actual point located in the center) in order to emulate larger point 302 * size. The points should be uniformly distributed over the primitive 303 * (first point positioned at the start point and the last one located at 304 * the end point) and their color should linearly interpolate from the 305 * (R, G, B, A) to (R', G', B', A'). All sub-points should use the same 306 * color as the parent point. 307 * 308 * The test should draw the points over a square outline. Each instance should 309 * draw a set of points occupying a separate outline. Each rectangle should 310 * occupy a block of 45x45. 311 * 312 * Test succeeds if centers of generated points have valid colors. 313 * 314 * 2.2. If "lines" output primitive type is used: 315 * 316 * Expanding on the idea presenting in 2.1, for each line segment the GS 317 * should generate three line segments, as presented below: 318 * 319 * Upper/left helper line segment 320 * Line segment 321 * Bottom/right helper line segment 322 * 323 * This is to emulate a larger line width than the minimum maximum line 324 * width all GLES implementations must support. 325 * 326 * Upper helper line segment should use start point's color; 327 * Middle line segment should take mix(start_color, end_color, 0.5) color; 328 * Bottom helper line segment should use end point's color; 329 * 330 * Test succeeds if all pixels of generated middle line segments have valid 331 * colors. Do not test corners. 332 * 333 * 2.3. If "triangles" output primitive type is used: 334 * 335 * Expanding on the idea presented in 2.1: for each input line segment, 336 * the GS should generate a triangle, using two vertices provided and 337 * (0, 0, 0, 1). By drawing a quad outline, whole screen-space should be 338 * covered with four triangles. 339 * The test passes if centroids of the generated triangles carry valid colors. 340 * 341 **/ 342 class GeometryShaderRenderingLinesCase : public GeometryShaderRenderingCase 343 { 344 public: 345 /* Public methods */ 346 GeometryShaderRenderingLinesCase(Context &context, const ExtParameters &extParams, const char *name, 347 bool use_adjacency_data, glw::GLenum drawcall_mode, 348 _shader_output_type output_type); 349 350 virtual ~GeometryShaderRenderingLinesCase(); 351 352 protected: 353 /* GeometryShaderRenderingCase interface implementation */ 354 unsigned int getAmountOfDrawInstances(); 355 unsigned int getAmountOfElementsPerInstance(); 356 unsigned int getAmountOfVerticesPerInstance(); 357 glw::GLenum getDrawCallMode(); 358 std::string getFragmentShaderCode(); 359 std::string getGeometryShaderCode(); 360 glw::GLuint getRawArraysDataBufferSize(bool instanced); 361 const void *getRawArraysDataBuffer(bool instanced); 362 void getRenderTargetSize(unsigned int n_instances, unsigned int *out_width, unsigned int *out_height); 363 glw::GLuint getUnorderedArraysDataBufferSize(bool instanced); 364 const void *getUnorderedArraysDataBuffer(bool instanced); 365 glw::GLuint getUnorderedElementsDataBufferSize(bool instanced); 366 const void *getUnorderedElementsDataBuffer(bool instanced); 367 glw::GLenum getUnorderedElementsDataType(); 368 glw::GLubyte getUnorderedElementsMaxIndex(); 369 glw::GLubyte getUnorderedElementsMinIndex(); 370 std::string getVertexShaderCode(); 371 void setUniformsBeforeDrawCall(_draw_call_type drawcall_type); 372 void verify(_draw_call_type drawcall_type, unsigned int instance_id, const unsigned char *data); 373 374 private: 375 /* Private variables */ 376 _shader_output_type m_output_type; 377 378 glw::GLenum m_drawcall_mode; 379 bool m_use_adjacency_data; 380 381 float *m_raw_array_instanced_data; 382 unsigned int m_raw_array_instanced_data_size; 383 float *m_raw_array_noninstanced_data; 384 unsigned int m_raw_array_noninstanced_data_size; 385 386 float *m_unordered_array_instanced_data; 387 unsigned int m_unordered_array_instanced_data_size; 388 float *m_unordered_array_noninstanced_data; 389 unsigned int m_unordered_array_noninstanced_data_size; 390 391 unsigned char *m_unordered_elements_instanced_data; 392 unsigned int m_unordered_elements_instanced_data_size; 393 unsigned char *m_unordered_elements_noninstanced_data; 394 unsigned int m_unordered_elements_noninstanced_data_size; 395 396 unsigned char m_unordered_elements_max_index; 397 unsigned char m_unordered_elements_min_index; 398 }; 399 400 /** Implements Geometry Shader conformance test group 1, 'triangles' and 401 * 'triangles_adjacency' input primitive type cases. Test specification 402 * for this case follows: 403 * 404 * All tests should draw a 45-degree rotated square shape consisting of four 405 * separate triangles, as depicted in the picture below: 406 * 407 * 408 * C 409 * / \ 410 * / \ 411 * B--A--D 412 * \ / 413 * \_/ 414 * E 415 * 416 * For GL_TRIANGLES data, the rendering order is: ABC, ACD, ADE, AEB; 417 * For GL_TRIANGLE_FAN, the rendering order is: ABCDEB; 418 * For GL_TRIANGLE_STRIP, the rendering order is: BACDAEB; 419 * 420 * Note that for triangle strips, a degenerate triangle will be rendered. 421 * Test implementation should not test the first triangle rendered in the 422 * top-right quarter, as it will be overwritten by the triangle that follows 423 * right after. 424 * 425 * Subsequent draw call instances should draw the geometry one after another, 426 * in vertical direction. 427 * 428 * Each of the tests should use 29x(29 * number of instances) resolution for 429 * the rendertarget. 430 * 431 * 3.1. If "points" output primitive type is used: 432 * 433 * The geometry shader should generate 3 points for a single input triangle. 434 * These points should be emitted for each of the triangle's vertex 435 * locations and: 436 * 437 * * First vertex should be of (R, G, B, A) color; 438 * * Second vertex should be of (R', G', B', A') color; 439 * * Third vertex should be of (R'', G'', B'', A'') color; 440 * 441 * Each point should actually consist of 9 emitted points of size 1 (as 442 * described in test scenario 1.1), with the middle point being positioned 443 * at exact vertex location. This is to emulate larger point size than the 444 * minimum maximum allows. All emitted points should use the same color as 445 * parent point's. 446 * 447 * Test succeeds if centers of the rendered points have valid colors. 448 * 449 * 3.2. If "lines" output primitive type is used: 450 * 451 * Let: 452 * 453 * * TL represent top-left corner of the triangle's bounding box; 454 * * TR represent top-right corner of the triangle's bounding box; 455 * * BL represent bottom-left corner of the triangle's bounding box; 456 * * BR represent bottom-right corner of the triangle's bounding box; 457 * 458 * The geometry shader should draw 4 line segments for a single input 459 * triangle: 460 * 461 * * First line segment should start at BL and end at TL and use a static 462 * (R, G, B, A) color; 463 * * Second line segment should start at TL and end at TR and use a static 464 * (R', G', B', A') color; 465 * * Third line segment should start at TR and end at BR and use a static 466 * (R'', G'', B'', A'') color; 467 * * Fourth line segment should start at BR and end at BL and use a static 468 * (R, G', B'', A) color; 469 * 470 * Each line segment should actually consist of 3 separate line segments 471 * "stacked" on top of each other, with the middle segment being positioned 472 * as described above (as described in test scenario 2.2). This is to 473 * emulate line width that is larger than the minimum maximum allows. All 474 * emitted line segments should use the same color as parent line segment's. 475 * 476 * Test succeeds if centers of the rendered line segments have valid colors. 477 * 478 * 3.3. If "triangles" output primitive type is used: 479 * 480 * Test should take incoming triangle vertex locations and order them in the 481 * following order: 482 * 483 * a) A - vertex in the origin; 484 * b) B - the other vertex located on the same height as A; 485 * c) C - remaining vertex; 486 * 487 * Let D = BC/2. 488 * 489 * The test should emit ABD and ACD triangles for input ABC triangle data. 490 * First triangle emitted should take color of the first input vertex 491 * (not necessarily A!). 492 * The second one should use third vertex's color (not necessarily C!), 493 * with the first channel being multiplied by two. 494 * 495 * Test succeeds if centers of the rendered triangles have valid colors; 496 * 497 **/ 498 class GeometryShaderRenderingTrianglesCase : public GeometryShaderRenderingCase 499 { 500 public: 501 /* Public methods */ 502 GeometryShaderRenderingTrianglesCase(Context &context, const ExtParameters &extParams, const char *name, 503 bool use_adjacency_data, glw::GLenum drawcall_mode, 504 _shader_output_type output_type); 505 506 virtual ~GeometryShaderRenderingTrianglesCase(); 507 508 protected: 509 /* GeometryShaderRenderingCase interface implementation */ 510 unsigned int getAmountOfDrawInstances(); 511 unsigned int getAmountOfElementsPerInstance(); 512 unsigned int getAmountOfVerticesPerInstance(); 513 glw::GLenum getDrawCallMode(); 514 std::string getFragmentShaderCode(); 515 std::string getGeometryShaderCode(); 516 glw::GLuint getRawArraysDataBufferSize(bool instanced); 517 const void *getRawArraysDataBuffer(bool instanced); 518 void getRenderTargetSize(unsigned int n_instances, unsigned int *out_width, unsigned int *out_height); 519 glw::GLuint getUnorderedArraysDataBufferSize(bool instanced); 520 const void *getUnorderedArraysDataBuffer(bool instanced); 521 glw::GLuint getUnorderedElementsDataBufferSize(bool instanced); 522 const void *getUnorderedElementsDataBuffer(bool instanced); 523 glw::GLenum getUnorderedElementsDataType(); 524 glw::GLubyte getUnorderedElementsMaxIndex(); 525 glw::GLubyte getUnorderedElementsMinIndex(); 526 std::string getVertexShaderCode(); 527 void setUniformsBeforeDrawCall(_draw_call_type drawcall_type); 528 void verify(_draw_call_type drawcall_type, unsigned int instance_id, const unsigned char *data); 529 530 private: 531 /* Private variables */ 532 _shader_output_type m_output_type; 533 534 glw::GLenum m_drawcall_mode; 535 bool m_use_adjacency_data; 536 537 float *m_raw_array_instanced_data; 538 unsigned int m_raw_array_instanced_data_size; 539 float *m_raw_array_noninstanced_data; 540 unsigned int m_raw_array_noninstanced_data_size; 541 542 float *m_unordered_array_instanced_data; 543 unsigned int m_unordered_array_instanced_data_size; 544 float *m_unordered_array_noninstanced_data; 545 unsigned int m_unordered_array_noninstanced_data_size; 546 547 unsigned char *m_unordered_elements_instanced_data; 548 unsigned int m_unordered_elements_instanced_data_size; 549 unsigned char *m_unordered_elements_noninstanced_data; 550 unsigned int m_unordered_elements_noninstanced_data_size; 551 552 unsigned char m_unordered_elements_max_index; 553 unsigned char m_unordered_elements_min_index; 554 }; 555 556 } // namespace glcts 557 558 #endif // _ESEXTCGEOMETRYSHADERRENDERING_HPP 559