Home | History | Annotate | Download | only in tessellation_shader
      1 #ifndef _ESEXTCTESSELLATIONSHADERVERTEXSPACING_HPP
      2 #define _ESEXTCTESSELLATIONSHADERVERTEXSPACING_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 "esextcTessellationShaderUtils.hpp"
     28 #include "gluShaderUtil.hpp"
     29 #include "tcuDefs.hpp"
     30 #include <deMath.h>
     31 
     32 namespace glcts
     33 {
     34 /** Implementation of Test Case 25
     35  *
     36  *  Make sure that vertex spacing mode defined in a tessellation evaluation
     37  *  shader affects the tessellation primitive generator as per specification,
     38  *  to the limit enforced by implementation-dependent behaviour.
     39  *  Consider all three tessellation primitive generator modes (triangles,
     40  *  quads, isolines). TE stage should be run in point mode.
     41  *  Make sure that by default the tessellation primitive generator works in
     42  *  equal_spacing spacing mode.
     43  *  Make sure that negative inner levels are clamped as defined for active
     44  *  vertex spacing mode.
     45  *
     46  *  Technical details:
     47  *
     48  *  0. Consider the following set: {-1 (where valid), 1, MAX_TESS_GEN_LEVEL_EXT / 2,
     49  *     MAX_TESS_GEN_LEVEL_EXT}. All combinations of values from this set
     50  *     in regard to relevant inner/outer tessellation levels for all
     51  *     primitive generator modes should be checked by this test.
     52  *
     53  *  1. This test should capture vertices output by TE stage and verify their
     54  *     locations. If an edge is defined by function y = a * t + b (a, b
     55  *     computed from locations of edge start & end points), t should be
     56  *     calculated for each vertex that is a part of the edge considered.
     57  *  2. Test passes if t values are in agreement with the specification
     58  *     (assume epsilon 1e-5) and vertex spacing mode considered.
     59  *
     60  *  This test implementation skips configurations meeting all of the following
     61  *  properties:
     62  *
     63  *  - primitive mode:      QUADS
     64  *  - vertex spacing mode: FRACTIONAL ODD
     65  *  - inner tess level[0]: <= 1
     66  *  - inner tess level[1]: <= 1
     67  *
     68  *  These configurations are affected by a nuance described in greater
     69  *  detail in Khronos Bugzilla#11979, which this test cannot handle.
     70  **/
     71 class TessellationShaderVertexSpacing : public TestCaseBase
     72 {
     73 public:
     74 	/* Public methods */
     75 	TessellationShaderVertexSpacing(Context& context, const ExtParameters& extParams);
     76 
     77 	virtual ~TessellationShaderVertexSpacing(void)
     78 	{
     79 	}
     80 
     81 	virtual void		  deinit(void);
     82 	void				  initTest(void);
     83 	virtual IterateResult iterate(void);
     84 
     85 private:
     86 	/* Private type definitions */
     87 	/** Stores properties of a single test run */
     88 	typedef struct _run
     89 	{
     90 		float								inner[2];
     91 		float								outer[4];
     92 		_tessellation_primitive_mode		primitive_mode;
     93 		_tessellation_shader_vertex_spacing vertex_spacing;
     94 
     95 		std::vector<char> data;
     96 		float*			  data_cartesian; /* only used for 'triangles' case */
     97 		unsigned int	  n_vertices;
     98 
     99 		/* Constructor. Resets all fields to default values */
    100 		_run()
    101 		{
    102 			memset(inner, 0, sizeof(inner));
    103 			memset(outer, 0, sizeof(outer));
    104 
    105 			n_vertices	 = 0;
    106 			primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
    107 			vertex_spacing = TESSELLATION_SHADER_VERTEX_SPACING_UNKNOWN;
    108 		}
    109 	} _run;
    110 
    111 	/** Stores either barycentric or Cartesian coordinate data
    112 	 *  (depending on primitive mode of a test run this structure
    113 	 *  will be instantiated for)
    114 	 */
    115 	typedef struct _tess_coordinate
    116 	{
    117 		float u;
    118 		float v;
    119 		float w;
    120 
    121 		/* Constructor. Resets all fields to 0 */
    122 		_tess_coordinate()
    123 		{
    124 			u = 0.0f;
    125 			v = 0.0f;
    126 			w = 0.0f;
    127 		}
    128 
    129 		/* Constructor.
    130 		 *
    131 		 * @param u Value to set for U component;
    132 		 * @param v Value to set for V component;
    133 		 * @param w Value to set for W component;
    134 		 */
    135 		_tess_coordinate(float _u, float _v, float _w)
    136 		{
    137 			this->u = _u;
    138 			this->v = _v;
    139 			this->w = _w;
    140 		}
    141 
    142 		/** Compares two barycentric/Cartesian coordinates, using test-wide epsilon.
    143 		 *
    144 		 *  @param in Coordinate to compare current instance against.
    145 		 *
    146 		 *  @return true if the coordinates are equal, false otherwise.
    147 		 **/
    148 		bool operator==(const _tess_coordinate& in) const;
    149 	} _tess_coordinate;
    150 
    151 	/** Stores Cartesian coordinate data. */
    152 	typedef struct _tess_coordinate_cartesian
    153 	{
    154 		float x;
    155 		float y;
    156 
    157 		/* Constructor. Resets all values to 0 */
    158 		_tess_coordinate_cartesian()
    159 		{
    160 			x = 0.0f;
    161 			y = 0.0f;
    162 		}
    163 
    164 		/* Constructor.
    165 		 *
    166 		 * @param x Value to use for X component;
    167 		 * @param y Value to use for Y component;
    168 		 */
    169 		_tess_coordinate_cartesian(float _x, float _y)
    170 		{
    171 			this->x = _x;
    172 			this->y = _y;
    173 		}
    174 
    175 		/** Compares two Cartesian coordinates, using test-wide epsilon.
    176 		 *
    177 		 *  @param in Coordinate to compare current instance against.
    178 		 *
    179 		 *  @return true if the coordinates are equal, false otherwise.
    180 		 **/
    181 		bool operator==(const _tess_coordinate_cartesian& in) const;
    182 	} _tess_coordinate_cartesian;
    183 
    184 	/** Stores information on:
    185 	 *
    186 	 *  - a delta between two coordinates;
    187 	 *  - amount of segments that had exactly that length.
    188 	 **/
    189 	typedef struct _tess_coordinate_delta
    190 	{
    191 		unsigned int counter;
    192 		float		 delta;
    193 
    194 		/* Constructor. Resets all values to 0 */
    195 		_tess_coordinate_delta()
    196 		{
    197 			counter = 0;
    198 			delta   = 0.0f;
    199 		}
    200 	} _tess_coordinate_delta;
    201 
    202 	/** Vector of coordinate deltas */
    203 	typedef std::vector<_tess_coordinate_delta>		_tess_coordinate_deltas;
    204 	typedef _tess_coordinate_deltas::const_iterator _tess_coordinate_deltas_const_iterator;
    205 	typedef _tess_coordinate_deltas::iterator		_tess_coordinate_deltas_iterator;
    206 
    207 	/** Vector of Cartesian coordinates making up an edge. */
    208 	typedef std::vector<_tess_coordinate_cartesian> _tess_edge_points;
    209 	typedef _tess_edge_points::const_iterator		_tess_edge_points_const_iterator;
    210 	typedef _tess_edge_points::iterator				_tess_edge_points_iterator;
    211 
    212 	/** Defines a single edge of a quad/triangle *or* a single isoline (depending
    213 	 *  on the primitive mode used for a test run, for which the edge is defined)
    214 	 */
    215 	typedef struct _tess_edge
    216 	{
    217 		_tess_edge_points points;
    218 		float			  edge_length;
    219 		float			  outermost_tess_level;
    220 		float			  tess_level;
    221 
    222 		/* Constructor.
    223 		 *
    224 		 * @param in_tess_level  Tessellation level value specific to the edge.
    225 		 * @param in_edge_length Total Euclidean length of the edge.
    226 		 */
    227 		_tess_edge(const float& in_tess_level, const float& in_outermost_tess_level, const float& in_edge_length)
    228 			: edge_length(in_edge_length), outermost_tess_level(in_outermost_tess_level), tess_level(in_tess_level)
    229 		{
    230 		}
    231 	} _tess_edge;
    232 
    233 	/** Vector of edges */
    234 	typedef std::vector<_tess_edge>		_tess_edges;
    235 	typedef _tess_edges::const_iterator _tess_edges_const_iterator;
    236 	typedef _tess_edges::iterator		_tess_edges_iterator;
    237 
    238 	/** Vector of test runs */
    239 	typedef std::vector<_run>	 _runs;
    240 	typedef _runs::const_iterator _runs_const_iterator;
    241 
    242 	/** Comparator that is used to sort points relative to a certain origin. */
    243 	struct _comparator_relative_to_base_point
    244 	{
    245 		/* Constructor. Sets all fields to 0 */
    246 		_comparator_relative_to_base_point() : base_point(0, 0)
    247 		{
    248 		}
    249 
    250 		/* Constructor.
    251 		 *
    252 		 * @param base_point Origin, against which all comparisons should be run against.
    253 		 */
    254 		_comparator_relative_to_base_point(const _tess_coordinate_cartesian& _base_point) : base_point(_base_point)
    255 		{
    256 		}
    257 
    258 		/* Tells which of the user-provided points is closer to the instance-specific
    259 		 * "origin".
    260 		 *
    261 		 * @param a First point to use.
    262 		 * @param b Second point to use.
    263 		 *
    264 		 * @return true if point @param a is closer to the "origin", false otherwise.
    265 		 */
    266 		bool operator()(_tess_coordinate_cartesian a, _tess_coordinate_cartesian b)
    267 		{
    268 			float distance_a_to_base =
    269 				deFloatSqrt((a.x - base_point.x) * (a.x - base_point.x) + (a.y - base_point.y) * (a.y - base_point.y));
    270 			float distance_b_to_base =
    271 				deFloatSqrt((b.x - base_point.x) * (b.x - base_point.x) + (b.y - base_point.y) * (b.y - base_point.y));
    272 
    273 			return distance_a_to_base < distance_b_to_base;
    274 		}
    275 
    276 		_tess_coordinate_cartesian base_point;
    277 	};
    278 
    279 	/** Comparator that is used to compare two tessellation coordinates using FP value
    280 	 *  equal operator.
    281 	 */
    282 	struct _comparator_exact_tess_coordinate_match : public std::unary_function<float, bool>
    283 	{
    284 		/* Constructor.
    285 		 *
    286 		 * @param in_base_coordinate Base tessellation coordinate to compare against.
    287 		 */
    288 		_comparator_exact_tess_coordinate_match(const _tess_coordinate_cartesian& in_base_coordinate)
    289 			: base_coordinate(in_base_coordinate)
    290 		{
    291 		}
    292 
    293 		/* Tells if the user-provided tessellation coordinate exactly matches the base tessellation
    294 		 * coordinate.
    295 		 *
    296 		 * @param value Tessellation coordinate to use for the operation.
    297 		 *
    298 		 * @return true if the coordinates are equal, false otherwise.
    299 		 */
    300 		bool operator()(const _tess_coordinate_cartesian& value)
    301 		{
    302 			return (value.x == base_coordinate.x) && (value.y == base_coordinate.y);
    303 		}
    304 
    305 		_tess_coordinate_cartesian base_coordinate;
    306 	};
    307 
    308 	/* Private methods */
    309 	static bool compareEdgeByX(_tess_coordinate_cartesian a, _tess_coordinate_cartesian b);
    310 	static bool compareEdgeByY(_tess_coordinate_cartesian a, _tess_coordinate_cartesian b);
    311 
    312 	bool isPointOnLine(const _tess_coordinate_cartesian& line_v1, const _tess_coordinate_cartesian& line_v2,
    313 					   const _tess_coordinate_cartesian& point);
    314 
    315 	_tess_edges getEdgesForIsolinesTessellation(const _run& run);
    316 	_tess_edges getEdgesForQuadsTessellation(const _run& run);
    317 	_tess_edges getEdgesForTrianglesTessellation(const _run& run);
    318 	void verifyEdges(const _tess_edges& edges, const _run& run);
    319 
    320 	/* Private variables */
    321 	glw::GLint				 m_gl_max_tess_gen_level_value;
    322 	glw::GLuint				 m_vao_id;
    323 	_runs					 m_runs;
    324 	TessellationShaderUtils* m_utils;
    325 };
    326 
    327 } // namespace glcts
    328 
    329 #endif // _ESEXTCTESSELLATIONSHADERVERTEXSPACING_HPP
    330