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