1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * OpenGL Conformance Test Suite 3e5c31af7Sopenharmony_ci * ----------------------------- 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright (c) 2014-2016 The Khronos Group Inc. 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci */ /*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief 22e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "esextcTessellationShaderIsolines.hpp" 25e5c31af7Sopenharmony_ci#include "esextcTessellationShaderUtils.hpp" 26e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp" 27e5c31af7Sopenharmony_ci#include "gluDefs.hpp" 28e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 29e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 30e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 31e5c31af7Sopenharmony_ci 32e5c31af7Sopenharmony_cinamespace glcts 33e5c31af7Sopenharmony_ci{ 34e5c31af7Sopenharmony_ci 35e5c31af7Sopenharmony_ci/** Constructor 36e5c31af7Sopenharmony_ci * 37e5c31af7Sopenharmony_ci * @param context Test context 38e5c31af7Sopenharmony_ci **/ 39e5c31af7Sopenharmony_ciTessellationShadersIsolines::TessellationShadersIsolines(Context& context, const ExtParameters& extParams) 40e5c31af7Sopenharmony_ci : TestCaseBase(context, extParams, "isolines_tessellation", 41e5c31af7Sopenharmony_ci "Verifies that the number of isolines generated during tessellation is " 42e5c31af7Sopenharmony_ci "derived from the first outer tessellation level.\n" 43e5c31af7Sopenharmony_ci "Makes sure that the number of segments in each isoline is derived from " 44e5c31af7Sopenharmony_ci "the second outer tessellation level.\n" 45e5c31af7Sopenharmony_ci "Makes sure that both inner tessellation levels and the 3rd and the 4th " 46e5c31af7Sopenharmony_ci "outer tessellation levels do not affect the tessellation process.\n" 47e5c31af7Sopenharmony_ci "Makes sure that equal_spacing vertex spacing mode does not affect amount" 48e5c31af7Sopenharmony_ci " of generated isolines.\n" 49e5c31af7Sopenharmony_ci "Makes sure no line is drawn between (0, 1) and (1, 1) in (u, v) domain.") 50e5c31af7Sopenharmony_ci , m_irrelevant_tess_value_1(0.0f) 51e5c31af7Sopenharmony_ci , m_irrelevant_tess_value_2(0.0f) 52e5c31af7Sopenharmony_ci , m_utils_ptr(DE_NULL) 53e5c31af7Sopenharmony_ci , m_vao_id(0) 54e5c31af7Sopenharmony_ci{ 55e5c31af7Sopenharmony_ci /* Left blank on purpose */ 56e5c31af7Sopenharmony_ci} 57e5c31af7Sopenharmony_ci 58e5c31af7Sopenharmony_ci/** Checks that amount of isolines generated during tessellation corresponds to the 59e5c31af7Sopenharmony_ci * first outer tessellation level. 60e5c31af7Sopenharmony_ci * 61e5c31af7Sopenharmony_ci * This check needs not to operate over all test results generated for a particular 62e5c31af7Sopenharmony_ci * vertex spacing mode. 63e5c31af7Sopenharmony_ci * 64e5c31af7Sopenharmony_ci * @param test_result Value of MAX_TESS_GEN_LEVEL token. For ES3.1 it will be equal to 65e5c31af7Sopenharmony_ci * GL_MAX_TESS_GEN_LEVEL_EXT and for ES3.2 to GL_MAX_TESS_GEN_LEVEL. 66e5c31af7Sopenharmony_ci * 67e5c31af7Sopenharmony_ci **/ 68e5c31af7Sopenharmony_civoid TessellationShadersIsolines::checkFirstOuterTessellationLevelEffect(_test_result& test_result, 69e5c31af7Sopenharmony_ci const glw::GLenum glMaxTessGenLevelToken) 70e5c31af7Sopenharmony_ci{ 71e5c31af7Sopenharmony_ci glcts::Context& context = test_result.parent->parent->getContext(); 72e5c31af7Sopenharmony_ci const glw::Functions& gl = context.getRenderContext().getFunctions(); 73e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_gen_level_value = 0; 74e5c31af7Sopenharmony_ci unsigned int n_isolines_expected = 0; 75e5c31af7Sopenharmony_ci 76e5c31af7Sopenharmony_ci if (test_result.n_vertices != 0) 77e5c31af7Sopenharmony_ci { 78e5c31af7Sopenharmony_ci /* Calculate how many isolines we're expecting */ 79e5c31af7Sopenharmony_ci gl.getIntegerv(glMaxTessGenLevelToken, &gl_max_tess_gen_level_value); 80e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 81e5c31af7Sopenharmony_ci 82e5c31af7Sopenharmony_ci /* NOTE: Amount of isolines should always be based on TESSELLATION_SHADER_VERTEX_SPACING_EQUAL 83e5c31af7Sopenharmony_ci * vertex spacing mode, even if a different one is defined in TE stage. 84e5c31af7Sopenharmony_ci */ 85e5c31af7Sopenharmony_ci float outer_zero_tess_level_clamped_rounded = 0.0f; 86e5c31af7Sopenharmony_ci 87e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing( 88e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, test_result.parent->outer_tess_levels[0], 89e5c31af7Sopenharmony_ci gl_max_tess_gen_level_value, DE_NULL, /* out_clamped */ 90e5c31af7Sopenharmony_ci &outer_zero_tess_level_clamped_rounded); 91e5c31af7Sopenharmony_ci 92e5c31af7Sopenharmony_ci n_isolines_expected = (unsigned int)outer_zero_tess_level_clamped_rounded; 93e5c31af7Sopenharmony_ci 94e5c31af7Sopenharmony_ci if (test_result.n_isolines != n_isolines_expected) 95e5c31af7Sopenharmony_ci { 96e5c31af7Sopenharmony_ci tcu::TestContext& test = test_result.parent->parent->getTestContext(); 97e5c31af7Sopenharmony_ci 98e5c31af7Sopenharmony_ci test.getLog() << tcu::TestLog::Message 99e5c31af7Sopenharmony_ci << "Tessellator generated an invalid amount of isolines:" << test_result.n_isolines 100e5c31af7Sopenharmony_ci << " instead of the expected amount:" << n_isolines_expected 101e5c31af7Sopenharmony_ci << " for the following inner tessellation level configuration:" 102e5c31af7Sopenharmony_ci << " (" << test_result.parent->inner_tess_levels[0] << ", " 103e5c31af7Sopenharmony_ci << test_result.parent->inner_tess_levels[1] << ")" 104e5c31af7Sopenharmony_ci << " and the following outer tesellation level configuration:" 105e5c31af7Sopenharmony_ci << " (" << test_result.parent->outer_tess_levels[0] << ", " 106e5c31af7Sopenharmony_ci << test_result.parent->outer_tess_levels[1] << ", " 107e5c31af7Sopenharmony_ci << test_result.parent->outer_tess_levels[2] << ", " 108e5c31af7Sopenharmony_ci << test_result.parent->outer_tess_levels[3] << ")" << tcu::TestLog::EndMessage; 109e5c31af7Sopenharmony_ci 110e5c31af7Sopenharmony_ci TCU_FAIL("Invalid amount of isolines generated by tessellator"); 111e5c31af7Sopenharmony_ci } 112e5c31af7Sopenharmony_ci } /* if (test_run.n_vertices != 0) */ 113e5c31af7Sopenharmony_ci} 114e5c31af7Sopenharmony_ci 115e5c31af7Sopenharmony_ci/** Makes sure that tessellation coordinates generated for inner+outer tessellation level 116e5c31af7Sopenharmony_ci * configurations, between which irrelevant levels have been defined, are exactly the same. 117e5c31af7Sopenharmony_ci * 118e5c31af7Sopenharmony_ci * This check needs to operate over all test results generated for a particular 119e5c31af7Sopenharmony_ci * vertex spacing mode. 120e5c31af7Sopenharmony_ci * 121e5c31af7Sopenharmony_ci * This function throws a TestError exception if the check fails. 122e5c31af7Sopenharmony_ci **/ 123e5c31af7Sopenharmony_civoid TessellationShadersIsolines::checkIrrelevantTessellationLevelsHaveNoEffect() 124e5c31af7Sopenharmony_ci{ 125e5c31af7Sopenharmony_ci /* Make sure that two example data sets, for which irrelevant tessellation levels have 126e5c31af7Sopenharmony_ci * been changed, are exactly the same 127e5c31af7Sopenharmony_ci */ 128e5c31af7Sopenharmony_ci DE_ASSERT(m_test_results.find(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL) != m_test_results.end()); 129e5c31af7Sopenharmony_ci 130e5c31af7Sopenharmony_ci const float epsilon = 1e-5f; 131e5c31af7Sopenharmony_ci float irrelevant_tess_level1_rounded_clamped = 0.0f; 132e5c31af7Sopenharmony_ci int irrelevant_tess_level1 = 0; 133e5c31af7Sopenharmony_ci float irrelevant_tess_level2_rounded_clamped = 0.0f; 134e5c31af7Sopenharmony_ci int irrelevant_tess_level2 = 0; 135e5c31af7Sopenharmony_ci _test_results_iterator test_result_iterator_start = 136e5c31af7Sopenharmony_ci m_test_results[TESSELLATION_SHADER_VERTEX_SPACING_EQUAL].begin(); 137e5c31af7Sopenharmony_ci _test_results_iterator test_result_iterator_end = m_test_results[TESSELLATION_SHADER_VERTEX_SPACING_EQUAL].end(); 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_ci /* Calculate two tessellation level values that we've used in init() */ 140e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 141e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_gen_level_value = 0; 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value); 144e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 145e5c31af7Sopenharmony_ci 146e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing( 147e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, m_irrelevant_tess_value_1, gl_max_tess_gen_level_value, 148e5c31af7Sopenharmony_ci DE_NULL, /* out_clamped */ 149e5c31af7Sopenharmony_ci &irrelevant_tess_level1_rounded_clamped); 150e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing( 151e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, m_irrelevant_tess_value_2, gl_max_tess_gen_level_value, 152e5c31af7Sopenharmony_ci DE_NULL, /* out_clamped */ 153e5c31af7Sopenharmony_ci &irrelevant_tess_level2_rounded_clamped); 154e5c31af7Sopenharmony_ci 155e5c31af7Sopenharmony_ci irrelevant_tess_level1 = (int)irrelevant_tess_level1_rounded_clamped; 156e5c31af7Sopenharmony_ci irrelevant_tess_level2 = (int)irrelevant_tess_level2_rounded_clamped; 157e5c31af7Sopenharmony_ci 158e5c31af7Sopenharmony_ci DE_ASSERT(de::abs(irrelevant_tess_level1 - irrelevant_tess_level2) > 0); 159e5c31af7Sopenharmony_ci 160e5c31af7Sopenharmony_ci /* Iterate through all test runs for equal spacing */ 161e5c31af7Sopenharmony_ci for (_test_results_iterator test_result_iterator = test_result_iterator_start; 162e5c31af7Sopenharmony_ci test_result_iterator != test_result_iterator_end; test_result_iterator++) 163e5c31af7Sopenharmony_ci { 164e5c31af7Sopenharmony_ci _test_result test_result = *test_result_iterator; 165e5c31af7Sopenharmony_ci 166e5c31af7Sopenharmony_ci if (test_result.irrelevant_tess_level == irrelevant_tess_level1) 167e5c31af7Sopenharmony_ci { 168e5c31af7Sopenharmony_ci _test_result test_result_reference = 169e5c31af7Sopenharmony_ci findTestResult(irrelevant_tess_level2, test_result.outer1_tess_level, test_result.outer2_tess_level, 170e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_SPACING_EQUAL); 171e5c31af7Sopenharmony_ci 172e5c31af7Sopenharmony_ci /* data for current test run and the reference one should match */ 173e5c31af7Sopenharmony_ci DE_ASSERT(test_result.n_vertices == test_result_reference.n_vertices); 174e5c31af7Sopenharmony_ci 175e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < test_result.n_vertices; ++n_vertex) 176e5c31af7Sopenharmony_ci { 177e5c31af7Sopenharmony_ci const float* vertex_data_1 = (&test_result.rendered_data[0]) + n_vertex * 3; /* components */ 178e5c31af7Sopenharmony_ci const float* vertex_data_2 = (&test_result_reference.rendered_data[0]) + n_vertex * 3; /* components */ 179e5c31af7Sopenharmony_ci 180e5c31af7Sopenharmony_ci if (de::abs(vertex_data_1[0] - vertex_data_2[0]) > epsilon || 181e5c31af7Sopenharmony_ci de::abs(vertex_data_1[1] - vertex_data_2[1]) > epsilon || 182e5c31af7Sopenharmony_ci de::abs(vertex_data_1[2] - vertex_data_2[2]) > epsilon) 183e5c31af7Sopenharmony_ci { 184e5c31af7Sopenharmony_ci tcu::TestContext& test = test_result_iterator->parent->parent->getTestContext(); 185e5c31af7Sopenharmony_ci 186e5c31af7Sopenharmony_ci test.getLog() 187e5c31af7Sopenharmony_ci << tcu::TestLog::Message 188e5c31af7Sopenharmony_ci << "Tessellator generated non-matching data for different tessellation level configurations, " 189e5c31af7Sopenharmony_ci "where only irrelevant tessellation levels have been changed; " 190e5c31af7Sopenharmony_ci << " data generated for {inner:" 191e5c31af7Sopenharmony_ci << " (" << test_result.parent->inner_tess_levels[0] << ", " 192e5c31af7Sopenharmony_ci << test_result.parent->inner_tess_levels[1] << ")" 193e5c31af7Sopenharmony_ci << " outer:" 194e5c31af7Sopenharmony_ci << " (" << test_result.parent->outer_tess_levels[0] << ", " 195e5c31af7Sopenharmony_ci << test_result.parent->outer_tess_levels[1] << ", " << test_result.parent->outer_tess_levels[2] 196e5c31af7Sopenharmony_ci << ", " << test_result.parent->outer_tess_levels[3] << ")" 197e5c31af7Sopenharmony_ci << "}:" 198e5c31af7Sopenharmony_ci << " (" << vertex_data_1[0] << ", " << vertex_data_1[1] << ", " << vertex_data_1[2] << ")" 199e5c31af7Sopenharmony_ci << ", data generated for {inner:" 200e5c31af7Sopenharmony_ci << " (" << test_result_reference.parent->inner_tess_levels[0] << ", " 201e5c31af7Sopenharmony_ci << test_result_reference.parent->inner_tess_levels[1] << ")" 202e5c31af7Sopenharmony_ci << " outer:" 203e5c31af7Sopenharmony_ci << " (" << test_result_reference.parent->outer_tess_levels[0] << ", " 204e5c31af7Sopenharmony_ci << test_result_reference.parent->outer_tess_levels[1] << ", " 205e5c31af7Sopenharmony_ci << test_result_reference.parent->outer_tess_levels[2] << ", " 206e5c31af7Sopenharmony_ci << test_result_reference.parent->outer_tess_levels[3] << ")" 207e5c31af7Sopenharmony_ci << "}:" 208e5c31af7Sopenharmony_ci << " (" << vertex_data_2[0] << ", " << vertex_data_2[1] << ", " << vertex_data_2[2] << ")" 209e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 210e5c31af7Sopenharmony_ci 211e5c31af7Sopenharmony_ci TCU_FAIL("Invalid amount of unique line segments generated by tessellator"); 212e5c31af7Sopenharmony_ci } /* if (equal and fractional_even data mismatch) */ 213e5c31af7Sopenharmony_ci } /* for (all vertices) */ 214e5c31af7Sopenharmony_ci } /* if (current test result's irrelelvant tessellation levels match what we're after) */ 215e5c31af7Sopenharmony_ci } /* for (all test runs) */ 216e5c31af7Sopenharmony_ci} 217e5c31af7Sopenharmony_ci 218e5c31af7Sopenharmony_ci/** Checks that the amount of line segments generated per isoline is as defined by 219e5c31af7Sopenharmony_ci * second outer tessellation level. 220e5c31af7Sopenharmony_ci * 221e5c31af7Sopenharmony_ci * This check needs not to operate over all test results generated for a particular 222e5c31af7Sopenharmony_ci * vertex spacing mode. 223e5c31af7Sopenharmony_ci * 224e5c31af7Sopenharmony_ci * This function throws a TestError exception if the check fails. 225e5c31af7Sopenharmony_ci * 226e5c31af7Sopenharmony_ci * @param test_result Test result descriptor to perform the check on. 227e5c31af7Sopenharmony_ci * 228e5c31af7Sopenharmony_ci **/ 229e5c31af7Sopenharmony_civoid TessellationShadersIsolines::checkSecondOuterTessellationLevelEffect(_test_result& test_result, 230e5c31af7Sopenharmony_ci const glw::GLenum glMaxTessGenLevelToken) 231e5c31af7Sopenharmony_ci{ 232e5c31af7Sopenharmony_ci typedef float _line_segment_x; 233e5c31af7Sopenharmony_ci typedef std::pair<_line_segment_x, _line_segment_x> _line_segment; 234e5c31af7Sopenharmony_ci typedef std::vector<_line_segment> _line_segments; 235e5c31af7Sopenharmony_ci typedef _line_segments::iterator _line_segments_iterator; 236e5c31af7Sopenharmony_ci 237e5c31af7Sopenharmony_ci glcts::Context& context = test_result.parent->parent->getContext(); 238e5c31af7Sopenharmony_ci const float epsilon = 1e-5f; 239e5c31af7Sopenharmony_ci _line_segments found_line_segments; 240e5c31af7Sopenharmony_ci const glw::Functions& gl = context.getRenderContext().getFunctions(); 241e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_gen_level_value = 0; 242e5c31af7Sopenharmony_ci float outer_tess_levels1_clamped_rounded = 0.0f; 243e5c31af7Sopenharmony_ci unsigned int n_line_segments_per_isoline_expected = 0; 244e5c31af7Sopenharmony_ci unsigned int n_unique_line_segments_found = 0; 245e5c31af7Sopenharmony_ci 246e5c31af7Sopenharmony_ci if (test_result.n_vertices != 0) 247e5c31af7Sopenharmony_ci { 248e5c31af7Sopenharmony_ci /* Calculate how many isolines we're expecting */ 249e5c31af7Sopenharmony_ci gl.getIntegerv(glMaxTessGenLevelToken, &gl_max_tess_gen_level_value); 250e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 251e5c31af7Sopenharmony_ci 252e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing( 253e5c31af7Sopenharmony_ci test_result.parent->vertex_spacing_mode, test_result.parent->outer_tess_levels[1], 254e5c31af7Sopenharmony_ci gl_max_tess_gen_level_value, DE_NULL, /* out_clamped */ 255e5c31af7Sopenharmony_ci &outer_tess_levels1_clamped_rounded); 256e5c31af7Sopenharmony_ci 257e5c31af7Sopenharmony_ci n_line_segments_per_isoline_expected = (unsigned int)outer_tess_levels1_clamped_rounded; 258e5c31af7Sopenharmony_ci 259e5c31af7Sopenharmony_ci /* Count unique line segments found in all the line segments making up the result data set. */ 260e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < test_result.n_vertices; 261e5c31af7Sopenharmony_ci n_vertex += 2 /* vertices per line segment */) 262e5c31af7Sopenharmony_ci { 263e5c31af7Sopenharmony_ci bool was_line_segment_found = false; 264e5c31af7Sopenharmony_ci const float* vertex1 = (&test_result.rendered_data[0]) + n_vertex * 3; /* components */ 265e5c31af7Sopenharmony_ci float vertex1_x = vertex1[0]; 266e5c31af7Sopenharmony_ci const float* vertex2 = (&test_result.rendered_data[0]) + (n_vertex + 1) * 3; /* components */ 267e5c31af7Sopenharmony_ci float vertex2_x = vertex2[0]; 268e5c31af7Sopenharmony_ci 269e5c31af7Sopenharmony_ci for (_line_segments_iterator found_line_segments_iterator = found_line_segments.begin(); 270e5c31af7Sopenharmony_ci found_line_segments_iterator != found_line_segments.end(); found_line_segments_iterator++) 271e5c31af7Sopenharmony_ci { 272e5c31af7Sopenharmony_ci float& found_vertex1_x = found_line_segments_iterator->first; 273e5c31af7Sopenharmony_ci float& found_vertex2_x = found_line_segments_iterator->second; 274e5c31af7Sopenharmony_ci 275e5c31af7Sopenharmony_ci if (de::abs(found_vertex1_x - vertex1_x) < epsilon && de::abs(found_vertex2_x - vertex2_x) < epsilon) 276e5c31af7Sopenharmony_ci { 277e5c31af7Sopenharmony_ci was_line_segment_found = true; 278e5c31af7Sopenharmony_ci 279e5c31af7Sopenharmony_ci break; 280e5c31af7Sopenharmony_ci } 281e5c31af7Sopenharmony_ci } /* for (all found Ys) */ 282e5c31af7Sopenharmony_ci 283e5c31af7Sopenharmony_ci if (!was_line_segment_found) 284e5c31af7Sopenharmony_ci { 285e5c31af7Sopenharmony_ci found_line_segments.push_back(_line_segment(vertex1_x, vertex2_x)); 286e5c31af7Sopenharmony_ci } 287e5c31af7Sopenharmony_ci } /* for (all vertices) */ 288e5c31af7Sopenharmony_ci 289e5c31af7Sopenharmony_ci /* Compare the values */ 290e5c31af7Sopenharmony_ci n_unique_line_segments_found = (unsigned int)found_line_segments.size(); 291e5c31af7Sopenharmony_ci 292e5c31af7Sopenharmony_ci if (n_unique_line_segments_found != n_line_segments_per_isoline_expected) 293e5c31af7Sopenharmony_ci { 294e5c31af7Sopenharmony_ci tcu::TestContext& test = test_result.parent->parent->getTestContext(); 295e5c31af7Sopenharmony_ci 296e5c31af7Sopenharmony_ci test.getLog() << tcu::TestLog::Message << "Tessellator generated an invalid amount of unique line segments:" 297e5c31af7Sopenharmony_ci << n_unique_line_segments_found 298e5c31af7Sopenharmony_ci << " instead of the expected amount:" << n_line_segments_per_isoline_expected 299e5c31af7Sopenharmony_ci << " for the following inner tessellation level configuration:" 300e5c31af7Sopenharmony_ci << " (" << test_result.parent->inner_tess_levels[0] << ", " 301e5c31af7Sopenharmony_ci << test_result.parent->inner_tess_levels[1] << ")" 302e5c31af7Sopenharmony_ci << " and the following outer tesellation level configuration:" 303e5c31af7Sopenharmony_ci << " (" << test_result.parent->outer_tess_levels[0] << ", " 304e5c31af7Sopenharmony_ci << test_result.parent->outer_tess_levels[1] << ", " 305e5c31af7Sopenharmony_ci << test_result.parent->outer_tess_levels[2] << ", " 306e5c31af7Sopenharmony_ci << test_result.parent->outer_tess_levels[3] << ")" 307e5c31af7Sopenharmony_ci << " and the following vertex spacing mode: " << test_result.parent->vertex_spacing_mode 308e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 309e5c31af7Sopenharmony_ci 310e5c31af7Sopenharmony_ci TCU_FAIL("Invalid amount of unique line segments generated by tessellator"); 311e5c31af7Sopenharmony_ci } 312e5c31af7Sopenharmony_ci } /* if (test_run.n_vertices != 0) */ 313e5c31af7Sopenharmony_ci} 314e5c31af7Sopenharmony_ci 315e5c31af7Sopenharmony_ci/** Verifies that no vertex making up any of the line segments outputted by the 316e5c31af7Sopenharmony_ci * tessellator is located at height equal to -1. 317e5c31af7Sopenharmony_ci * 318e5c31af7Sopenharmony_ci * This check needs not to operate over all test results generated for a particular 319e5c31af7Sopenharmony_ci * vertex spacing mode. 320e5c31af7Sopenharmony_ci * 321e5c31af7Sopenharmony_ci * This function throws a TestError exception if the check fails. 322e5c31af7Sopenharmony_ci * 323e5c31af7Sopenharmony_ci * @param test_result Test result descriptor to perform the check on. 324e5c31af7Sopenharmony_ci * 325e5c31af7Sopenharmony_ci **/ 326e5c31af7Sopenharmony_civoid TessellationShadersIsolines::checkNoLineSegmentIsDefinedAtHeightOne(_test_result& test_result, glw::GLenum unused) 327e5c31af7Sopenharmony_ci{ 328e5c31af7Sopenharmony_ci (void)unused; // suppress warning 329e5c31af7Sopenharmony_ci 330e5c31af7Sopenharmony_ci const float epsilon = 1e-5f; 331e5c31af7Sopenharmony_ci 332e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < test_result.n_vertices; ++n_vertex) 333e5c31af7Sopenharmony_ci { 334e5c31af7Sopenharmony_ci const float* vertex = (&test_result.rendered_data[0]) + n_vertex * 3; /* components */ 335e5c31af7Sopenharmony_ci 336e5c31af7Sopenharmony_ci if (de::abs(vertex[1] - 1.0f) < epsilon) 337e5c31af7Sopenharmony_ci { 338e5c31af7Sopenharmony_ci tcu::TestContext& test = test_result.parent->parent->getTestContext(); 339e5c31af7Sopenharmony_ci 340e5c31af7Sopenharmony_ci test.getLog() << tcu::TestLog::Message << "Tessellator generated the following coordinate:" 341e5c31af7Sopenharmony_ci << " (" << vertex[0] << ", " << vertex[1] << ", " << vertex[2] << ")" 342e5c31af7Sopenharmony_ci << " for the following inner tessellation level configuration:" 343e5c31af7Sopenharmony_ci << " (" << test_result.parent->inner_tess_levels[0] << ", " 344e5c31af7Sopenharmony_ci << test_result.parent->inner_tess_levels[1] << ")" 345e5c31af7Sopenharmony_ci << " and the following outer tesellation level configuration:" 346e5c31af7Sopenharmony_ci << " (" << test_result.parent->outer_tess_levels[0] << ", " 347e5c31af7Sopenharmony_ci << test_result.parent->outer_tess_levels[1] << ", " 348e5c31af7Sopenharmony_ci << test_result.parent->outer_tess_levels[2] << ", " 349e5c31af7Sopenharmony_ci << test_result.parent->outer_tess_levels[3] << ")" 350e5c31af7Sopenharmony_ci << " which is invalid: Y must never be equal to 1." << tcu::TestLog::EndMessage; 351e5c31af7Sopenharmony_ci 352e5c31af7Sopenharmony_ci TCU_FAIL("Invalid line segment generated by tessellator"); 353e5c31af7Sopenharmony_ci } /* If the Y coordinate is set at 1 */ 354e5c31af7Sopenharmony_ci } /* for (all vertices) */ 355e5c31af7Sopenharmony_ci} 356e5c31af7Sopenharmony_ci 357e5c31af7Sopenharmony_ci/** Verifies that amount of isolines generated for the same inner+outer level 358e5c31af7Sopenharmony_ci * configurations but for different vertex spacing modes is exactly the same. 359e5c31af7Sopenharmony_ci * 360e5c31af7Sopenharmony_ci * This check needs to operate over all test results generated for a particular 361e5c31af7Sopenharmony_ci * vertex spacing mode. 362e5c31af7Sopenharmony_ci * 363e5c31af7Sopenharmony_ci * This function throws a TestError exception if the check fails. 364e5c31af7Sopenharmony_ci * 365e5c31af7Sopenharmony_ci **/ 366e5c31af7Sopenharmony_civoid TessellationShadersIsolines::checkVertexSpacingDoesNotAffectAmountOfGeneratedIsolines() 367e5c31af7Sopenharmony_ci{ 368e5c31af7Sopenharmony_ci DE_ASSERT(m_tests.find(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL) != m_tests.end()); 369e5c31af7Sopenharmony_ci 370e5c31af7Sopenharmony_ci _test_results_iterator test_result_iterator_start = 371e5c31af7Sopenharmony_ci m_test_results[TESSELLATION_SHADER_VERTEX_SPACING_EQUAL].begin(); 372e5c31af7Sopenharmony_ci _test_results_iterator test_result_iterator_end = m_test_results[TESSELLATION_SHADER_VERTEX_SPACING_EQUAL].end(); 373e5c31af7Sopenharmony_ci 374e5c31af7Sopenharmony_ci for (_test_results_iterator test_result_iterator = test_result_iterator_start; 375e5c31af7Sopenharmony_ci test_result_iterator != test_result_iterator_end; test_result_iterator++) 376e5c31af7Sopenharmony_ci { 377e5c31af7Sopenharmony_ci _test_result& test_result_equal = *test_result_iterator; 378e5c31af7Sopenharmony_ci _test_result test_result_fe; 379e5c31af7Sopenharmony_ci _test_result test_result_fo; 380e5c31af7Sopenharmony_ci 381e5c31af7Sopenharmony_ci /* Find a corresponding fractional_even test run descriptor */ 382e5c31af7Sopenharmony_ci test_result_fe = 383e5c31af7Sopenharmony_ci findTestResult(test_result_equal.irrelevant_tess_level, test_result_equal.outer1_tess_level, 384e5c31af7Sopenharmony_ci test_result_equal.outer2_tess_level, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN); 385e5c31af7Sopenharmony_ci test_result_fo = 386e5c31af7Sopenharmony_ci findTestResult(test_result_equal.irrelevant_tess_level, test_result_equal.outer1_tess_level, 387e5c31af7Sopenharmony_ci test_result_equal.outer2_tess_level, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD); 388e5c31af7Sopenharmony_ci 389e5c31af7Sopenharmony_ci /* Make sure the amounts match */ 390e5c31af7Sopenharmony_ci if (test_result_equal.n_isolines != test_result_fe.n_isolines || 391e5c31af7Sopenharmony_ci test_result_fe.n_isolines != test_result_fo.n_isolines) 392e5c31af7Sopenharmony_ci { 393e5c31af7Sopenharmony_ci tcu::TestContext& test = test_result_iterator->parent->parent->getTestContext(); 394e5c31af7Sopenharmony_ci 395e5c31af7Sopenharmony_ci test.getLog() << tcu::TestLog::Message << "Tessellator generated different amount of isolines for EQUAL/" 396e5c31af7Sopenharmony_ci "FRACTIONAL_EVEN/FRACTIONAL_ODD vertex spacing modes which is " 397e5c31af7Sopenharmony_ci "invalid." 398e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 399e5c31af7Sopenharmony_ci 400e5c31af7Sopenharmony_ci TCU_FAIL("Invalid amount of unique isolines generated by tessellator"); 401e5c31af7Sopenharmony_ci } /* if (amount of generated isolines does not match) */ 402e5c31af7Sopenharmony_ci } /* for (all test runs) */ 403e5c31af7Sopenharmony_ci} 404e5c31af7Sopenharmony_ci 405e5c31af7Sopenharmony_ci/** Counts amount of unique isolines in the captured data set and updates 406e5c31af7Sopenharmony_ci * n_isolines field of user-provided @param test_result instance. 407e5c31af7Sopenharmony_ci * 408e5c31af7Sopenharmony_ci * @param test_result Test result instance to update. 409e5c31af7Sopenharmony_ci */ 410e5c31af7Sopenharmony_civoid TessellationShadersIsolines::countIsolines(_test_result& test_result) 411e5c31af7Sopenharmony_ci{ 412e5c31af7Sopenharmony_ci const float epsilon = 1e-5f; 413e5c31af7Sopenharmony_ci std::vector<float> found_ys; 414e5c31af7Sopenharmony_ci 415e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < test_result.n_vertices; ++n_vertex) 416e5c31af7Sopenharmony_ci { 417e5c31af7Sopenharmony_ci bool was_y_found = false; 418e5c31af7Sopenharmony_ci const float* vertex = (&test_result.rendered_data[0]) + n_vertex * 3; /* components */ 419e5c31af7Sopenharmony_ci float vertex_y = vertex[1]; 420e5c31af7Sopenharmony_ci 421e5c31af7Sopenharmony_ci for (std::vector<float>::iterator found_ys_iterator = found_ys.begin(); found_ys_iterator != found_ys.end(); 422e5c31af7Sopenharmony_ci found_ys_iterator++) 423e5c31af7Sopenharmony_ci { 424e5c31af7Sopenharmony_ci float& found_y = *found_ys_iterator; 425e5c31af7Sopenharmony_ci 426e5c31af7Sopenharmony_ci if (de::abs(vertex_y - found_y) < epsilon) 427e5c31af7Sopenharmony_ci { 428e5c31af7Sopenharmony_ci was_y_found = true; 429e5c31af7Sopenharmony_ci 430e5c31af7Sopenharmony_ci break; 431e5c31af7Sopenharmony_ci } 432e5c31af7Sopenharmony_ci } /* for (all found Ys) */ 433e5c31af7Sopenharmony_ci 434e5c31af7Sopenharmony_ci if (!was_y_found) 435e5c31af7Sopenharmony_ci { 436e5c31af7Sopenharmony_ci found_ys.push_back(vertex_y); 437e5c31af7Sopenharmony_ci } 438e5c31af7Sopenharmony_ci } /* for (all vertices) */ 439e5c31af7Sopenharmony_ci 440e5c31af7Sopenharmony_ci /* Store the value */ 441e5c31af7Sopenharmony_ci test_result.n_isolines = (unsigned int)found_ys.size(); 442e5c31af7Sopenharmony_ci} 443e5c31af7Sopenharmony_ci 444e5c31af7Sopenharmony_ci/** Deinitializes ES objects created for the test. */ 445e5c31af7Sopenharmony_civoid TessellationShadersIsolines::deinit() 446e5c31af7Sopenharmony_ci{ 447e5c31af7Sopenharmony_ci /* Call base class' deinit() */ 448e5c31af7Sopenharmony_ci TestCaseBase::deinit(); 449e5c31af7Sopenharmony_ci 450e5c31af7Sopenharmony_ci if (!m_is_tessellation_shader_supported) 451e5c31af7Sopenharmony_ci { 452e5c31af7Sopenharmony_ci return; 453e5c31af7Sopenharmony_ci } 454e5c31af7Sopenharmony_ci 455e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 456e5c31af7Sopenharmony_ci 457e5c31af7Sopenharmony_ci /* Reset GL_PATCH_VERTICES_EXT to default value */ 458e5c31af7Sopenharmony_ci gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 459e5c31af7Sopenharmony_ci 460e5c31af7Sopenharmony_ci /* Disable GL_RASTERIZER_DISCARD mode */ 461e5c31af7Sopenharmony_ci gl.disable(GL_RASTERIZER_DISCARD); 462e5c31af7Sopenharmony_ci 463e5c31af7Sopenharmony_ci /* Unbind vertex array object */ 464e5c31af7Sopenharmony_ci gl.bindVertexArray(0); 465e5c31af7Sopenharmony_ci 466e5c31af7Sopenharmony_ci /* Release Utilities instance */ 467e5c31af7Sopenharmony_ci if (m_utils_ptr != NULL) 468e5c31af7Sopenharmony_ci { 469e5c31af7Sopenharmony_ci delete m_utils_ptr; 470e5c31af7Sopenharmony_ci 471e5c31af7Sopenharmony_ci m_utils_ptr = DE_NULL; 472e5c31af7Sopenharmony_ci } 473e5c31af7Sopenharmony_ci 474e5c31af7Sopenharmony_ci if (m_vao_id != 0) 475e5c31af7Sopenharmony_ci { 476e5c31af7Sopenharmony_ci gl.deleteVertexArrays(1, &m_vao_id); 477e5c31af7Sopenharmony_ci 478e5c31af7Sopenharmony_ci m_vao_id = 0; 479e5c31af7Sopenharmony_ci } 480e5c31af7Sopenharmony_ci 481e5c31af7Sopenharmony_ci /* Free the data structures we allocated for the test */ 482e5c31af7Sopenharmony_ci m_tests.clear(); 483e5c31af7Sopenharmony_ci} 484e5c31af7Sopenharmony_ci 485e5c31af7Sopenharmony_ci/** Retrieves test result structure for a particular set of properties. 486e5c31af7Sopenharmony_ci * 487e5c31af7Sopenharmony_ci * @param irrelevant_tess_level Irrelevant tessellation level the test result descriptor should be using. 488e5c31af7Sopenharmony_ci * @param outer1_tess_level First outer tessellation level value the test result descriptor should be using. 489e5c31af7Sopenharmony_ci * @param outer2_tess_level Second outer tessellation level value the test result descriptor should be using. 490e5c31af7Sopenharmony_ci * @param vertex_spacing_mode Vertex spacing mode the test result descriptor should be using. 491e5c31af7Sopenharmony_ci * 492e5c31af7Sopenharmony_ci * This function throws a TestError exception if the test result descriptor the caller is after is not found. 493e5c31af7Sopenharmony_ci * 494e5c31af7Sopenharmony_ci * @return Test result descriptor of interest. 495e5c31af7Sopenharmony_ci **/ 496e5c31af7Sopenharmony_ciTessellationShadersIsolines::_test_result TessellationShadersIsolines::findTestResult( 497e5c31af7Sopenharmony_ci _irrelevant_tess_level irrelevant_tess_level, _outer1_tess_level outer1_tess_level, 498e5c31af7Sopenharmony_ci _outer2_tess_level outer2_tess_level, _tessellation_shader_vertex_spacing vertex_spacing_mode) 499e5c31af7Sopenharmony_ci{ 500e5c31af7Sopenharmony_ci DE_ASSERT(m_tests.find(vertex_spacing_mode) != m_tests.end()); 501e5c31af7Sopenharmony_ci 502e5c31af7Sopenharmony_ci _test_results& test_results = m_test_results[vertex_spacing_mode]; 503e5c31af7Sopenharmony_ci bool has_found = false; 504e5c31af7Sopenharmony_ci TessellationShadersIsolines::_test_result result; 505e5c31af7Sopenharmony_ci 506e5c31af7Sopenharmony_ci for (_test_results_iterator test_results_iterator = test_results.begin(); 507e5c31af7Sopenharmony_ci test_results_iterator != test_results.end(); test_results_iterator++) 508e5c31af7Sopenharmony_ci { 509e5c31af7Sopenharmony_ci if (test_results_iterator->irrelevant_tess_level == irrelevant_tess_level && 510e5c31af7Sopenharmony_ci test_results_iterator->outer1_tess_level == outer1_tess_level && 511e5c31af7Sopenharmony_ci test_results_iterator->outer2_tess_level == outer2_tess_level) 512e5c31af7Sopenharmony_ci { 513e5c31af7Sopenharmony_ci has_found = true; 514e5c31af7Sopenharmony_ci result = *test_results_iterator; 515e5c31af7Sopenharmony_ci 516e5c31af7Sopenharmony_ci break; 517e5c31af7Sopenharmony_ci } 518e5c31af7Sopenharmony_ci } /* for (all test runs) */ 519e5c31af7Sopenharmony_ci 520e5c31af7Sopenharmony_ci if (!has_found) 521e5c31af7Sopenharmony_ci { 522e5c31af7Sopenharmony_ci TCU_FAIL("Requested test run was not found."); 523e5c31af7Sopenharmony_ci } 524e5c31af7Sopenharmony_ci 525e5c31af7Sopenharmony_ci return result; 526e5c31af7Sopenharmony_ci} 527e5c31af7Sopenharmony_ci 528e5c31af7Sopenharmony_ci/** Retrieves rendering context associated with the test instance. 529e5c31af7Sopenharmony_ci * 530e5c31af7Sopenharmony_ci * @return Rendering context. 531e5c31af7Sopenharmony_ci * 532e5c31af7Sopenharmony_ci **/ 533e5c31af7Sopenharmony_ciContext& TessellationShadersIsolines::getContext() 534e5c31af7Sopenharmony_ci{ 535e5c31af7Sopenharmony_ci return m_context; 536e5c31af7Sopenharmony_ci} 537e5c31af7Sopenharmony_ci 538e5c31af7Sopenharmony_ci/** Initializes ES objects necessary to run the test. */ 539e5c31af7Sopenharmony_civoid TessellationShadersIsolines::initTest() 540e5c31af7Sopenharmony_ci{ 541e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 542e5c31af7Sopenharmony_ci 543e5c31af7Sopenharmony_ci /* Skip if required extensions are not supported. */ 544e5c31af7Sopenharmony_ci if (!m_is_tessellation_shader_supported) 545e5c31af7Sopenharmony_ci { 546e5c31af7Sopenharmony_ci throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 547e5c31af7Sopenharmony_ci } 548e5c31af7Sopenharmony_ci 549e5c31af7Sopenharmony_ci /* Generate Utilities instance */ 550e5c31af7Sopenharmony_ci m_utils_ptr = new TessellationShaderUtils(gl, this); 551e5c31af7Sopenharmony_ci 552e5c31af7Sopenharmony_ci /* Set up vertex array object */ 553e5c31af7Sopenharmony_ci gl.genVertexArrays(1, &m_vao_id); 554e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 555e5c31af7Sopenharmony_ci 556e5c31af7Sopenharmony_ci gl.bindVertexArray(m_vao_id); 557e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 558e5c31af7Sopenharmony_ci 559e5c31af7Sopenharmony_ci /* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */ 560e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_gen_level_value = 0; 561e5c31af7Sopenharmony_ci 562e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value); 563e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 564e5c31af7Sopenharmony_ci 565e5c31af7Sopenharmony_ci /* Initialize reference tessellation values */ 566e5c31af7Sopenharmony_ci const glw::GLfloat tess_levels[] = { -1.0f, 4.0f, float(gl_max_tess_gen_level_value) * 0.5f, 567e5c31af7Sopenharmony_ci float(gl_max_tess_gen_level_value) }; 568e5c31af7Sopenharmony_ci const unsigned int n_tess_levels = sizeof(tess_levels) / sizeof(tess_levels[0]); 569e5c31af7Sopenharmony_ci 570e5c31af7Sopenharmony_ci m_irrelevant_tess_value_1 = tess_levels[0]; 571e5c31af7Sopenharmony_ci m_irrelevant_tess_value_2 = tess_levels[1]; 572e5c31af7Sopenharmony_ci 573e5c31af7Sopenharmony_ci /* Initialize all test passes. 574e5c31af7Sopenharmony_ci * 575e5c31af7Sopenharmony_ci * Make sure each relevant outer tessellation level iterates through values 576e5c31af7Sopenharmony_ci * of our interest 577e5c31af7Sopenharmony_ci */ 578e5c31af7Sopenharmony_ci for (unsigned int outer1_tess_level_index = 0; outer1_tess_level_index < n_tess_levels; ++outer1_tess_level_index) 579e5c31af7Sopenharmony_ci { 580e5c31af7Sopenharmony_ci for (unsigned int outer2_tess_level_index = 0; outer2_tess_level_index < n_tess_levels; 581e5c31af7Sopenharmony_ci ++outer2_tess_level_index) 582e5c31af7Sopenharmony_ci { 583e5c31af7Sopenharmony_ci /* To make the test execute in a reasonable time frame, just use 584e5c31af7Sopenharmony_ci * two different levels for the outer tessellation levels */ 585e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(n_tess_levels >= 2); 586e5c31af7Sopenharmony_ci 587e5c31af7Sopenharmony_ci for (unsigned int other_tess_level_index = 0; other_tess_level_index < 2 /* see comment */; 588e5c31af7Sopenharmony_ci ++other_tess_level_index) 589e5c31af7Sopenharmony_ci { 590e5c31af7Sopenharmony_ci float inner_tess_levels[2] = { tess_levels[other_tess_level_index], 591e5c31af7Sopenharmony_ci tess_levels[other_tess_level_index] }; 592e5c31af7Sopenharmony_ci float outer_tess_levels[4] = { tess_levels[outer1_tess_level_index], 593e5c31af7Sopenharmony_ci tess_levels[outer2_tess_level_index], 594e5c31af7Sopenharmony_ci tess_levels[other_tess_level_index], 595e5c31af7Sopenharmony_ci tess_levels[other_tess_level_index] }; 596e5c31af7Sopenharmony_ci 597e5c31af7Sopenharmony_ci /* Finally, iterate over three vertex spacing modes */ 598e5c31af7Sopenharmony_ci _tessellation_shader_vertex_spacing vertex_spacing_mode; 599e5c31af7Sopenharmony_ci 600e5c31af7Sopenharmony_ci const _tessellation_shader_vertex_spacing vs_modes[] = { 601e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN, 602e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD 603e5c31af7Sopenharmony_ci }; 604e5c31af7Sopenharmony_ci const int n_vs_modes = sizeof(vs_modes) / sizeof(vs_modes[0]); 605e5c31af7Sopenharmony_ci 606e5c31af7Sopenharmony_ci for (int n_vs_mode = 0; n_vs_mode < n_vs_modes; ++n_vs_mode) 607e5c31af7Sopenharmony_ci { 608e5c31af7Sopenharmony_ci vertex_spacing_mode = vs_modes[n_vs_mode]; 609e5c31af7Sopenharmony_ci 610e5c31af7Sopenharmony_ci _test_descriptor test; 611e5c31af7Sopenharmony_ci 612e5c31af7Sopenharmony_ci initTestDescriptor(vertex_spacing_mode, inner_tess_levels, outer_tess_levels, 613e5c31af7Sopenharmony_ci tess_levels[other_tess_level_index], test); 614e5c31af7Sopenharmony_ci 615e5c31af7Sopenharmony_ci m_tests[vertex_spacing_mode].push_back(test); 616e5c31af7Sopenharmony_ci } /* for (all available vertex spacing modes) */ 617e5c31af7Sopenharmony_ci } /* for (all irrelevant tessellation levels) */ 618e5c31af7Sopenharmony_ci } /* for (all defined second outer tessellation levels) */ 619e5c31af7Sopenharmony_ci } /* for (all defined first outer tessellation levels) */ 620e5c31af7Sopenharmony_ci} 621e5c31af7Sopenharmony_ci 622e5c31af7Sopenharmony_ci/** Initializes all ES objects necessary to run a specific test pass. 623e5c31af7Sopenharmony_ci * 624e5c31af7Sopenharmony_ci * @param vertex_spacing Vertex spacing mode to initialize the test descriptor with. 625e5c31af7Sopenharmony_ci * @param inner_tess_levels Two FP values defining subsequent inner tessellation levels 626e5c31af7Sopenharmony_ci * to be used for initializing the test descriptor. Must NOT be 627e5c31af7Sopenharmony_ci * NULL. 628e5c31af7Sopenharmony_ci * @param outer_tess_levels Four FP values defining subsequent outer tessellation levels 629e5c31af7Sopenharmony_ci * to be used for initializing the test descriptor. Must NOT be 630e5c31af7Sopenharmony_ci * NULL. 631e5c31af7Sopenharmony_ci * @param irrelevant_tess_level Value to be used to set irrelevant tessellation level values. 632e5c31af7Sopenharmony_ci * @param test Test descriptor to fill with IDs of initialized objects. 633e5c31af7Sopenharmony_ci **/ 634e5c31af7Sopenharmony_civoid TessellationShadersIsolines::initTestDescriptor(_tessellation_shader_vertex_spacing vertex_spacing, 635e5c31af7Sopenharmony_ci const float* inner_tess_levels, const float* outer_tess_levels, 636e5c31af7Sopenharmony_ci float irrelevant_tess_level, _test_descriptor& test) 637e5c31af7Sopenharmony_ci{ 638e5c31af7Sopenharmony_ci memcpy(test.inner_tess_levels, inner_tess_levels, sizeof(test.inner_tess_levels)); 639e5c31af7Sopenharmony_ci memcpy(test.outer_tess_levels, outer_tess_levels, sizeof(test.outer_tess_levels)); 640e5c31af7Sopenharmony_ci 641e5c31af7Sopenharmony_ci test.parent = this; 642e5c31af7Sopenharmony_ci test.irrelevant_tess_level = irrelevant_tess_level; 643e5c31af7Sopenharmony_ci test.vertex_spacing_mode = vertex_spacing; 644e5c31af7Sopenharmony_ci} 645e5c31af7Sopenharmony_ci 646e5c31af7Sopenharmony_ci/** Executes the test. 647e5c31af7Sopenharmony_ci * 648e5c31af7Sopenharmony_ci * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 649e5c31af7Sopenharmony_ci * 650e5c31af7Sopenharmony_ci * Note the function throws exception should an error occur! 651e5c31af7Sopenharmony_ci * 652e5c31af7Sopenharmony_ci * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 653e5c31af7Sopenharmony_ci **/ 654e5c31af7Sopenharmony_citcu::TestNode::IterateResult TessellationShadersIsolines::iterate(void) 655e5c31af7Sopenharmony_ci{ 656e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 657e5c31af7Sopenharmony_ci 658e5c31af7Sopenharmony_ci initTest(); 659e5c31af7Sopenharmony_ci 660e5c31af7Sopenharmony_ci /* We only need to use one vertex per so go for it */ 661e5c31af7Sopenharmony_ci gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1); 662e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname"); 663e5c31af7Sopenharmony_ci 664e5c31af7Sopenharmony_ci /* We don't need to rasterize anything in this test */ 665e5c31af7Sopenharmony_ci gl.enable(GL_RASTERIZER_DISCARD); 666e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed"); 667e5c31af7Sopenharmony_ci 668e5c31af7Sopenharmony_ci /* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value before we continue */ 669e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_gen_level_value = 0; 670e5c31af7Sopenharmony_ci 671e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value); 672e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname."); 673e5c31af7Sopenharmony_ci 674e5c31af7Sopenharmony_ci /* To perform actual tests, we need to first retrieve the tessellated coordinates data. 675e5c31af7Sopenharmony_ci * Run all tests configured and fill per-test buffer with the information. 676e5c31af7Sopenharmony_ci **/ 677e5c31af7Sopenharmony_ci for (_tests_per_vertex_spacing_map_iterator vs_key_iterator = m_tests.begin(); vs_key_iterator != m_tests.end(); 678e5c31af7Sopenharmony_ci vs_key_iterator++) 679e5c31af7Sopenharmony_ci { 680e5c31af7Sopenharmony_ci for (_tests_const_iterator test_iterator = vs_key_iterator->second.begin(); 681e5c31af7Sopenharmony_ci test_iterator != vs_key_iterator->second.end(); test_iterator++) 682e5c31af7Sopenharmony_ci { 683e5c31af7Sopenharmony_ci const _test_descriptor& test = *test_iterator; 684e5c31af7Sopenharmony_ci 685e5c31af7Sopenharmony_ci /* Capture tessellation data for considered configuration */ 686e5c31af7Sopenharmony_ci unsigned int n_rendered_vertices = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator( 687e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES, test.inner_tess_levels, test.outer_tess_levels, 688e5c31af7Sopenharmony_ci test.vertex_spacing_mode, false); /* is_point_mode_enabled */ 689e5c31af7Sopenharmony_ci std::vector<char> rendered_data = m_utils_ptr->getDataGeneratedByTessellator( 690e5c31af7Sopenharmony_ci test.inner_tess_levels, false, /* point mode */ 691e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES, TESSELLATION_SHADER_VERTEX_ORDERING_CCW, 692e5c31af7Sopenharmony_ci test.vertex_spacing_mode, test.outer_tess_levels); 693e5c31af7Sopenharmony_ci 694e5c31af7Sopenharmony_ci /* Store the data in a test result descriptor */ 695e5c31af7Sopenharmony_ci _test_result result; 696e5c31af7Sopenharmony_ci 697e5c31af7Sopenharmony_ci result.n_vertices = n_rendered_vertices; 698e5c31af7Sopenharmony_ci result.parent = &test; 699e5c31af7Sopenharmony_ci result.irrelevant_tess_level = (int)test.irrelevant_tess_level; 700e5c31af7Sopenharmony_ci result.outer1_tess_level = (int)test.outer_tess_levels[0]; 701e5c31af7Sopenharmony_ci result.outer2_tess_level = (int)test.outer_tess_levels[1]; 702e5c31af7Sopenharmony_ci result.rendered_data.resize(rendered_data.size() / sizeof(float)); 703e5c31af7Sopenharmony_ci if (0 != rendered_data.size()) 704e5c31af7Sopenharmony_ci { 705e5c31af7Sopenharmony_ci memcpy(&result.rendered_data[0], &rendered_data[0], rendered_data.size()); 706e5c31af7Sopenharmony_ci } 707e5c31af7Sopenharmony_ci if (result.rendered_data.size() > 0) 708e5c31af7Sopenharmony_ci { 709e5c31af7Sopenharmony_ci countIsolines(result); 710e5c31af7Sopenharmony_ci } 711e5c31af7Sopenharmony_ci 712e5c31af7Sopenharmony_ci /* Store the test run descriptor. */ 713e5c31af7Sopenharmony_ci m_test_results[test.vertex_spacing_mode].push_back(result); 714e5c31af7Sopenharmony_ci } 715e5c31af7Sopenharmony_ci } 716e5c31af7Sopenharmony_ci 717e5c31af7Sopenharmony_ci /* Now we can proceed with actual tests */ 718e5c31af7Sopenharmony_ci /* (test 1): Make sure amount of isolines is determined by first outer tessellation level */ 719e5c31af7Sopenharmony_ci runForAllTestResults(checkFirstOuterTessellationLevelEffect); 720e5c31af7Sopenharmony_ci 721e5c31af7Sopenharmony_ci /* (test 2): Make sure amount of line segments per height is determined by second outer 722e5c31af7Sopenharmony_ci * tessellation level. 723e5c31af7Sopenharmony_ci */ 724e5c31af7Sopenharmony_ci runForAllTestResults(checkSecondOuterTessellationLevelEffect); 725e5c31af7Sopenharmony_ci 726e5c31af7Sopenharmony_ci /* (test 3): Make sure 3rd, 4th outer tessellation levels, as well as all inner tessellation 727e5c31af7Sopenharmony_ci * levels have no impact on the tessellated coordinates */ 728e5c31af7Sopenharmony_ci checkIrrelevantTessellationLevelsHaveNoEffect(); 729e5c31af7Sopenharmony_ci 730e5c31af7Sopenharmony_ci /* (test 4): Make sure no matter what vertex spacing is requested in TC stage, it is always 731e5c31af7Sopenharmony_ci * equal_spacing that is applied. 732e5c31af7Sopenharmony_ci */ 733e5c31af7Sopenharmony_ci checkVertexSpacingDoesNotAffectAmountOfGeneratedIsolines(); 734e5c31af7Sopenharmony_ci 735e5c31af7Sopenharmony_ci /* (test 5): Make sure that no data set features a line segment at height of 1. */ 736e5c31af7Sopenharmony_ci runForAllTestResults(checkNoLineSegmentIsDefinedAtHeightOne); 737e5c31af7Sopenharmony_ci 738e5c31af7Sopenharmony_ci /* All done */ 739e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 740e5c31af7Sopenharmony_ci return STOP; 741e5c31af7Sopenharmony_ci} 742e5c31af7Sopenharmony_ci 743e5c31af7Sopenharmony_ci/** Calls the caller-provided function provided for each test result descriptor 744e5c31af7Sopenharmony_ci * created during pre-computation stage. 745e5c31af7Sopenharmony_ci * 746e5c31af7Sopenharmony_ci * @param pProcessTestRun Function pointer to call. The function will be called 747e5c31af7Sopenharmony_ci * exactly once for each cached test result descriptor. 748e5c31af7Sopenharmony_ci * 749e5c31af7Sopenharmony_ci **/ 750e5c31af7Sopenharmony_civoid TessellationShadersIsolines::runForAllTestResults(PFNTESTRESULTPROCESSORPROC pProcessTestResult) 751e5c31af7Sopenharmony_ci{ 752e5c31af7Sopenharmony_ci for (_test_results_per_vertex_spacing_map_iterator vs_key_iterator = m_test_results.begin(); 753e5c31af7Sopenharmony_ci vs_key_iterator != m_test_results.end(); vs_key_iterator++) 754e5c31af7Sopenharmony_ci { 755e5c31af7Sopenharmony_ci for (_test_results_iterator test_results_iterator = vs_key_iterator->second.begin(); 756e5c31af7Sopenharmony_ci test_results_iterator != vs_key_iterator->second.end(); test_results_iterator++) 757e5c31af7Sopenharmony_ci { 758e5c31af7Sopenharmony_ci _test_result& test_result = *test_results_iterator; 759e5c31af7Sopenharmony_ci 760e5c31af7Sopenharmony_ci pProcessTestResult(test_result, m_glExtTokens.MAX_TESS_GEN_LEVEL); 761e5c31af7Sopenharmony_ci } /* for (all level3 keys) */ 762e5c31af7Sopenharmony_ci } /* for (all vertex spacing modes) */ 763e5c31af7Sopenharmony_ci} 764e5c31af7Sopenharmony_ci 765e5c31af7Sopenharmony_ci} /* namespace glcts */ 766