1 #ifndef _ESEXTCTESSELLATIONSHADERUTILS_HPP
2 #define _ESEXTCTESSELLATIONSHADERUTILS_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 #include "gluContextInfo.hpp"
28 #include "gluDefs.hpp"
29 #include "glwFunctions.hpp"
30 #include "tcuDefs.hpp"
31 #include <cstring>
32 #include <vector>
33 
34 namespace glcts
35 {
36 
37 /** Stores an ivec4 representation */
38 typedef struct _ivec4
39 {
40     int x;
41     int y;
42     int z;
43     int w;
44 
45     /** Constructor.
46      *
47      *  @param in_x Value to use for X component;
48      *  @param in_y Value to use for Y component;
49      *  @param in_z Value to use for Z component;
50      *  @param in_w Value to use for W component.
51      */
_ivec4glcts::_ivec452     _ivec4(int in_x, int in_y, int in_z, int in_w)
53     {
54         x = in_x;
55         y = in_y;
56         z = in_z;
57         w = in_w;
58     }
59 
60     /** Compares all components of _ivec4 instance with
61      *  another instance.
62      *
63      *  @return true if all components match, false otherwise.
64      **/
operator ==glcts::_ivec465     bool operator==(const _ivec4 &in) const
66     {
67         return (x == in.x) && (y == in.y) && (z == in.z) && (w == in.w);
68     }
69 
70     /** Implements inequality operator.
71      *
72      *  @return true if any of the compared components
73      *          do not match, false otherwise.
74      **/
operator !=glcts::_ivec475     bool operator!=(const _ivec4 &in) const
76     {
77         return !(*this == in);
78     }
79 } _ivec4;
80 
81 /* Stores a vec2 representation */
82 typedef struct _vec2
83 {
84     float x;
85     float y;
86 
87     /** Constructor.
88      *
89      *  @param in_x Value to use for X component;
90      *  @param in_y Value to use for Y component;
91      */
_vec2glcts::_vec292     _vec2(float in_x, float in_y)
93     {
94         x = in_x;
95         y = in_y;
96     }
97 
98     /** Compares all components of _vec2 instance with
99      *  another instance, using == operator.
100      *
101      *  @return true if all components match, false otherwise.
102      **/
operator ==glcts::_vec2103     bool operator==(const _vec2 &in) const
104     {
105         return (x == in.x) && (y == in.y);
106     }
107 
108     /** Implements inequality operator.
109      *
110      *  @return true if any of the compared components
111      *          do not match, false otherwise.
112      **/
operator !=glcts::_vec2113     bool operator!=(const _vec2 &in) const
114     {
115         return !(*this == in);
116     }
117 } _vec2;
118 
119 /* Stores a vec4 representation */
120 typedef struct _vec4
121 {
122     float x;
123     float y;
124     float z;
125     float w;
126 
127     /** Constructor.
128      *
129      *  @param in_x Value to use for X component;
130      *  @param in_y Value to use for Y component;
131      *  @param in_z Value to use for Z component;
132      *  @param in_w Value to use for W component.
133      */
_vec4glcts::_vec4134     _vec4(float in_x, float in_y, float in_z, float in_w)
135     {
136         x = in_x;
137         y = in_y;
138         z = in_z;
139         w = in_w;
140     }
141 
142     /** Compares all components of _vec4 instance with
143      *  another instance, using == operator.
144      *
145      *  @return true if all components match, false otherwise.
146      **/
operator ==glcts::_vec4147     bool operator==(const _vec4 &in) const
148     {
149         return (x == in.x) && (y == in.y) && (z == in.z) && (w == in.w);
150     }
151 
152     /** Implements inequality operator.
153      *
154      *  @return true if any of the compared components
155      *          do not match, false otherwise.
156      **/
operator !=glcts::_vec4157     bool operator!=(const _vec4 &in) const
158     {
159         return !(*this == in);
160     }
161 } _vec4;
162 
163 /** Defines a set of tessellation inner+outer levels */
164 typedef struct _tessellation_levels
165 {
166     float inner[2];
167     float outer[4];
168 
_tessellation_levelsglcts::_tessellation_levels169     _tessellation_levels()
170     {
171         memset(inner, 0, sizeof(inner));
172         memset(outer, 0, sizeof(outer));
173     }
174 } _tessellation_levels;
175 
176 /* Defines a vector of tessellation levels */
177 typedef std::vector<_tessellation_levels> _tessellation_levels_set;
178 typedef _tessellation_levels_set::const_iterator _tessellation_levels_set_const_iterator;
179 typedef _tessellation_levels_set::iterator _tessellation_levels_set_iterator;
180 
181 /* Determines condition that returned level sets should meet in order to be returned
182  * by TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode() .
183  */
184 typedef enum
185 {
186     /********* General modes: do not use these values in conjugation  *********/
187 
188     /* All combinations of values from the set {-1, 1, GL_MAX_TESS_GEN_LEVEL_EXT / 2,
189      * GL_MAX_TESS_GEN_LEVEL_EXT} will be used for inner/outer tesselelation
190      * levels relevant to user-specified primitive mode.
191      * An important exception is that the negative value will be SKIPPED for
192      * outer tessellation levels (because otherwise no geometry will be generated
193      * by the tessellator)
194      **/
195     TESSELLATION_LEVEL_SET_FILTER_ALL_COMBINATIONS = 0x1,
196 
197     /* Only combinations where:
198      *
199      * - inner tessellation levels use different values (inner[0] != inner[1])
200      * - outer tessellation levels use different values (outer[0] != outer[1] !=
201      *   != outer[2] != outer[3]);
202      *
203      * are allowed. */
204     TESSELLATION_LEVEL_SET_FILTER_INNER_AND_OUTER_LEVELS_USE_DIFFERENT_VALUES = 0x2,
205 
206     /* All inner/outer tessellation level use the same base value */
207     TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE = 0x4,
208 
209     /********* Flags: can be combined with above general mode values  *********/
210     TESSELLATION_LEVEL_SET_FILTER_EXCLUDE_NEGATIVE_BASE_VALUE = 0x8
211 } _tessellation_level_set_filter;
212 
213 /* Represents primitive modes supported by GL_EXT_tessellation_shader */
214 typedef enum
215 {
216     TESSELLATION_SHADER_PRIMITIVE_MODE_FIRST = 0,
217 
218     TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES = TESSELLATION_SHADER_PRIMITIVE_MODE_FIRST,
219     TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES,
220     TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
221 
222     TESSELLATION_SHADER_PRIMITIVE_MODE_COUNT,
223     TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN = TESSELLATION_SHADER_PRIMITIVE_MODE_COUNT
224 } _tessellation_primitive_mode;
225 
226 /** Represents vertex ordering modes supported by GL_EXT_tessellation_shader */
227 typedef enum
228 {
229     TESSELLATION_SHADER_VERTEX_ORDERING_CCW,
230     TESSELLATION_SHADER_VERTEX_ORDERING_CW,
231     TESSELLATION_SHADER_VERTEX_ORDERING_DEFAULT,
232     TESSELLATION_SHADER_VERTEX_ORDERING_UNKNOWN
233 } _tessellation_shader_vertex_ordering;
234 
235 /** Represents vertex spacing modes supported by GL_EXT_tessellation_shader */
236 typedef enum
237 {
238     TESSELLATION_SHADER_VERTEX_SPACING_FIRST,
239 
240     TESSELLATION_SHADER_VERTEX_SPACING_EQUAL = TESSELLATION_SHADER_VERTEX_SPACING_FIRST,
241     TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN,
242     TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD,
243     TESSELLATION_SHADER_VERTEX_SPACING_DEFAULT,
244 
245     TESSELLATION_SHADER_VERTEX_SPACING_COUNT,
246     TESSELLATION_SHADER_VERTEX_SPACING_UNKNOWN = TESSELLATION_SHADER_VERTEX_SPACING_COUNT
247 } _tessellation_shader_vertex_spacing;
248 
249 /** Defines what tesellation stages should be tested for a given test pass. */
250 typedef enum
251 {
252     TESSELLATION_TEST_TYPE_FIRST,
253 
254     TESSELLATION_TEST_TYPE_TCS_TES = TESSELLATION_TEST_TYPE_FIRST, /* tcs + tes stages defined */
255     TESSELLATION_TEST_TYPE_TES,                                    /* only tes stage defined */
256 
257     /* Always last */
258     TESSELLATION_TEST_TYPE_COUNT,
259     TESSELLATION_TEST_TYPE_UNKNOWN = TESSELLATION_TEST_TYPE_COUNT
260 } _tessellation_test_type;
261 
262 /* Stores various helper functions used across multiple tessellation shader tests */
263 class TessellationShaderUtils
264 {
265 public:
266     /* Public methods */
267     TessellationShaderUtils(const glw::Functions &gl, glcts::TestCaseBase *parentTest);
268     ~TessellationShaderUtils();
269 
270     void compileShaders(glw::GLint n_shaders, const glw::GLuint *shaders, bool should_succeed);
271 
272     static void convertBarycentricCoordinatesToCartesian(const float *barycentric_coordinates,
273                                                          float *out_cartesian_coordinates);
274 
275     static void convertCartesianCoordinatesToBarycentric(const float *cartesian_coordinates,
276                                                          float *out_barycentric_coordinates);
277 
278     unsigned int getAmountOfVerticesGeneratedByTessellator(_tessellation_primitive_mode primitive_mode,
279                                                            const float *inner_tessellation_level,
280                                                            const float *outer_tessellation_level,
281                                                            _tessellation_shader_vertex_spacing vertex_spacing,
282                                                            bool is_point_mode_enabled);
283 
284     std::vector<char> getDataGeneratedByTessellator(const float *inner, bool point_mode,
285                                                     _tessellation_primitive_mode primitive_mode,
286                                                     _tessellation_shader_vertex_ordering vertex_ordering,
287                                                     _tessellation_shader_vertex_spacing vertex_spacing,
288                                                     const float *outer);
289 
290     static std::string getESTokenForPrimitiveMode(_tessellation_primitive_mode primitive_mode);
291     static std::string getESTokenForVertexOrderingMode(_tessellation_shader_vertex_ordering vertex_ordering);
292     static std::string getESTokenForVertexSpacingMode(_tessellation_shader_vertex_spacing vertex_spacing);
293 
294     static std::string getGenericTCCode(unsigned int n_patch_vertices, bool should_use_glInvocationID_indexed_input);
295 
296     static std::string getGenericTECode(_tessellation_shader_vertex_spacing vertex_spacing,
297                                         _tessellation_primitive_mode primitive_mode,
298                                         _tessellation_shader_vertex_ordering vertex_ordering, bool point_mode);
299 
300     static glw::GLint getPatchVerticesForPrimitiveMode(_tessellation_primitive_mode primitive_mode);
301 
302     static void getTessellationLevelAfterVertexSpacing(_tessellation_shader_vertex_spacing vertex_spacing, float level,
303                                                        glw::GLint gl_max_tess_gen_level_value, float *out_clamped,
304                                                        float *out_clamped_and_rounded);
305 
306     static _tessellation_levels_set getTessellationLevelSetForPrimitiveMode(_tessellation_primitive_mode primitive_mode,
307                                                                             glw::GLint gl_max_tess_gen_level_value,
308                                                                             _tessellation_level_set_filter filter);
309 
310     static glw::GLenum getTFModeForPrimitiveMode(_tessellation_primitive_mode primitive_mode, bool is_point_mode);
311 
312     static bool isOuterEdgeVertex(_tessellation_primitive_mode primitive_mode, const float *tessellated_vertex_data);
313 
314     static bool isTriangleDefined(const float *triangle_vertex_data, const float *vertex_data);
315 
316 private:
317     /* Private type definitions */
318     /** Defines a single counter program */
319     typedef struct _tessellation_vertex_counter_program
320     {
321         /* Properties */
322         float inner_tess_level[2];
323         bool is_point_mode_enabled;
324         glw::GLint n_patch_vertices;
325         float outer_tess_level[4];
326         _tessellation_primitive_mode primitive_mode;
327         _tessellation_shader_vertex_spacing vertex_spacing;
328 
329         std::vector<char> m_data;
330         unsigned int n_data_vertices;
331 
332         glw::GLint po_id;
333         glw::GLint tc_id;
334         glw::GLint te_id;
335         glw::GLint tess_level_inner_uniform_location;
336         glw::GLint tess_level_outer_uniform_location;
337         const glw::Functions &m_gl;
338 
_tessellation_vertex_counter_programglcts::TessellationShaderUtils::_tessellation_vertex_counter_program339         _tessellation_vertex_counter_program(const glw::Functions &gl) : m_gl(gl)
340         {
341             memset(inner_tess_level, 0, sizeof(inner_tess_level));
342             memset(outer_tess_level, 0, sizeof(outer_tess_level));
343 
344             is_point_mode_enabled = false;
345             n_patch_vertices      = 0;
346             po_id                 = 0;
347             primitive_mode        = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
348             tc_id                 = 0;
349             te_id                 = 0;
350             vertex_spacing        = TESSELLATION_SHADER_VERTEX_SPACING_UNKNOWN;
351             n_data_vertices       = 0;
352 
353             tess_level_inner_uniform_location = -1;
354             tess_level_outer_uniform_location = -1;
355         }
356 
~_tessellation_vertex_counter_programglcts::TessellationShaderUtils::_tessellation_vertex_counter_program357         ~_tessellation_vertex_counter_program()
358         {
359             if (po_id != 0)
360             {
361                 m_gl.deleteProgram(po_id);
362                 po_id = 0;
363             }
364 
365             if (tc_id != 0)
366             {
367                 m_gl.deleteShader(tc_id);
368                 tc_id = 0;
369             }
370 
371             if (te_id != 0)
372             {
373                 m_gl.deleteShader(te_id);
374                 te_id = 0;
375             }
376         }
377     } _tessellation_vertex_counter_program;
378 
379     /* A vector of counter programs */
380     typedef std::vector<_tessellation_vertex_counter_program> _programs;
381     typedef _programs::const_iterator _programs_const_iterator;
382     typedef _programs::iterator _programs_iterator;
383 
384     /* Private methods */
385     void captureTessellationData(_tessellation_vertex_counter_program &program);
386     void deinit();
387     void init();
388 
389     void initTessellationVertexCounterProgram(const float *inner_tess_level, const float *outer_tess_level,
390                                               glw::GLint n_patch_vertices,
391                                               _tessellation_shader_vertex_spacing vertex_spacing,
392                                               _tessellation_primitive_mode primitive_mode, bool is_point_mode_enabled,
393                                               _tessellation_vertex_counter_program &result_descriptor);
394 
395     /* Private variables */
396     const glw::Functions &m_gl;
397     glw::GLuint m_bo_id;
398     glw::GLuint m_fs_id;
399     glw::GLuint m_qo_pg_id;
400     glw::GLuint m_vs_id;
401 
402     glcts::TestCaseBase *m_parent_test;
403 };
404 
405 } // namespace glcts
406 
407 #endif // _ESEXTCTESSELLATIONSHADERUTILS_HPP
408