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