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