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