• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
~TessellationShaderVertexSpacing(void)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 */
_runglcts::TessellationShaderVertexSpacing::_run100 		_run()
101 		{
102 			memset(inner, 0, sizeof(inner));
103 			memset(outer, 0, sizeof(outer));
104 			data_cartesian	= 0;
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 */
_tess_coordinateglcts::TessellationShaderVertexSpacing::_tess_coordinate122 		_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 		 */
_tess_coordinateglcts::TessellationShaderVertexSpacing::_tess_coordinate135 		_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 */
_tess_coordinate_cartesianglcts::TessellationShaderVertexSpacing::_tess_coordinate_cartesian158 		_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 		 */
_tess_coordinate_cartesianglcts::TessellationShaderVertexSpacing::_tess_coordinate_cartesian169 		_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 */
_tess_coordinate_deltaglcts::TessellationShaderVertexSpacing::_tess_coordinate_delta195 		_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 		 */
_tess_edgeglcts::TessellationShaderVertexSpacing::_tess_edge227 		_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 */
_comparator_relative_to_base_pointglcts::TessellationShaderVertexSpacing::_comparator_relative_to_base_point246 		_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 		 */
_comparator_relative_to_base_pointglcts::TessellationShaderVertexSpacing::_comparator_relative_to_base_point254 		_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 		 */
operator ()glcts::TessellationShaderVertexSpacing::_comparator_relative_to_base_point266 		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
283 	{
284 		/* Constructor.
285 		 *
286 		 * @param in_base_coordinate Base tessellation coordinate to compare against.
287 		 */
_comparator_exact_tess_coordinate_matchglcts::TessellationShaderVertexSpacing::_comparator_exact_tess_coordinate_match288 		_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 		 */
operator ()glcts::TessellationShaderVertexSpacing::_comparator_exact_tess_coordinate_match300 		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