Home | History | Annotate | Download | only in tessellation_shader
      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 	 */
     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 */
     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 	 */
     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 */
    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 	 */
    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 */
    164 typedef 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 */
    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 	/********* 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 */
    213 typedef 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 */
    225 typedef 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 */
    233 typedef 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. */
    246 typedef 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 */
    258 class TessellationShaderUtils
    259 {
    260 public:
    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 
    311 private:
    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