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
34namespace glcts
35{
36
37/** Stores an ivec4 representation */
38typedef 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	 */
52	_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	 **/
65	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	 **/
75	bool operator!=(const _ivec4& in) const
76	{
77		return !(*this == in);
78	}
79} _ivec4;
80
81/* Stores a vec2 representation */
82typedef 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	 */
92	_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	 **/
103	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	 **/
113	bool operator!=(const _vec2& in) const
114	{
115		return !(*this == in);
116	}
117} _vec2;
118
119/* Stores a vec4 representation */
120typedef 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	 */
134	_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	 **/
147	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	 **/
157	bool operator!=(const _vec4& in) const
158	{
159		return !(*this == in);
160	}
161} _vec4;
162
163/** Defines a set of tessellation inner+outer levels */
164typedef struct _tessellation_levels
165{
166	float inner[2];
167	float outer[4];
168
169	_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 */
177typedef std::vector<_tessellation_levels>		 _tessellation_levels_set;
178typedef _tessellation_levels_set::const_iterator _tessellation_levels_set_const_iterator;
179typedef _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 */
184typedef enum {
185	/********* General modes: do not use these values in conjugation  *********/
186
187	/* All combinations of values from the set {-1, 1, GL_MAX_TESS_GEN_LEVEL_EXT / 2,
188	 * GL_MAX_TESS_GEN_LEVEL_EXT} will be used for inner/outer tesselelation
189	 * levels relevant to user-specified primitive mode.
190	 * An important exception is that the negative value will be SKIPPED for
191	 * outer tessellation levels (because otherwise no geometry will be generated
192	 * by the tessellator)
193	 **/
194	TESSELLATION_LEVEL_SET_FILTER_ALL_COMBINATIONS = 0x1,
195
196	/* Only combinations where:
197	 *
198	 * - inner tessellation levels use different values (inner[0] != inner[1])
199	 * - outer tessellation levels use different values (outer[0] != outer[1] !=
200	 *   != outer[2] != outer[3]);
201	 *
202	 * are allowed. */
203	TESSELLATION_LEVEL_SET_FILTER_INNER_AND_OUTER_LEVELS_USE_DIFFERENT_VALUES = 0x2,
204
205	/* All inner/outer tessellation level use the same base value */
206	TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE = 0x4,
207
208	/********* Flags: can be combined with above general mode values  *********/
209	TESSELLATION_LEVEL_SET_FILTER_EXCLUDE_NEGATIVE_BASE_VALUE = 0x8
210} _tessellation_level_set_filter;
211
212/* Represents primitive modes supported by GL_EXT_tessellation_shader */
213typedef enum {
214	TESSELLATION_SHADER_PRIMITIVE_MODE_FIRST = 0,
215
216	TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES = TESSELLATION_SHADER_PRIMITIVE_MODE_FIRST,
217	TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES,
218	TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
219
220	TESSELLATION_SHADER_PRIMITIVE_MODE_COUNT,
221	TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN = TESSELLATION_SHADER_PRIMITIVE_MODE_COUNT
222} _tessellation_primitive_mode;
223
224/** Represents vertex ordering modes supported by GL_EXT_tessellation_shader */
225typedef enum {
226	TESSELLATION_SHADER_VERTEX_ORDERING_CCW,
227	TESSELLATION_SHADER_VERTEX_ORDERING_CW,
228	TESSELLATION_SHADER_VERTEX_ORDERING_DEFAULT,
229	TESSELLATION_SHADER_VERTEX_ORDERING_UNKNOWN
230} _tessellation_shader_vertex_ordering;
231
232/** Represents vertex spacing modes supported by GL_EXT_tessellation_shader */
233typedef enum {
234	TESSELLATION_SHADER_VERTEX_SPACING_FIRST,
235
236	TESSELLATION_SHADER_VERTEX_SPACING_EQUAL = TESSELLATION_SHADER_VERTEX_SPACING_FIRST,
237	TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN,
238	TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD,
239	TESSELLATION_SHADER_VERTEX_SPACING_DEFAULT,
240
241	TESSELLATION_SHADER_VERTEX_SPACING_COUNT,
242	TESSELLATION_SHADER_VERTEX_SPACING_UNKNOWN = TESSELLATION_SHADER_VERTEX_SPACING_COUNT
243} _tessellation_shader_vertex_spacing;
244
245/** Defines what tesellation stages should be tested for a given test pass. */
246typedef enum {
247	TESSELLATION_TEST_TYPE_FIRST,
248
249	TESSELLATION_TEST_TYPE_TCS_TES = TESSELLATION_TEST_TYPE_FIRST, /* tcs + tes stages defined */
250	TESSELLATION_TEST_TYPE_TES,									   /* only tes stage defined */
251
252	/* Always last */
253	TESSELLATION_TEST_TYPE_COUNT,
254	TESSELLATION_TEST_TYPE_UNKNOWN = TESSELLATION_TEST_TYPE_COUNT
255} _tessellation_test_type;
256
257/* Stores various helper functions used across multiple tessellation shader tests */
258class TessellationShaderUtils
259{
260public:
261	/* Public methods */
262	TessellationShaderUtils(const glw::Functions& gl, glcts::TestCaseBase* parentTest);
263	~TessellationShaderUtils();
264
265	void compileShaders(glw::GLint n_shaders, const glw::GLuint* shaders, bool should_succeed);
266
267	static void convertBarycentricCoordinatesToCartesian(const float* barycentric_coordinates,
268														 float*		  out_cartesian_coordinates);
269
270	static void convertCartesianCoordinatesToBarycentric(const float* cartesian_coordinates,
271														 float*		  out_barycentric_coordinates);
272
273	unsigned int getAmountOfVerticesGeneratedByTessellator(_tessellation_primitive_mode		   primitive_mode,
274														   const float*						   inner_tessellation_level,
275														   const float*						   outer_tessellation_level,
276														   _tessellation_shader_vertex_spacing vertex_spacing,
277														   bool								   is_point_mode_enabled);
278
279	std::vector<char> getDataGeneratedByTessellator(const float* inner, bool point_mode,
280													_tessellation_primitive_mode		 primitive_mode,
281													_tessellation_shader_vertex_ordering vertex_ordering,
282													_tessellation_shader_vertex_spacing  vertex_spacing,
283													const float*						 outer);
284
285	static std::string getESTokenForPrimitiveMode(_tessellation_primitive_mode primitive_mode);
286	static std::string getESTokenForVertexOrderingMode(_tessellation_shader_vertex_ordering vertex_ordering);
287	static std::string getESTokenForVertexSpacingMode(_tessellation_shader_vertex_spacing vertex_spacing);
288
289	static std::string getGenericTCCode(unsigned int n_patch_vertices, bool should_use_glInvocationID_indexed_input);
290
291	static std::string getGenericTECode(_tessellation_shader_vertex_spacing  vertex_spacing,
292										_tessellation_primitive_mode		 primitive_mode,
293										_tessellation_shader_vertex_ordering vertex_ordering, bool point_mode);
294
295	static glw::GLint getPatchVerticesForPrimitiveMode(_tessellation_primitive_mode primitive_mode);
296
297	static void getTessellationLevelAfterVertexSpacing(_tessellation_shader_vertex_spacing vertex_spacing, float level,
298													   glw::GLint gl_max_tess_gen_level_value, float* out_clamped,
299													   float* out_clamped_and_rounded);
300
301	static _tessellation_levels_set getTessellationLevelSetForPrimitiveMode(_tessellation_primitive_mode primitive_mode,
302																			glw::GLint gl_max_tess_gen_level_value,
303																			_tessellation_level_set_filter filter);
304
305	static glw::GLenum getTFModeForPrimitiveMode(_tessellation_primitive_mode primitive_mode, bool is_point_mode);
306
307	static bool isOuterEdgeVertex(_tessellation_primitive_mode primitive_mode, const float* tessellated_vertex_data);
308
309	static bool isTriangleDefined(const float* triangle_vertex_data, const float* vertex_data);
310
311private:
312	/* Private type definitions */
313	/** Defines a single counter program */
314	typedef struct _tessellation_vertex_counter_program
315	{
316		/* Properties */
317		float								inner_tess_level[2];
318		bool								is_point_mode_enabled;
319		glw::GLint							n_patch_vertices;
320		float								outer_tess_level[4];
321		_tessellation_primitive_mode		primitive_mode;
322		_tessellation_shader_vertex_spacing vertex_spacing;
323
324		std::vector<char> m_data;
325		unsigned int	  n_data_vertices;
326
327		glw::GLint			  po_id;
328		glw::GLint			  tc_id;
329		glw::GLint			  te_id;
330		glw::GLint			  tess_level_inner_uniform_location;
331		glw::GLint			  tess_level_outer_uniform_location;
332		const glw::Functions& m_gl;
333
334		_tessellation_vertex_counter_program(const glw::Functions& gl) : m_gl(gl)
335		{
336			memset(inner_tess_level, 0, sizeof(inner_tess_level));
337			memset(outer_tess_level, 0, sizeof(outer_tess_level));
338
339			is_point_mode_enabled = false;
340			n_patch_vertices	  = 0;
341			po_id				  = 0;
342			primitive_mode		  = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
343			tc_id				  = 0;
344			te_id				  = 0;
345			vertex_spacing		  = TESSELLATION_SHADER_VERTEX_SPACING_UNKNOWN;
346			n_data_vertices		  = 0;
347
348			tess_level_inner_uniform_location = -1;
349			tess_level_outer_uniform_location = -1;
350		}
351
352		~_tessellation_vertex_counter_program()
353		{
354			if (po_id != 0)
355			{
356				m_gl.deleteProgram(po_id);
357				po_id = 0;
358			}
359
360			if (tc_id != 0)
361			{
362				m_gl.deleteShader(tc_id);
363				tc_id = 0;
364			}
365
366			if (te_id != 0)
367			{
368				m_gl.deleteShader(te_id);
369				te_id = 0;
370			}
371		}
372	} _tessellation_vertex_counter_program;
373
374	/* A vector of counter programs */
375	typedef std::vector<_tessellation_vertex_counter_program> _programs;
376	typedef _programs::const_iterator						  _programs_const_iterator;
377	typedef _programs::iterator								  _programs_iterator;
378
379	/* Private methods */
380	void captureTessellationData(_tessellation_vertex_counter_program& program);
381	void deinit();
382	void init();
383
384	void initTessellationVertexCounterProgram(const float* inner_tess_level, const float* outer_tess_level,
385											  glw::GLint						  n_patch_vertices,
386											  _tessellation_shader_vertex_spacing vertex_spacing,
387											  _tessellation_primitive_mode primitive_mode, bool is_point_mode_enabled,
388											  _tessellation_vertex_counter_program& result_descriptor);
389
390	/* Private variables */
391	const glw::Functions& m_gl;
392	glw::GLuint			  m_bo_id;
393	glw::GLuint			  m_fs_id;
394	glw::GLuint			  m_qo_pg_id;
395	glw::GLuint			  m_vs_id;
396
397	glcts::TestCaseBase* m_parent_test;
398};
399
400} // namespace glcts
401
402#endif // _ESEXTCTESSELLATIONSHADERUTILS_HPP
403