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 "esextcTessellationShaderInvariance.hpp" 25e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp" 26e5c31af7Sopenharmony_ci#include "gluDefs.hpp" 27e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 28e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 29e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 30e5c31af7Sopenharmony_ci 31e5c31af7Sopenharmony_cinamespace glcts 32e5c31af7Sopenharmony_ci{ 33e5c31af7Sopenharmony_ci 34e5c31af7Sopenharmony_ci/* Defines a single vertex in tessellation space */ 35e5c31af7Sopenharmony_citypedef struct _vertex 36e5c31af7Sopenharmony_ci{ 37e5c31af7Sopenharmony_ci float u; 38e5c31af7Sopenharmony_ci float v; 39e5c31af7Sopenharmony_ci float w; 40e5c31af7Sopenharmony_ci 41e5c31af7Sopenharmony_ci _vertex() 42e5c31af7Sopenharmony_ci { 43e5c31af7Sopenharmony_ci u = 0.0f; 44e5c31af7Sopenharmony_ci v = 0.0f; 45e5c31af7Sopenharmony_ci w = 0.0f; 46e5c31af7Sopenharmony_ci } 47e5c31af7Sopenharmony_ci} _vertex; 48e5c31af7Sopenharmony_ci 49e5c31af7Sopenharmony_ci/** Constructor 50e5c31af7Sopenharmony_ci * 51e5c31af7Sopenharmony_ci * @param context Test context 52e5c31af7Sopenharmony_ci **/ 53e5c31af7Sopenharmony_ciTessellationShaderInvarianceTests::TessellationShaderInvarianceTests(glcts::Context& context, 54e5c31af7Sopenharmony_ci const ExtParameters& extParams) 55e5c31af7Sopenharmony_ci : TestCaseGroupBase(context, extParams, "tessellation_invariance", 56e5c31af7Sopenharmony_ci "Verifies the implementation conforms to invariance rules.") 57e5c31af7Sopenharmony_ci{ 58e5c31af7Sopenharmony_ci /* No implementation needed */ 59e5c31af7Sopenharmony_ci} 60e5c31af7Sopenharmony_ci 61e5c31af7Sopenharmony_ci/** 62e5c31af7Sopenharmony_ci * Initializes test groups for geometry shader tests 63e5c31af7Sopenharmony_ci **/ 64e5c31af7Sopenharmony_civoid TessellationShaderInvarianceTests::init(void) 65e5c31af7Sopenharmony_ci{ 66e5c31af7Sopenharmony_ci addChild(new glcts::TessellationShaderInvarianceRule1Test(m_context, m_extParams)); 67e5c31af7Sopenharmony_ci addChild(new glcts::TessellationShaderInvarianceRule2Test(m_context, m_extParams)); 68e5c31af7Sopenharmony_ci addChild(new glcts::TessellationShaderInvarianceRule3Test(m_context, m_extParams)); 69e5c31af7Sopenharmony_ci addChild(new glcts::TessellationShaderInvarianceRule4Test(m_context, m_extParams)); 70e5c31af7Sopenharmony_ci addChild(new glcts::TessellationShaderInvarianceRule5Test(m_context, m_extParams)); 71e5c31af7Sopenharmony_ci addChild(new glcts::TessellationShaderInvarianceRule6Test(m_context, m_extParams)); 72e5c31af7Sopenharmony_ci addChild(new glcts::TessellationShaderInvarianceRule7Test(m_context, m_extParams)); 73e5c31af7Sopenharmony_ci} 74e5c31af7Sopenharmony_ci 75e5c31af7Sopenharmony_ci/** Constructor 76e5c31af7Sopenharmony_ci * 77e5c31af7Sopenharmony_ci * @param context Test context 78e5c31af7Sopenharmony_ci * @param name Test name 79e5c31af7Sopenharmony_ci * @param description Test description 80e5c31af7Sopenharmony_ci **/ 81e5c31af7Sopenharmony_ciTessellationShaderInvarianceBaseTest::TessellationShaderInvarianceBaseTest(Context& context, 82e5c31af7Sopenharmony_ci const ExtParameters& extParams, 83e5c31af7Sopenharmony_ci const char* name, const char* description) 84e5c31af7Sopenharmony_ci : TestCaseBase(context, extParams, name, description) 85e5c31af7Sopenharmony_ci , m_utils_ptr(DE_NULL) 86e5c31af7Sopenharmony_ci , m_bo_id(0) 87e5c31af7Sopenharmony_ci , m_qo_tfpw_id(0) 88e5c31af7Sopenharmony_ci , m_vao_id(0) 89e5c31af7Sopenharmony_ci{ 90e5c31af7Sopenharmony_ci /* Left blank on purpose */ 91e5c31af7Sopenharmony_ci} 92e5c31af7Sopenharmony_ci 93e5c31af7Sopenharmony_ci/** Deinitializes ES objects created for the test. */ 94e5c31af7Sopenharmony_civoid TessellationShaderInvarianceBaseTest::deinit() 95e5c31af7Sopenharmony_ci{ 96e5c31af7Sopenharmony_ci /* Call base class' deinit() */ 97e5c31af7Sopenharmony_ci TestCaseBase::deinit(); 98e5c31af7Sopenharmony_ci 99e5c31af7Sopenharmony_ci if (!m_is_tessellation_shader_supported) 100e5c31af7Sopenharmony_ci { 101e5c31af7Sopenharmony_ci return; 102e5c31af7Sopenharmony_ci } 103e5c31af7Sopenharmony_ci 104e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 105e5c31af7Sopenharmony_ci 106e5c31af7Sopenharmony_ci /* Revert buffer object bindings */ 107e5c31af7Sopenharmony_ci gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */); 108e5c31af7Sopenharmony_ci gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */); 109e5c31af7Sopenharmony_ci 110e5c31af7Sopenharmony_ci /* Disable GL_RASTERIZER_DISCARD mode */ 111e5c31af7Sopenharmony_ci gl.disable(GL_RASTERIZER_DISCARD); 112e5c31af7Sopenharmony_ci 113e5c31af7Sopenharmony_ci /* Reset GL_PATCH_VERTICES_EXT to default value */ 114e5c31af7Sopenharmony_ci gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 115e5c31af7Sopenharmony_ci 116e5c31af7Sopenharmony_ci /* Unbind vertex array object */ 117e5c31af7Sopenharmony_ci gl.bindVertexArray(0); 118e5c31af7Sopenharmony_ci 119e5c31af7Sopenharmony_ci /* Deinitialize all ES objects that were created for test purposes */ 120e5c31af7Sopenharmony_ci if (m_bo_id != 0) 121e5c31af7Sopenharmony_ci { 122e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_bo_id); 123e5c31af7Sopenharmony_ci 124e5c31af7Sopenharmony_ci m_bo_id = 0; 125e5c31af7Sopenharmony_ci } 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_ci for (_programs_iterator it = m_programs.begin(); it != m_programs.end(); ++it) 128e5c31af7Sopenharmony_ci { 129e5c31af7Sopenharmony_ci _test_program& program = *it; 130e5c31af7Sopenharmony_ci 131e5c31af7Sopenharmony_ci if (program.po_id != 0) 132e5c31af7Sopenharmony_ci { 133e5c31af7Sopenharmony_ci gl.deleteProgram(program.po_id); 134e5c31af7Sopenharmony_ci } 135e5c31af7Sopenharmony_ci } 136e5c31af7Sopenharmony_ci m_programs.clear(); 137e5c31af7Sopenharmony_ci 138e5c31af7Sopenharmony_ci if (m_qo_tfpw_id != 0) 139e5c31af7Sopenharmony_ci { 140e5c31af7Sopenharmony_ci gl.deleteQueries(1, &m_qo_tfpw_id); 141e5c31af7Sopenharmony_ci 142e5c31af7Sopenharmony_ci m_qo_tfpw_id = 0; 143e5c31af7Sopenharmony_ci } 144e5c31af7Sopenharmony_ci 145e5c31af7Sopenharmony_ci if (m_vao_id != 0) 146e5c31af7Sopenharmony_ci { 147e5c31af7Sopenharmony_ci gl.deleteVertexArrays(1, &m_vao_id); 148e5c31af7Sopenharmony_ci 149e5c31af7Sopenharmony_ci m_vao_id = 0; 150e5c31af7Sopenharmony_ci } 151e5c31af7Sopenharmony_ci 152e5c31af7Sopenharmony_ci /* Deinitialize TS utils instance */ 153e5c31af7Sopenharmony_ci if (m_utils_ptr != NULL) 154e5c31af7Sopenharmony_ci { 155e5c31af7Sopenharmony_ci delete m_utils_ptr; 156e5c31af7Sopenharmony_ci 157e5c31af7Sopenharmony_ci m_utils_ptr = NULL; 158e5c31af7Sopenharmony_ci } 159e5c31af7Sopenharmony_ci} 160e5c31af7Sopenharmony_ci 161e5c31af7Sopenharmony_ci/** Executes a single-counted GL_PATCHES_EXT draw call. 162e5c31af7Sopenharmony_ci * 163e5c31af7Sopenharmony_ci * Throws TestError exception if an error occurs. 164e5c31af7Sopenharmony_ci * 165e5c31af7Sopenharmony_ci * @param n_iteration Not used. 166e5c31af7Sopenharmony_ci * 167e5c31af7Sopenharmony_ci **/ 168e5c31af7Sopenharmony_civoid TessellationShaderInvarianceBaseTest::executeDrawCall(unsigned int n_iteration) 169e5c31af7Sopenharmony_ci{ 170e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 171e5c31af7Sopenharmony_ci 172e5c31af7Sopenharmony_ci DE_UNREF(n_iteration); 173e5c31af7Sopenharmony_ci 174e5c31af7Sopenharmony_ci gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, getDrawCallCountArgument()); 175e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed"); 176e5c31af7Sopenharmony_ci} 177e5c31af7Sopenharmony_ci 178e5c31af7Sopenharmony_ci/** Returns a value that should be used for the draw call's "count" argument. 179e5c31af7Sopenharmony_ci * 180e5c31af7Sopenharmony_ci * @param Always 1 181e5c31af7Sopenharmony_ci **/ 182e5c31af7Sopenharmony_ciunsigned int TessellationShaderInvarianceBaseTest::getDrawCallCountArgument() 183e5c31af7Sopenharmony_ci{ 184e5c31af7Sopenharmony_ci return 1; 185e5c31af7Sopenharmony_ci} 186e5c31af7Sopenharmony_ci 187e5c31af7Sopenharmony_ci/** Returns source code for fragment shader stage which does 188e5c31af7Sopenharmony_ci * not do anything. 189e5c31af7Sopenharmony_ci * 190e5c31af7Sopenharmony_ci * @param n_iteration Not used. 191e5c31af7Sopenharmony_ci * 192e5c31af7Sopenharmony_ci * @return Requested string. 193e5c31af7Sopenharmony_ci **/ 194e5c31af7Sopenharmony_cistd::string TessellationShaderInvarianceBaseTest::getFSCode(unsigned int n_iteration) 195e5c31af7Sopenharmony_ci{ 196e5c31af7Sopenharmony_ci DE_UNREF(n_iteration); 197e5c31af7Sopenharmony_ci 198e5c31af7Sopenharmony_ci std::string result = "${VERSION}\n" 199e5c31af7Sopenharmony_ci "\n" 200e5c31af7Sopenharmony_ci "void main()\n" 201e5c31af7Sopenharmony_ci "{\n" 202e5c31af7Sopenharmony_ci "}\n"; 203e5c31af7Sopenharmony_ci 204e5c31af7Sopenharmony_ci return result; 205e5c31af7Sopenharmony_ci} 206e5c31af7Sopenharmony_ci 207e5c31af7Sopenharmony_ci/** Retrieves name of a vec2 uniform that stores inner tesselaton level information, 208e5c31af7Sopenharmony_ci * later assigned to gl_TessLevelInner in tessellation evaluation shader. 209e5c31af7Sopenharmony_ci * 210e5c31af7Sopenharmony_ci * @return Requested name. 211e5c31af7Sopenharmony_ci **/ 212e5c31af7Sopenharmony_ciconst char* TessellationShaderInvarianceBaseTest::getInnerTessLevelUniformName() 213e5c31af7Sopenharmony_ci{ 214e5c31af7Sopenharmony_ci static const char* result = "inner_tess_level"; 215e5c31af7Sopenharmony_ci 216e5c31af7Sopenharmony_ci return result; 217e5c31af7Sopenharmony_ci} 218e5c31af7Sopenharmony_ci 219e5c31af7Sopenharmony_ci/** Retrieves name of a vec4 uniform that stores outer tesselation level information, 220e5c31af7Sopenharmony_ci * later assigned to gl_TessLevelOuter in tessellation evaluation shader. 221e5c31af7Sopenharmony_ci * 222e5c31af7Sopenharmony_ci * @return Requested name. 223e5c31af7Sopenharmony_ci **/ 224e5c31af7Sopenharmony_ciconst char* TessellationShaderInvarianceBaseTest::getOuterTessLevelUniformName() 225e5c31af7Sopenharmony_ci{ 226e5c31af7Sopenharmony_ci static const char* result = "outer_tess_level"; 227e5c31af7Sopenharmony_ci 228e5c31af7Sopenharmony_ci return result; 229e5c31af7Sopenharmony_ci} 230e5c31af7Sopenharmony_ci 231e5c31af7Sopenharmony_ci/** Returns generic tessellation control shader code, which sends 4 output patch 232e5c31af7Sopenharmony_ci * to tessellation evaluation shader stage and uses the very first input patch 233e5c31af7Sopenharmony_ci * vertex only. 234e5c31af7Sopenharmony_ci * 235e5c31af7Sopenharmony_ci * @return Tessellation control source code. 236e5c31af7Sopenharmony_ci */ 237e5c31af7Sopenharmony_cistd::string TessellationShaderInvarianceBaseTest::getTCCode(unsigned int n_iteration) 238e5c31af7Sopenharmony_ci{ 239e5c31af7Sopenharmony_ci DE_UNREF(n_iteration); 240e5c31af7Sopenharmony_ci 241e5c31af7Sopenharmony_ci /* In order to support all three primitive types, our generic tessellation 242e5c31af7Sopenharmony_ci * control shader will pass 4 vertices to TE stage */ 243e5c31af7Sopenharmony_ci return TessellationShaderUtils::getGenericTCCode(4, /* n_patch_vertices */ 244e5c31af7Sopenharmony_ci false); 245e5c31af7Sopenharmony_ci} 246e5c31af7Sopenharmony_ci 247e5c31af7Sopenharmony_ci/** Retrieves XFB properties for the test pass. 248e5c31af7Sopenharmony_ci * 249e5c31af7Sopenharmony_ci * @param n_iteration Not used. 250e5c31af7Sopenharmony_ci * @param out_n_names Deref will be used to store amount of strings @param *out_n_names 251e5c31af7Sopenharmony_ci * offers. 252e5c31af7Sopenharmony_ci * @param out_names Deref will be used to store pointer to an array of strings holding 253e5c31af7Sopenharmony_ci * names of varyings that should be captured via transform feedback. 254e5c31af7Sopenharmony_ci * Must not be NULL. 255e5c31af7Sopenharmony_ci * 256e5c31af7Sopenharmony_ci **/ 257e5c31af7Sopenharmony_civoid TessellationShaderInvarianceBaseTest::getXFBProperties(unsigned int n_iteration, unsigned int* out_n_names, 258e5c31af7Sopenharmony_ci const char*** out_names) 259e5c31af7Sopenharmony_ci{ 260e5c31af7Sopenharmony_ci static const char* names[] = { "result_uvw" }; 261e5c31af7Sopenharmony_ci 262e5c31af7Sopenharmony_ci DE_UNREF(n_iteration); 263e5c31af7Sopenharmony_ci 264e5c31af7Sopenharmony_ci *out_n_names = 1; 265e5c31af7Sopenharmony_ci *out_names = names; 266e5c31af7Sopenharmony_ci} 267e5c31af7Sopenharmony_ci 268e5c31af7Sopenharmony_ci/** Returns vertex shader source code. The shader sets gl_Position to 269e5c31af7Sopenharmony_ci * vec4(1, 2, 3, 0). 270e5c31af7Sopenharmony_ci * 271e5c31af7Sopenharmony_ci * @return Vertex shader source code. 272e5c31af7Sopenharmony_ci **/ 273e5c31af7Sopenharmony_cistd::string TessellationShaderInvarianceBaseTest::getVSCode(unsigned int n_iteration) 274e5c31af7Sopenharmony_ci{ 275e5c31af7Sopenharmony_ci DE_UNREF(n_iteration); 276e5c31af7Sopenharmony_ci 277e5c31af7Sopenharmony_ci std::string result = "${VERSION}\n" 278e5c31af7Sopenharmony_ci "\n" 279e5c31af7Sopenharmony_ci "void main()\n" 280e5c31af7Sopenharmony_ci "{\n" 281e5c31af7Sopenharmony_ci " gl_Position = vec4(1.0, 2.0, 3.0, 0.0);\n" 282e5c31af7Sopenharmony_ci "}\n"; 283e5c31af7Sopenharmony_ci 284e5c31af7Sopenharmony_ci return result; 285e5c31af7Sopenharmony_ci} 286e5c31af7Sopenharmony_ci 287e5c31af7Sopenharmony_ci/** Initializes ES objects required to execute the test. 288e5c31af7Sopenharmony_ci * 289e5c31af7Sopenharmony_ci * Throws TestError exception if an error occurs. 290e5c31af7Sopenharmony_ci * 291e5c31af7Sopenharmony_ci **/ 292e5c31af7Sopenharmony_civoid TessellationShaderInvarianceBaseTest::initTest() 293e5c31af7Sopenharmony_ci{ 294e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 295e5c31af7Sopenharmony_ci glw::GLuint shared_fs_id = 0; 296e5c31af7Sopenharmony_ci glw::GLuint shared_tc_id = 0; 297e5c31af7Sopenharmony_ci glw::GLuint shared_te_id = 0; 298e5c31af7Sopenharmony_ci glw::GLuint shared_vs_id = 0; 299e5c31af7Sopenharmony_ci 300e5c31af7Sopenharmony_ci gl.genVertexArrays(1, &m_vao_id); 301e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 302e5c31af7Sopenharmony_ci 303e5c31af7Sopenharmony_ci gl.bindVertexArray(m_vao_id); 304e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 305e5c31af7Sopenharmony_ci 306e5c31af7Sopenharmony_ci /* Initialize GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query object */ 307e5c31af7Sopenharmony_ci gl.genQueries(1, &m_qo_tfpw_id); 308e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries() call failed"); 309e5c31af7Sopenharmony_ci 310e5c31af7Sopenharmony_ci /* Initialize tessellation shader utils */ 311e5c31af7Sopenharmony_ci m_utils_ptr = new TessellationShaderUtils(gl, this); 312e5c31af7Sopenharmony_ci 313e5c31af7Sopenharmony_ci /* Initialize a buffer object we will use to store XFB data. 314e5c31af7Sopenharmony_ci * Note: we intentionally skip a glBufferData() call here, 315e5c31af7Sopenharmony_ci * the actual buffer storage size is iteration-specific. 316e5c31af7Sopenharmony_ci **/ 317e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_bo_id); 318e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed"); 319e5c31af7Sopenharmony_ci 320e5c31af7Sopenharmony_ci gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id); 321e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed"); 322e5c31af7Sopenharmony_ci 323e5c31af7Sopenharmony_ci gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */ 324e5c31af7Sopenharmony_ci m_bo_id); 325e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed"); 326e5c31af7Sopenharmony_ci 327e5c31af7Sopenharmony_ci /* Iterate through all iterations */ 328e5c31af7Sopenharmony_ci const unsigned int n_iterations = getAmountOfIterations(); 329e5c31af7Sopenharmony_ci m_programs.reserve(n_iterations); 330e5c31af7Sopenharmony_ci 331e5c31af7Sopenharmony_ci const glw::GLenum SHADER_TYPE_FRAGMENT = GL_FRAGMENT_SHADER; 332e5c31af7Sopenharmony_ci const glw::GLenum SHADER_TYPE_TESSELLATION_CONTROL = m_glExtTokens.TESS_CONTROL_SHADER; 333e5c31af7Sopenharmony_ci const glw::GLenum SHADER_TYPE_TESSELLATION_EVALUATION = m_glExtTokens.TESS_EVALUATION_SHADER; 334e5c31af7Sopenharmony_ci const glw::GLenum SHADER_TYPE_VERTEX = GL_VERTEX_SHADER; 335e5c31af7Sopenharmony_ci 336e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < n_iterations; ++n_iteration) 337e5c31af7Sopenharmony_ci { 338e5c31af7Sopenharmony_ci _test_program program; 339e5c31af7Sopenharmony_ci 340e5c31af7Sopenharmony_ci /* Create an iteration-specific program object */ 341e5c31af7Sopenharmony_ci program.po_id = gl.createProgram(); 342e5c31af7Sopenharmony_ci 343e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 344e5c31af7Sopenharmony_ci 345e5c31af7Sopenharmony_ci /* Query the implementation on which shader types should be compiled on 346e5c31af7Sopenharmony_ci * a per-iteration basis, and which can be initialized only once */ 347e5c31af7Sopenharmony_ci static const glw::GLenum shader_types[] = { SHADER_TYPE_FRAGMENT, SHADER_TYPE_TESSELLATION_CONTROL, 348e5c31af7Sopenharmony_ci SHADER_TYPE_TESSELLATION_EVALUATION, SHADER_TYPE_VERTEX }; 349e5c31af7Sopenharmony_ci static const unsigned int n_shader_types = sizeof(shader_types) / sizeof(shader_types[0]); 350e5c31af7Sopenharmony_ci 351e5c31af7Sopenharmony_ci for (unsigned int n_shader_type = 0; n_shader_type < n_shader_types; ++n_shader_type) 352e5c31af7Sopenharmony_ci { 353e5c31af7Sopenharmony_ci std::string shader_body; 354e5c31af7Sopenharmony_ci const char* shader_body_ptr = DE_NULL; 355e5c31af7Sopenharmony_ci glw::GLuint shader_id = 0; 356e5c31af7Sopenharmony_ci glw::GLenum shader_type = shader_types[n_shader_type]; 357e5c31af7Sopenharmony_ci glw::GLenum shader_type_es = (glw::GLenum)shader_type; 358e5c31af7Sopenharmony_ci 359e5c31af7Sopenharmony_ci // Check whether the test should use a separate program objects for each iteration. 360e5c31af7Sopenharmony_ci bool is_shader_iteration_specific = false; 361e5c31af7Sopenharmony_ci if (shader_type == SHADER_TYPE_TESSELLATION_EVALUATION) 362e5c31af7Sopenharmony_ci { 363e5c31af7Sopenharmony_ci is_shader_iteration_specific = true; 364e5c31af7Sopenharmony_ci } 365e5c31af7Sopenharmony_ci else if ((shader_type != SHADER_TYPE_FRAGMENT) && (shader_type != SHADER_TYPE_TESSELLATION_CONTROL) && 366e5c31af7Sopenharmony_ci (shader_type != SHADER_TYPE_VERTEX)) 367e5c31af7Sopenharmony_ci { 368e5c31af7Sopenharmony_ci TCU_FAIL("Unrecognized shader type"); 369e5c31af7Sopenharmony_ci } 370e5c31af7Sopenharmony_ci 371e5c31af7Sopenharmony_ci /* We need to initialize the shader object if: 372e5c31af7Sopenharmony_ci * 373e5c31af7Sopenharmony_ci * - its body differs between iterations; 374e5c31af7Sopenharmony_ci * - its body is shared by all iterations AND this is the first iteration 375e5c31af7Sopenharmony_ci */ 376e5c31af7Sopenharmony_ci bool has_shader_been_generated = false; 377e5c31af7Sopenharmony_ci 378e5c31af7Sopenharmony_ci if ((!is_shader_iteration_specific && n_iteration == 0) || is_shader_iteration_specific) 379e5c31af7Sopenharmony_ci { 380e5c31af7Sopenharmony_ci /* Create the shader object */ 381e5c31af7Sopenharmony_ci has_shader_been_generated = true; 382e5c31af7Sopenharmony_ci shader_id = gl.createShader(shader_type_es); 383e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed"); 384e5c31af7Sopenharmony_ci 385e5c31af7Sopenharmony_ci /* Assign shader body to the object */ 386e5c31af7Sopenharmony_ci if (shader_type == SHADER_TYPE_FRAGMENT) 387e5c31af7Sopenharmony_ci { 388e5c31af7Sopenharmony_ci shader_body = getFSCode(n_iteration); 389e5c31af7Sopenharmony_ci } 390e5c31af7Sopenharmony_ci else if (shader_type == SHADER_TYPE_TESSELLATION_CONTROL) 391e5c31af7Sopenharmony_ci { 392e5c31af7Sopenharmony_ci shader_body = getTCCode(n_iteration); 393e5c31af7Sopenharmony_ci } 394e5c31af7Sopenharmony_ci else if (shader_type == SHADER_TYPE_TESSELLATION_EVALUATION) 395e5c31af7Sopenharmony_ci { 396e5c31af7Sopenharmony_ci shader_body = getTECode(n_iteration); 397e5c31af7Sopenharmony_ci } 398e5c31af7Sopenharmony_ci else if (shader_type == SHADER_TYPE_VERTEX) 399e5c31af7Sopenharmony_ci { 400e5c31af7Sopenharmony_ci shader_body = getVSCode(n_iteration); 401e5c31af7Sopenharmony_ci } 402e5c31af7Sopenharmony_ci else 403e5c31af7Sopenharmony_ci { 404e5c31af7Sopenharmony_ci TCU_FAIL("Unrecognized shader type"); 405e5c31af7Sopenharmony_ci } 406e5c31af7Sopenharmony_ci 407e5c31af7Sopenharmony_ci shader_body_ptr = shader_body.c_str(); 408e5c31af7Sopenharmony_ci 409e5c31af7Sopenharmony_ci shaderSourceSpecialized(shader_id, 1, &shader_body_ptr); 410e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); 411e5c31af7Sopenharmony_ci 412e5c31af7Sopenharmony_ci /* Compile the shader object */ 413e5c31af7Sopenharmony_ci m_utils_ptr->compileShaders(1, /* n_shaders */ 414e5c31af7Sopenharmony_ci &shader_id, true); /* should_succeed */ 415e5c31af7Sopenharmony_ci 416e5c31af7Sopenharmony_ci /* If this is a shader object that will be shared by all iterations, cache it 417e5c31af7Sopenharmony_ci * in a dedicated variable */ 418e5c31af7Sopenharmony_ci if (!is_shader_iteration_specific) 419e5c31af7Sopenharmony_ci { 420e5c31af7Sopenharmony_ci if (shader_type == SHADER_TYPE_FRAGMENT) 421e5c31af7Sopenharmony_ci { 422e5c31af7Sopenharmony_ci shared_fs_id = shader_id; 423e5c31af7Sopenharmony_ci } 424e5c31af7Sopenharmony_ci else if (shader_type == SHADER_TYPE_TESSELLATION_CONTROL) 425e5c31af7Sopenharmony_ci { 426e5c31af7Sopenharmony_ci shared_tc_id = shader_id; 427e5c31af7Sopenharmony_ci } 428e5c31af7Sopenharmony_ci else if (shader_type == SHADER_TYPE_TESSELLATION_EVALUATION) 429e5c31af7Sopenharmony_ci { 430e5c31af7Sopenharmony_ci shared_te_id = shader_id; 431e5c31af7Sopenharmony_ci } 432e5c31af7Sopenharmony_ci else if (shader_type == SHADER_TYPE_VERTEX) 433e5c31af7Sopenharmony_ci { 434e5c31af7Sopenharmony_ci shared_vs_id = shader_id; 435e5c31af7Sopenharmony_ci } 436e5c31af7Sopenharmony_ci else 437e5c31af7Sopenharmony_ci { 438e5c31af7Sopenharmony_ci TCU_FAIL("Unrecognized shader type"); 439e5c31af7Sopenharmony_ci } 440e5c31af7Sopenharmony_ci } /* if (!is_shader_iteration_specific) */ 441e5c31af7Sopenharmony_ci } /* if (shader object needs to be initialized) */ 442e5c31af7Sopenharmony_ci else 443e5c31af7Sopenharmony_ci { 444e5c31af7Sopenharmony_ci shader_id = (shader_type == SHADER_TYPE_FRAGMENT) ? 445e5c31af7Sopenharmony_ci shared_fs_id : 446e5c31af7Sopenharmony_ci (shader_type == SHADER_TYPE_TESSELLATION_CONTROL) ? 447e5c31af7Sopenharmony_ci shared_tc_id : 448e5c31af7Sopenharmony_ci (shader_type == SHADER_TYPE_TESSELLATION_EVALUATION) ? shared_te_id : shared_vs_id; 449e5c31af7Sopenharmony_ci } 450e5c31af7Sopenharmony_ci 451e5c31af7Sopenharmony_ci /* Attach the shader object to iteration-specific program object */ 452e5c31af7Sopenharmony_ci gl.attachShader(program.po_id, shader_id); 453e5c31af7Sopenharmony_ci 454e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); 455e5c31af7Sopenharmony_ci 456e5c31af7Sopenharmony_ci /* Now that the object has been attached, we can flag it for deletion */ 457e5c31af7Sopenharmony_ci if (has_shader_been_generated) 458e5c31af7Sopenharmony_ci { 459e5c31af7Sopenharmony_ci gl.deleteShader(shader_id); 460e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed"); 461e5c31af7Sopenharmony_ci } 462e5c31af7Sopenharmony_ci } /* for (all shader types) */ 463e5c31af7Sopenharmony_ci 464e5c31af7Sopenharmony_ci /* Set up transform feed-back */ 465e5c31af7Sopenharmony_ci unsigned int n_xfb_names = 0; 466e5c31af7Sopenharmony_ci const char** xfb_names = NULL; 467e5c31af7Sopenharmony_ci 468e5c31af7Sopenharmony_ci getXFBProperties(n_iteration, &n_xfb_names, &xfb_names); 469e5c31af7Sopenharmony_ci 470e5c31af7Sopenharmony_ci gl.transformFeedbackVaryings(program.po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS); 471e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed."); 472e5c31af7Sopenharmony_ci 473e5c31af7Sopenharmony_ci /* Try to link the program object */ 474e5c31af7Sopenharmony_ci glw::GLint link_status = GL_FALSE; 475e5c31af7Sopenharmony_ci 476e5c31af7Sopenharmony_ci gl.linkProgram(program.po_id); 477e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed"); 478e5c31af7Sopenharmony_ci 479e5c31af7Sopenharmony_ci gl.getProgramiv(program.po_id, GL_LINK_STATUS, &link_status); 480e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed"); 481e5c31af7Sopenharmony_ci 482e5c31af7Sopenharmony_ci if (link_status != GL_TRUE) 483e5c31af7Sopenharmony_ci { 484e5c31af7Sopenharmony_ci TCU_FAIL("Program linking failed"); 485e5c31af7Sopenharmony_ci } 486e5c31af7Sopenharmony_ci 487e5c31af7Sopenharmony_ci /* Retrieve inner/outer tess level uniform locations */ 488e5c31af7Sopenharmony_ci program.inner_tess_level_uniform_location = 489e5c31af7Sopenharmony_ci gl.getUniformLocation(program.po_id, getInnerTessLevelUniformName()); 490e5c31af7Sopenharmony_ci program.outer_tess_level_uniform_location = 491e5c31af7Sopenharmony_ci gl.getUniformLocation(program.po_id, getOuterTessLevelUniformName()); 492e5c31af7Sopenharmony_ci 493e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed"); 494e5c31af7Sopenharmony_ci 495e5c31af7Sopenharmony_ci /* Store the program object */ 496e5c31af7Sopenharmony_ci m_programs.push_back(program); 497e5c31af7Sopenharmony_ci } /* for (all iterations) */ 498e5c31af7Sopenharmony_ci} 499e5c31af7Sopenharmony_ci 500e5c31af7Sopenharmony_ci/** Executes the test. 501e5c31af7Sopenharmony_ci * 502e5c31af7Sopenharmony_ci * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 503e5c31af7Sopenharmony_ci * 504e5c31af7Sopenharmony_ci * Note the function throws exception should an error occur! 505e5c31af7Sopenharmony_ci * 506e5c31af7Sopenharmony_ci * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 507e5c31af7Sopenharmony_ci **/ 508e5c31af7Sopenharmony_citcu::TestNode::IterateResult TessellationShaderInvarianceBaseTest::iterate(void) 509e5c31af7Sopenharmony_ci{ 510e5c31af7Sopenharmony_ci /* Do not execute if required extensions are not supported. */ 511e5c31af7Sopenharmony_ci if (!m_is_tessellation_shader_supported) 512e5c31af7Sopenharmony_ci { 513e5c31af7Sopenharmony_ci throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 514e5c31af7Sopenharmony_ci } 515e5c31af7Sopenharmony_ci 516e5c31af7Sopenharmony_ci /* Initialize all objects needed to run the test */ 517e5c31af7Sopenharmony_ci initTest(); 518e5c31af7Sopenharmony_ci 519e5c31af7Sopenharmony_ci /* Do a general set-up */ 520e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 521e5c31af7Sopenharmony_ci 522e5c31af7Sopenharmony_ci gl.enable(GL_RASTERIZER_DISCARD); 523e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed."); 524e5c31af7Sopenharmony_ci 525e5c31af7Sopenharmony_ci gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1); 526e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname"); 527e5c31af7Sopenharmony_ci 528e5c31af7Sopenharmony_ci /* There are two types of verification supported by this base test implementation: 529e5c31af7Sopenharmony_ci * 530e5c31af7Sopenharmony_ci * - iteration-specific (verifyResultDataForIteration() ) 531e5c31af7Sopenharmony_ci * - global (verifyResultData() ) 532e5c31af7Sopenharmony_ci * 533e5c31af7Sopenharmony_ci * It is up to test implementation to decide which of the two (or perhaps both) 534e5c31af7Sopenharmony_ci * entry-points it should overload and use for validating the result data. 535e5c31af7Sopenharmony_ci */ 536e5c31af7Sopenharmony_ci const unsigned int n_iterations = getAmountOfIterations(); 537e5c31af7Sopenharmony_ci char** iteration_data = new char*[n_iterations]; 538e5c31af7Sopenharmony_ci 539e5c31af7Sopenharmony_ci /* Execute the test */ 540e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < n_iterations; ++n_iteration) 541e5c31af7Sopenharmony_ci { 542e5c31af7Sopenharmony_ci _test_program& program = m_programs[n_iteration]; 543e5c31af7Sopenharmony_ci 544e5c31af7Sopenharmony_ci /* Retrieve iteration properties for current iteration */ 545e5c31af7Sopenharmony_ci unsigned int bo_size = 0; 546e5c31af7Sopenharmony_ci float inner_tess_levels[2] = { 0 }; 547e5c31af7Sopenharmony_ci bool is_point_mode = false; 548e5c31af7Sopenharmony_ci float outer_tess_levels[4] = { 0 }; 549e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN; 550e5c31af7Sopenharmony_ci _tessellation_shader_vertex_ordering vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_UNKNOWN; 551e5c31af7Sopenharmony_ci 552e5c31af7Sopenharmony_ci getIterationProperties(n_iteration, inner_tess_levels, outer_tess_levels, &is_point_mode, &primitive_mode, 553e5c31af7Sopenharmony_ci &vertex_ordering, &bo_size); 554e5c31af7Sopenharmony_ci 555e5c31af7Sopenharmony_ci DE_ASSERT(bo_size != 0); 556e5c31af7Sopenharmony_ci 557e5c31af7Sopenharmony_ci /* Activate iteration-specific program */ 558e5c31af7Sopenharmony_ci gl.useProgram(program.po_id); 559e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed."); 560e5c31af7Sopenharmony_ci 561e5c31af7Sopenharmony_ci /* Set up buffer object storage */ 562e5c31af7Sopenharmony_ci { 563e5c31af7Sopenharmony_ci char* zero_bo_data = new char[bo_size]; 564e5c31af7Sopenharmony_ci 565e5c31af7Sopenharmony_ci memset(zero_bo_data, 0, bo_size); 566e5c31af7Sopenharmony_ci 567e5c31af7Sopenharmony_ci gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, zero_bo_data, GL_STATIC_DRAW); 568e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed"); 569e5c31af7Sopenharmony_ci 570e5c31af7Sopenharmony_ci delete[] zero_bo_data; 571e5c31af7Sopenharmony_ci zero_bo_data = NULL; 572e5c31af7Sopenharmony_ci } 573e5c31af7Sopenharmony_ci 574e5c31af7Sopenharmony_ci /* Allocate space for iteration-specific data */ 575e5c31af7Sopenharmony_ci iteration_data[n_iteration] = new char[bo_size]; 576e5c31af7Sopenharmony_ci 577e5c31af7Sopenharmony_ci /* Configure inner/outer tessellation levels as requested for the iteration */ 578e5c31af7Sopenharmony_ci gl.uniform2fv(program.inner_tess_level_uniform_location, 1, /* count */ 579e5c31af7Sopenharmony_ci inner_tess_levels); 580e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2fv() call failed"); 581e5c31af7Sopenharmony_ci 582e5c31af7Sopenharmony_ci gl.uniform4fv(program.outer_tess_level_uniform_location, 1, /* count */ 583e5c31af7Sopenharmony_ci outer_tess_levels); 584e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed"); 585e5c31af7Sopenharmony_ci 586e5c31af7Sopenharmony_ci /* Launch the TFPW query */ 587e5c31af7Sopenharmony_ci gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_qo_tfpw_id); 588e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), 589e5c31af7Sopenharmony_ci "glBeginQuery() for GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN target failed."); 590e5c31af7Sopenharmony_ci 591e5c31af7Sopenharmony_ci /* Prepare for TF */ 592e5c31af7Sopenharmony_ci glw::GLenum tf_mode = TessellationShaderUtils::getTFModeForPrimitiveMode(primitive_mode, is_point_mode); 593e5c31af7Sopenharmony_ci 594e5c31af7Sopenharmony_ci gl.beginTransformFeedback(tf_mode); 595e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed"); 596e5c31af7Sopenharmony_ci { 597e5c31af7Sopenharmony_ci /* Execute the draw call */ 598e5c31af7Sopenharmony_ci executeDrawCall(n_iteration); 599e5c31af7Sopenharmony_ci 600e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed"); 601e5c31af7Sopenharmony_ci } 602e5c31af7Sopenharmony_ci gl.endTransformFeedback(); 603e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed"); 604e5c31af7Sopenharmony_ci 605e5c31af7Sopenharmony_ci gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); 606e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) call failed"); 607e5c31af7Sopenharmony_ci 608e5c31af7Sopenharmony_ci /* Make sure that we had sufficient amount of space in a buffer object we used to 609e5c31af7Sopenharmony_ci * capture XFB data. 610e5c31af7Sopenharmony_ci **/ 611e5c31af7Sopenharmony_ci glw::GLuint n_tf_primitives_written = 0; 612e5c31af7Sopenharmony_ci glw::GLuint used_tf_bo_size = 0; 613e5c31af7Sopenharmony_ci 614e5c31af7Sopenharmony_ci gl.getQueryObjectuiv(m_qo_tfpw_id, GL_QUERY_RESULT, &n_tf_primitives_written); 615e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), 616e5c31af7Sopenharmony_ci "Could not retrieve GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query object result"); 617e5c31af7Sopenharmony_ci 618e5c31af7Sopenharmony_ci if (is_point_mode) 619e5c31af7Sopenharmony_ci { 620e5c31af7Sopenharmony_ci used_tf_bo_size = static_cast<glw::GLuint>(n_tf_primitives_written * sizeof(float) * 3 /* components */); 621e5c31af7Sopenharmony_ci } 622e5c31af7Sopenharmony_ci else if (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES) 623e5c31af7Sopenharmony_ci { 624e5c31af7Sopenharmony_ci used_tf_bo_size = static_cast<glw::GLuint>(n_tf_primitives_written * sizeof(float) * 2 /* vertices */ * 625e5c31af7Sopenharmony_ci 3 /* components */); 626e5c31af7Sopenharmony_ci } 627e5c31af7Sopenharmony_ci else 628e5c31af7Sopenharmony_ci { 629e5c31af7Sopenharmony_ci used_tf_bo_size = static_cast<glw::GLuint>(n_tf_primitives_written * sizeof(float) * 3 /* vertices */ * 630e5c31af7Sopenharmony_ci 3 /* components */); 631e5c31af7Sopenharmony_ci } 632e5c31af7Sopenharmony_ci 633e5c31af7Sopenharmony_ci if (used_tf_bo_size != bo_size) 634e5c31af7Sopenharmony_ci { 635e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Expected " << bo_size 636e5c31af7Sopenharmony_ci << " to be filled with tessellation data, " 637e5c31af7Sopenharmony_ci "only " 638e5c31af7Sopenharmony_ci << used_tf_bo_size << "was used." << tcu::TestLog::EndMessage; 639e5c31af7Sopenharmony_ci 640e5c31af7Sopenharmony_ci TCU_FAIL("Amount of primitives generated during TF does not match amount of primitives that were expected" 641e5c31af7Sopenharmony_ci " to be generated by the tessellator"); 642e5c31af7Sopenharmony_ci } 643e5c31af7Sopenharmony_ci 644e5c31af7Sopenharmony_ci /* Map the buffer object we earlier bound to GL_TRANSFORM_FEEDBACK_BUFFER 645e5c31af7Sopenharmony_ci * target into process space. */ 646e5c31af7Sopenharmony_ci const void* xfb_data = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 647e5c31af7Sopenharmony_ci bo_size, GL_MAP_READ_BIT); 648e5c31af7Sopenharmony_ci 649e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed"); 650e5c31af7Sopenharmony_ci 651e5c31af7Sopenharmony_ci memcpy(iteration_data[n_iteration], xfb_data, bo_size); 652e5c31af7Sopenharmony_ci 653e5c31af7Sopenharmony_ci /* Unmap the buffer object */ 654e5c31af7Sopenharmony_ci gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 655e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed"); 656e5c31af7Sopenharmony_ci 657e5c31af7Sopenharmony_ci /* Ask the test implementation to verify the results */ 658e5c31af7Sopenharmony_ci verifyResultDataForIteration(n_iteration, iteration_data[n_iteration]); 659e5c31af7Sopenharmony_ci } /* for (all iterations) */ 660e5c31af7Sopenharmony_ci 661e5c31af7Sopenharmony_ci /* Now that we've executed all iterations, we can call a global verification 662e5c31af7Sopenharmony_ci * entry-point */ 663e5c31af7Sopenharmony_ci verifyResultData((const void**)iteration_data); 664e5c31af7Sopenharmony_ci 665e5c31af7Sopenharmony_ci /* At this point we're safe to release space allocated for data coming from 666e5c31af7Sopenharmony_ci * all the iterations */ 667e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < n_iterations; ++n_iteration) 668e5c31af7Sopenharmony_ci { 669e5c31af7Sopenharmony_ci char* iter_data = (char*)iteration_data[n_iteration]; 670e5c31af7Sopenharmony_ci delete[] iter_data; 671e5c31af7Sopenharmony_ci 672e5c31af7Sopenharmony_ci iteration_data[n_iteration] = DE_NULL; 673e5c31af7Sopenharmony_ci } /* for (all iterations) */ 674e5c31af7Sopenharmony_ci 675e5c31af7Sopenharmony_ci delete[] iteration_data; 676e5c31af7Sopenharmony_ci iteration_data = DE_NULL; 677e5c31af7Sopenharmony_ci 678e5c31af7Sopenharmony_ci /* All done */ 679e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 680e5c31af7Sopenharmony_ci return STOP; 681e5c31af7Sopenharmony_ci} 682e5c31af7Sopenharmony_ci 683e5c31af7Sopenharmony_ci/* Does nothing (stub implementation) 684e5c31af7Sopenharmony_ci * 685e5c31af7Sopenharmony_ci * @param n_iteration Not used. 686e5c31af7Sopenharmony_ci * @param data Not used. 687e5c31af7Sopenharmony_ci * 688e5c31af7Sopenharmony_ci **/ 689e5c31af7Sopenharmony_civoid TessellationShaderInvarianceBaseTest::verifyResultDataForIteration(unsigned int n_iteration, const void* data) 690e5c31af7Sopenharmony_ci{ 691e5c31af7Sopenharmony_ci DE_UNREF(n_iteration && data); 692e5c31af7Sopenharmony_ci 693e5c31af7Sopenharmony_ci /* Do nothing - this is just a stub. */ 694e5c31af7Sopenharmony_ci} 695e5c31af7Sopenharmony_ci 696e5c31af7Sopenharmony_ci/* Does nothing (stub implementation) 697e5c31af7Sopenharmony_ci * 698e5c31af7Sopenharmony_ci * @param all_iterations_data Not used. 699e5c31af7Sopenharmony_ci * 700e5c31af7Sopenharmony_ci **/ 701e5c31af7Sopenharmony_civoid TessellationShaderInvarianceBaseTest::verifyResultData(const void** all_iterations_data) 702e5c31af7Sopenharmony_ci{ 703e5c31af7Sopenharmony_ci DE_UNREF(all_iterations_data); 704e5c31af7Sopenharmony_ci 705e5c31af7Sopenharmony_ci /* Do nothing - this is just a stub. */ 706e5c31af7Sopenharmony_ci} 707e5c31af7Sopenharmony_ci 708e5c31af7Sopenharmony_ci/** Constructor. 709e5c31af7Sopenharmony_ci * 710e5c31af7Sopenharmony_ci * @param context Rendering context. 711e5c31af7Sopenharmony_ci * 712e5c31af7Sopenharmony_ci **/ 713e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule1Test::TessellationShaderInvarianceRule1Test(Context& context, 714e5c31af7Sopenharmony_ci const ExtParameters& extParams) 715e5c31af7Sopenharmony_ci : TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule1", 716e5c31af7Sopenharmony_ci "Verifies conformance with first invariance rule") 717e5c31af7Sopenharmony_ci{ 718e5c31af7Sopenharmony_ci /* Left blank intentionally */ 719e5c31af7Sopenharmony_ci} 720e5c31af7Sopenharmony_ci 721e5c31af7Sopenharmony_ci/** Destructor. */ 722e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule1Test::~TessellationShaderInvarianceRule1Test() 723e5c31af7Sopenharmony_ci{ 724e5c31af7Sopenharmony_ci /* Left blank intentionally */ 725e5c31af7Sopenharmony_ci} 726e5c31af7Sopenharmony_ci 727e5c31af7Sopenharmony_ci/** Retrieves amount of iterations the base test implementation should run before 728e5c31af7Sopenharmony_ci * calling global verification routine. 729e5c31af7Sopenharmony_ci * 730e5c31af7Sopenharmony_ci * @return Always 6. 731e5c31af7Sopenharmony_ci **/ 732e5c31af7Sopenharmony_ciunsigned int TessellationShaderInvarianceRule1Test::getAmountOfIterations() 733e5c31af7Sopenharmony_ci{ 734e5c31af7Sopenharmony_ci return 6; 735e5c31af7Sopenharmony_ci} 736e5c31af7Sopenharmony_ci 737e5c31af7Sopenharmony_ci/** Returns a value that should be used for the draw call's "count" argument. 738e5c31af7Sopenharmony_ci * 739e5c31af7Sopenharmony_ci * @param Always 3 740e5c31af7Sopenharmony_ci **/ 741e5c31af7Sopenharmony_ciunsigned int TessellationShaderInvarianceRule1Test::getDrawCallCountArgument() 742e5c31af7Sopenharmony_ci{ 743e5c31af7Sopenharmony_ci return 3; 744e5c31af7Sopenharmony_ci} 745e5c31af7Sopenharmony_ci 746e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation properties. 747e5c31af7Sopenharmony_ci * 748e5c31af7Sopenharmony_ci * @param n_iteration Iteration index to retrieve the properties for. 749e5c31af7Sopenharmony_ci * @param out_inner_tess_levels Deref will be used to store iteration-specific inner 750e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 751e5c31af7Sopenharmony_ci * @param out_outer_tess_levels Deref will be used to store iteration-specific outer 752e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 753e5c31af7Sopenharmony_ci * @param out_point_mode Deref will be used to store iteration-specific flag 754e5c31af7Sopenharmony_ci * telling whether point mode should be enabled for given pass. 755e5c31af7Sopenharmony_ci * Must not be NULL. 756e5c31af7Sopenharmony_ci * @param out_primitive_mode Deref will be used to store iteration-specific primitive 757e5c31af7Sopenharmony_ci * mode. Must not be NULL. 758e5c31af7Sopenharmony_ci * @param out_vertex_ordering Deref will be used to store iteration-specific vertex ordering. 759e5c31af7Sopenharmony_ci * Must not be NULL. 760e5c31af7Sopenharmony_ci * @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object 761e5c31af7Sopenharmony_ci * storage should offer for the draw call to succeed. Must not 762e5c31af7Sopenharmony_ci * be NULL. 763e5c31af7Sopenharmony_ci **/ 764e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule1Test::getIterationProperties( 765e5c31af7Sopenharmony_ci unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode, 766e5c31af7Sopenharmony_ci _tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering, 767e5c31af7Sopenharmony_ci unsigned int* out_result_buffer_size) 768e5c31af7Sopenharmony_ci{ 769e5c31af7Sopenharmony_ci *out_vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_CCW; 770e5c31af7Sopenharmony_ci 771e5c31af7Sopenharmony_ci switch (n_iteration) 772e5c31af7Sopenharmony_ci { 773e5c31af7Sopenharmony_ci case 0: 774e5c31af7Sopenharmony_ci case 5: 775e5c31af7Sopenharmony_ci { 776e5c31af7Sopenharmony_ci /* Triangles (point mode) */ 777e5c31af7Sopenharmony_ci out_inner_tess_levels[0] = 1.0f; 778e5c31af7Sopenharmony_ci out_outer_tess_levels[0] = 1.0f; 779e5c31af7Sopenharmony_ci out_outer_tess_levels[1] = 1.0f; 780e5c31af7Sopenharmony_ci out_outer_tess_levels[2] = 1.0f; 781e5c31af7Sopenharmony_ci 782e5c31af7Sopenharmony_ci *out_point_mode = true; 783e5c31af7Sopenharmony_ci *out_primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES; 784e5c31af7Sopenharmony_ci 785e5c31af7Sopenharmony_ci break; 786e5c31af7Sopenharmony_ci } 787e5c31af7Sopenharmony_ci 788e5c31af7Sopenharmony_ci case 1: 789e5c31af7Sopenharmony_ci case 3: 790e5c31af7Sopenharmony_ci { 791e5c31af7Sopenharmony_ci /* Lines */ 792e5c31af7Sopenharmony_ci out_outer_tess_levels[0] = 1.0f; 793e5c31af7Sopenharmony_ci out_outer_tess_levels[1] = 1.0f; 794e5c31af7Sopenharmony_ci 795e5c31af7Sopenharmony_ci *out_point_mode = false; 796e5c31af7Sopenharmony_ci *out_primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES; 797e5c31af7Sopenharmony_ci 798e5c31af7Sopenharmony_ci break; 799e5c31af7Sopenharmony_ci } 800e5c31af7Sopenharmony_ci 801e5c31af7Sopenharmony_ci case 2: 802e5c31af7Sopenharmony_ci case 4: 803e5c31af7Sopenharmony_ci { 804e5c31af7Sopenharmony_ci /* Triangles */ 805e5c31af7Sopenharmony_ci out_inner_tess_levels[0] = 1.0f; 806e5c31af7Sopenharmony_ci out_outer_tess_levels[0] = 1.0f; 807e5c31af7Sopenharmony_ci out_outer_tess_levels[1] = 1.0f; 808e5c31af7Sopenharmony_ci out_outer_tess_levels[2] = 1.0f; 809e5c31af7Sopenharmony_ci 810e5c31af7Sopenharmony_ci *out_point_mode = false; 811e5c31af7Sopenharmony_ci *out_primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES; 812e5c31af7Sopenharmony_ci 813e5c31af7Sopenharmony_ci break; 814e5c31af7Sopenharmony_ci } 815e5c31af7Sopenharmony_ci 816e5c31af7Sopenharmony_ci default: 817e5c31af7Sopenharmony_ci { 818e5c31af7Sopenharmony_ci TCU_FAIL("Unrecognzied iteration index"); 819e5c31af7Sopenharmony_ci } 820e5c31af7Sopenharmony_ci } 821e5c31af7Sopenharmony_ci 822e5c31af7Sopenharmony_ci *out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator( 823e5c31af7Sopenharmony_ci *out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 824e5c31af7Sopenharmony_ci *out_point_mode); 825e5c31af7Sopenharmony_ci 826e5c31af7Sopenharmony_ci *out_result_buffer_size = static_cast<unsigned int>(*out_result_buffer_size * getDrawCallCountArgument() * 827e5c31af7Sopenharmony_ci 3 /* components */ * sizeof(float)); 828e5c31af7Sopenharmony_ci 829e5c31af7Sopenharmony_ci DE_ASSERT(*out_result_buffer_size != 0); 830e5c31af7Sopenharmony_ci} 831e5c31af7Sopenharmony_ci 832e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation evaluation shader code. 833e5c31af7Sopenharmony_ci * 834e5c31af7Sopenharmony_ci * @param n_iteration Iteration index, for which the source code is being obtained. 835e5c31af7Sopenharmony_ci * 836e5c31af7Sopenharmony_ci * @return Requested source code. 837e5c31af7Sopenharmony_ci **/ 838e5c31af7Sopenharmony_cistd::string TessellationShaderInvarianceRule1Test::getTECode(unsigned int n_iteration) 839e5c31af7Sopenharmony_ci{ 840e5c31af7Sopenharmony_ci unsigned int bo_size = 0; 841e5c31af7Sopenharmony_ci float inner_tess_levels[2] = { 0 }; 842e5c31af7Sopenharmony_ci float outer_tess_levels[4] = { 0 }; 843e5c31af7Sopenharmony_ci bool point_mode = false; 844e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN; 845e5c31af7Sopenharmony_ci _tessellation_shader_vertex_ordering vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_UNKNOWN; 846e5c31af7Sopenharmony_ci 847e5c31af7Sopenharmony_ci getIterationProperties(n_iteration, inner_tess_levels, outer_tess_levels, &point_mode, &primitive_mode, 848e5c31af7Sopenharmony_ci &vertex_ordering, &bo_size); 849e5c31af7Sopenharmony_ci 850e5c31af7Sopenharmony_ci return TessellationShaderUtils::getGenericTECode(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, primitive_mode, 851e5c31af7Sopenharmony_ci vertex_ordering, point_mode); 852e5c31af7Sopenharmony_ci} 853e5c31af7Sopenharmony_ci 854e5c31af7Sopenharmony_ci/** Verifies result data. Accesses data generated by all iterations. 855e5c31af7Sopenharmony_ci * 856e5c31af7Sopenharmony_ci * Throws TestError exception if an error occurs. 857e5c31af7Sopenharmony_ci * 858e5c31af7Sopenharmony_ci * @param all_iterations_data An array of pointers to buffers, holding gl_TessCoord 859e5c31af7Sopenharmony_ci * data generated by subsequent iterations. 860e5c31af7Sopenharmony_ci **/ 861e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule1Test::verifyResultData(const void** all_iterations_data) 862e5c31af7Sopenharmony_ci{ 863e5c31af7Sopenharmony_ci const float* lines_vertex_data_1 = (const float*)all_iterations_data[1]; 864e5c31af7Sopenharmony_ci const float* lines_vertex_data_2 = (const float*)all_iterations_data[3]; 865e5c31af7Sopenharmony_ci const float* point_vertex_data_1 = (const float*)all_iterations_data[0]; 866e5c31af7Sopenharmony_ci const float* point_vertex_data_2 = (const float*)all_iterations_data[5]; 867e5c31af7Sopenharmony_ci const float* tris_vertex_data_1 = (const float*)all_iterations_data[2]; 868e5c31af7Sopenharmony_ci const float* tris_vertex_data_2 = (const float*)all_iterations_data[4]; 869e5c31af7Sopenharmony_ci 870e5c31af7Sopenharmony_ci const unsigned int n_line_vertices = 2 /* vertices per line segment */ * getDrawCallCountArgument(); /* lines */ 871e5c31af7Sopenharmony_ci const unsigned int n_point_vertices = 1 /* vertices per point */ * getDrawCallCountArgument(); /* points */ 872e5c31af7Sopenharmony_ci const unsigned int n_tri_vertices = 3 /* vertices per triangle */ * getDrawCallCountArgument(); /* triangles */ 873e5c31af7Sopenharmony_ci const unsigned int vertex_size = sizeof(float) * 3; /* components */ 874e5c31af7Sopenharmony_ci 875e5c31af7Sopenharmony_ci /* Make sure the data sets match, given different draw call ordering */ 876e5c31af7Sopenharmony_ci for (int n_type = 0; n_type < 3 /* lines, points, tris */; ++n_type) 877e5c31af7Sopenharmony_ci { 878e5c31af7Sopenharmony_ci const float* data1_ptr = DE_NULL; 879e5c31af7Sopenharmony_ci const float* data2_ptr = DE_NULL; 880e5c31af7Sopenharmony_ci std::string data_type_string; 881e5c31af7Sopenharmony_ci unsigned int n_vertices = 0; 882e5c31af7Sopenharmony_ci 883e5c31af7Sopenharmony_ci switch (n_type) 884e5c31af7Sopenharmony_ci { 885e5c31af7Sopenharmony_ci case 0: 886e5c31af7Sopenharmony_ci { 887e5c31af7Sopenharmony_ci data1_ptr = lines_vertex_data_1; 888e5c31af7Sopenharmony_ci data2_ptr = lines_vertex_data_2; 889e5c31af7Sopenharmony_ci data_type_string = "Line"; 890e5c31af7Sopenharmony_ci n_vertices = n_line_vertices; 891e5c31af7Sopenharmony_ci 892e5c31af7Sopenharmony_ci break; 893e5c31af7Sopenharmony_ci } 894e5c31af7Sopenharmony_ci 895e5c31af7Sopenharmony_ci case 1: 896e5c31af7Sopenharmony_ci { 897e5c31af7Sopenharmony_ci data1_ptr = point_vertex_data_1; 898e5c31af7Sopenharmony_ci data2_ptr = point_vertex_data_2; 899e5c31af7Sopenharmony_ci data_type_string = "Point"; 900e5c31af7Sopenharmony_ci n_vertices = n_point_vertices; 901e5c31af7Sopenharmony_ci 902e5c31af7Sopenharmony_ci break; 903e5c31af7Sopenharmony_ci } 904e5c31af7Sopenharmony_ci 905e5c31af7Sopenharmony_ci case 2: 906e5c31af7Sopenharmony_ci { 907e5c31af7Sopenharmony_ci data1_ptr = tris_vertex_data_1; 908e5c31af7Sopenharmony_ci data2_ptr = tris_vertex_data_2; 909e5c31af7Sopenharmony_ci data_type_string = "Triangle"; 910e5c31af7Sopenharmony_ci n_vertices = n_tri_vertices; 911e5c31af7Sopenharmony_ci 912e5c31af7Sopenharmony_ci break; 913e5c31af7Sopenharmony_ci } 914e5c31af7Sopenharmony_ci 915e5c31af7Sopenharmony_ci default: 916e5c31af7Sopenharmony_ci { 917e5c31af7Sopenharmony_ci TCU_FAIL("Internal error: type index was not recognized"); 918e5c31af7Sopenharmony_ci } 919e5c31af7Sopenharmony_ci } /* switch (n_type) */ 920e5c31af7Sopenharmony_ci 921e5c31af7Sopenharmony_ci /* Make sure the buffer storage in both cases has been modified */ 922e5c31af7Sopenharmony_ci { 923e5c31af7Sopenharmony_ci unsigned int zero_bo_size = vertex_size * n_vertices; 924e5c31af7Sopenharmony_ci char* zero_bo_data = new char[vertex_size * n_vertices]; 925e5c31af7Sopenharmony_ci 926e5c31af7Sopenharmony_ci memset(zero_bo_data, 0, zero_bo_size); 927e5c31af7Sopenharmony_ci 928e5c31af7Sopenharmony_ci if (memcmp(data1_ptr, zero_bo_data, zero_bo_size) == 0 || 929e5c31af7Sopenharmony_ci memcmp(data2_ptr, zero_bo_data, zero_bo_size) == 0) 930e5c31af7Sopenharmony_ci { 931e5c31af7Sopenharmony_ci TCU_FAIL("One of the draw calls has not outputted any data to XFB buffer object storage"); 932e5c31af7Sopenharmony_ci } 933e5c31af7Sopenharmony_ci 934e5c31af7Sopenharmony_ci delete[] zero_bo_data; 935e5c31af7Sopenharmony_ci zero_bo_data = NULL; 936e5c31af7Sopenharmony_ci } 937e5c31af7Sopenharmony_ci 938e5c31af7Sopenharmony_ci /* Compare the data */ 939e5c31af7Sopenharmony_ci if (memcmp(data1_ptr, data2_ptr, vertex_size * n_vertices) != 0) 940e5c31af7Sopenharmony_ci { 941e5c31af7Sopenharmony_ci std::stringstream logMessage; 942e5c31af7Sopenharmony_ci 943e5c31af7Sopenharmony_ci logMessage << data_type_string << " data rendered in pass 1: ("; 944e5c31af7Sopenharmony_ci 945e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < n_vertices; ++n_vertex) 946e5c31af7Sopenharmony_ci { 947e5c31af7Sopenharmony_ci logMessage << data1_ptr[n_vertex]; 948e5c31af7Sopenharmony_ci 949e5c31af7Sopenharmony_ci if (n_vertex != (n_vertices - 1)) 950e5c31af7Sopenharmony_ci { 951e5c31af7Sopenharmony_ci logMessage << ", "; 952e5c31af7Sopenharmony_ci } 953e5c31af7Sopenharmony_ci else 954e5c31af7Sopenharmony_ci { 955e5c31af7Sopenharmony_ci logMessage << ") "; 956e5c31af7Sopenharmony_ci } 957e5c31af7Sopenharmony_ci } /* for (all vertices) */ 958e5c31af7Sopenharmony_ci 959e5c31af7Sopenharmony_ci logMessage << "and in pass 2: ("; 960e5c31af7Sopenharmony_ci 961e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < n_vertices; ++n_vertex) 962e5c31af7Sopenharmony_ci { 963e5c31af7Sopenharmony_ci logMessage << data2_ptr[n_vertex]; 964e5c31af7Sopenharmony_ci 965e5c31af7Sopenharmony_ci if (n_vertex != (n_vertices - 1)) 966e5c31af7Sopenharmony_ci { 967e5c31af7Sopenharmony_ci logMessage << ", "; 968e5c31af7Sopenharmony_ci } 969e5c31af7Sopenharmony_ci else 970e5c31af7Sopenharmony_ci { 971e5c31af7Sopenharmony_ci logMessage << ") "; 972e5c31af7Sopenharmony_ci } 973e5c31af7Sopenharmony_ci } /* for (all vertices) */ 974e5c31af7Sopenharmony_ci 975e5c31af7Sopenharmony_ci logMessage << "do not match"; 976e5c31af7Sopenharmony_ci 977e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << logMessage.str().c_str() << tcu::TestLog::EndMessage; 978e5c31af7Sopenharmony_ci 979e5c31af7Sopenharmony_ci TCU_FAIL("Data mismatch"); 980e5c31af7Sopenharmony_ci } /* if (data mismatch) */ 981e5c31af7Sopenharmony_ci } /* for (all primitive types) */ 982e5c31af7Sopenharmony_ci} 983e5c31af7Sopenharmony_ci 984e5c31af7Sopenharmony_ci/** Constructor. 985e5c31af7Sopenharmony_ci * 986e5c31af7Sopenharmony_ci * @param context Rendering context. 987e5c31af7Sopenharmony_ci * 988e5c31af7Sopenharmony_ci **/ 989e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule2Test::TessellationShaderInvarianceRule2Test(Context& context, 990e5c31af7Sopenharmony_ci const ExtParameters& extParams) 991e5c31af7Sopenharmony_ci : TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule2", 992e5c31af7Sopenharmony_ci "Verifies conformance with second invariance rule") 993e5c31af7Sopenharmony_ci{ 994e5c31af7Sopenharmony_ci memset(m_n_tessellated_vertices, 0, sizeof(m_n_tessellated_vertices)); 995e5c31af7Sopenharmony_ci} 996e5c31af7Sopenharmony_ci 997e5c31af7Sopenharmony_ci/** Destructor. */ 998e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule2Test::~TessellationShaderInvarianceRule2Test() 999e5c31af7Sopenharmony_ci{ 1000e5c31af7Sopenharmony_ci /* Left blank intentionally */ 1001e5c31af7Sopenharmony_ci} 1002e5c31af7Sopenharmony_ci 1003e5c31af7Sopenharmony_ci/** Retrieves amount of iterations the base test implementation should run before 1004e5c31af7Sopenharmony_ci * calling global verification routine. 1005e5c31af7Sopenharmony_ci * 1006e5c31af7Sopenharmony_ci * @return Always 4. 1007e5c31af7Sopenharmony_ci **/ 1008e5c31af7Sopenharmony_ciunsigned int TessellationShaderInvarianceRule2Test::getAmountOfIterations() 1009e5c31af7Sopenharmony_ci{ 1010e5c31af7Sopenharmony_ci return 4; 1011e5c31af7Sopenharmony_ci} 1012e5c31af7Sopenharmony_ci 1013e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation properties. 1014e5c31af7Sopenharmony_ci * 1015e5c31af7Sopenharmony_ci * @param n_iteration Iteration index to retrieve the properties for. 1016e5c31af7Sopenharmony_ci * @param out_inner_tess_levels Deref will be used to store iteration-specific inner 1017e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 1018e5c31af7Sopenharmony_ci * @param out_outer_tess_levels Deref will be used to store iteration-specific outer 1019e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 1020e5c31af7Sopenharmony_ci * @param out_point_mode Deref will be used to store iteration-specific flag 1021e5c31af7Sopenharmony_ci * telling whether point mode should be enabled for given pass. 1022e5c31af7Sopenharmony_ci * Must not be NULL. 1023e5c31af7Sopenharmony_ci * @param out_primitive_mode Deref will be used to store iteration-specific primitive 1024e5c31af7Sopenharmony_ci * mode. Must not be NULL. 1025e5c31af7Sopenharmony_ci * @param out_vertex_ordering Deref will be used to store iteration-specific vertex 1026e5c31af7Sopenharmony_ci * ordering. Must not be NULL. 1027e5c31af7Sopenharmony_ci * @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object 1028e5c31af7Sopenharmony_ci * storage should offer for the draw call to succeed. Can 1029e5c31af7Sopenharmony_ci * be NULL. 1030e5c31af7Sopenharmony_ci **/ 1031e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule2Test::getIterationProperties( 1032e5c31af7Sopenharmony_ci unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode, 1033e5c31af7Sopenharmony_ci _tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering, 1034e5c31af7Sopenharmony_ci unsigned int* out_result_buffer_size) 1035e5c31af7Sopenharmony_ci{ 1036e5c31af7Sopenharmony_ci *out_vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_CCW; 1037e5c31af7Sopenharmony_ci 1038e5c31af7Sopenharmony_ci switch (n_iteration) 1039e5c31af7Sopenharmony_ci { 1040e5c31af7Sopenharmony_ci case 0: 1041e5c31af7Sopenharmony_ci case 1: 1042e5c31af7Sopenharmony_ci { 1043e5c31af7Sopenharmony_ci /* Triangles */ 1044e5c31af7Sopenharmony_ci out_outer_tess_levels[0] = 2.0f; 1045e5c31af7Sopenharmony_ci out_outer_tess_levels[1] = 3.0f; 1046e5c31af7Sopenharmony_ci out_outer_tess_levels[2] = 4.0f; 1047e5c31af7Sopenharmony_ci 1048e5c31af7Sopenharmony_ci if (n_iteration == 0) 1049e5c31af7Sopenharmony_ci { 1050e5c31af7Sopenharmony_ci out_inner_tess_levels[0] = 4.0f; 1051e5c31af7Sopenharmony_ci out_inner_tess_levels[1] = 5.0f; 1052e5c31af7Sopenharmony_ci } 1053e5c31af7Sopenharmony_ci else 1054e5c31af7Sopenharmony_ci { 1055e5c31af7Sopenharmony_ci out_inner_tess_levels[0] = 3.0f; 1056e5c31af7Sopenharmony_ci out_inner_tess_levels[1] = 4.0f; 1057e5c31af7Sopenharmony_ci } 1058e5c31af7Sopenharmony_ci 1059e5c31af7Sopenharmony_ci *out_point_mode = false; 1060e5c31af7Sopenharmony_ci *out_primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES; 1061e5c31af7Sopenharmony_ci 1062e5c31af7Sopenharmony_ci break; 1063e5c31af7Sopenharmony_ci } 1064e5c31af7Sopenharmony_ci 1065e5c31af7Sopenharmony_ci case 2: 1066e5c31af7Sopenharmony_ci case 3: 1067e5c31af7Sopenharmony_ci { 1068e5c31af7Sopenharmony_ci /* Quads */ 1069e5c31af7Sopenharmony_ci out_outer_tess_levels[0] = 2.0f; 1070e5c31af7Sopenharmony_ci out_outer_tess_levels[1] = 3.0f; 1071e5c31af7Sopenharmony_ci out_outer_tess_levels[2] = 4.0f; 1072e5c31af7Sopenharmony_ci out_outer_tess_levels[3] = 5.0f; 1073e5c31af7Sopenharmony_ci 1074e5c31af7Sopenharmony_ci if (n_iteration == 2) 1075e5c31af7Sopenharmony_ci { 1076e5c31af7Sopenharmony_ci out_inner_tess_levels[0] = 2.0f; 1077e5c31af7Sopenharmony_ci out_inner_tess_levels[1] = 3.0f; 1078e5c31af7Sopenharmony_ci } 1079e5c31af7Sopenharmony_ci else 1080e5c31af7Sopenharmony_ci { 1081e5c31af7Sopenharmony_ci out_inner_tess_levels[0] = 4.0f; 1082e5c31af7Sopenharmony_ci out_inner_tess_levels[1] = 5.0f; 1083e5c31af7Sopenharmony_ci } 1084e5c31af7Sopenharmony_ci 1085e5c31af7Sopenharmony_ci *out_point_mode = false; 1086e5c31af7Sopenharmony_ci *out_primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS; 1087e5c31af7Sopenharmony_ci 1088e5c31af7Sopenharmony_ci break; 1089e5c31af7Sopenharmony_ci } 1090e5c31af7Sopenharmony_ci 1091e5c31af7Sopenharmony_ci default: 1092e5c31af7Sopenharmony_ci { 1093e5c31af7Sopenharmony_ci TCU_FAIL("Unrecognized iteration index"); 1094e5c31af7Sopenharmony_ci } 1095e5c31af7Sopenharmony_ci } 1096e5c31af7Sopenharmony_ci 1097e5c31af7Sopenharmony_ci if (out_result_buffer_size != DE_NULL) 1098e5c31af7Sopenharmony_ci { 1099e5c31af7Sopenharmony_ci *out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator( 1100e5c31af7Sopenharmony_ci *out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 1101e5c31af7Sopenharmony_ci *out_point_mode); 1102e5c31af7Sopenharmony_ci 1103e5c31af7Sopenharmony_ci m_n_tessellated_vertices[n_iteration] = *out_result_buffer_size; 1104e5c31af7Sopenharmony_ci *out_result_buffer_size = 1105e5c31af7Sopenharmony_ci static_cast<unsigned int>(*out_result_buffer_size * 3 /* components */ * sizeof(float)); 1106e5c31af7Sopenharmony_ci 1107e5c31af7Sopenharmony_ci DE_ASSERT(*out_result_buffer_size != 0); 1108e5c31af7Sopenharmony_ci } 1109e5c31af7Sopenharmony_ci} 1110e5c31af7Sopenharmony_ci 1111e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation evaluation shader code. 1112e5c31af7Sopenharmony_ci * 1113e5c31af7Sopenharmony_ci * @param n_iteration Iteration index, for which the source code is being obtained. 1114e5c31af7Sopenharmony_ci * 1115e5c31af7Sopenharmony_ci * @return Requested source code. 1116e5c31af7Sopenharmony_ci **/ 1117e5c31af7Sopenharmony_cistd::string TessellationShaderInvarianceRule2Test::getTECode(unsigned int n_iteration) 1118e5c31af7Sopenharmony_ci{ 1119e5c31af7Sopenharmony_ci unsigned int bo_size = 0; 1120e5c31af7Sopenharmony_ci float inner_tess_levels[2] = { 0 }; 1121e5c31af7Sopenharmony_ci float outer_tess_levels[4] = { 0 }; 1122e5c31af7Sopenharmony_ci bool point_mode = false; 1123e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN; 1124e5c31af7Sopenharmony_ci _tessellation_shader_vertex_ordering vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_UNKNOWN; 1125e5c31af7Sopenharmony_ci 1126e5c31af7Sopenharmony_ci getIterationProperties(n_iteration, inner_tess_levels, outer_tess_levels, &point_mode, &primitive_mode, 1127e5c31af7Sopenharmony_ci &vertex_ordering, &bo_size); 1128e5c31af7Sopenharmony_ci 1129e5c31af7Sopenharmony_ci return TessellationShaderUtils::getGenericTECode(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, primitive_mode, 1130e5c31af7Sopenharmony_ci vertex_ordering, point_mode); 1131e5c31af7Sopenharmony_ci} 1132e5c31af7Sopenharmony_ci 1133e5c31af7Sopenharmony_ci/** Verifies result data. Accesses data generated by all iterations. 1134e5c31af7Sopenharmony_ci * 1135e5c31af7Sopenharmony_ci * Throws TestError exception if an error occurs. 1136e5c31af7Sopenharmony_ci * 1137e5c31af7Sopenharmony_ci * @param all_iterations_data An array of pointers to buffers, holding gl_TessCoord 1138e5c31af7Sopenharmony_ci * data generated by subsequent iterations. 1139e5c31af7Sopenharmony_ci **/ 1140e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule2Test::verifyResultData(const void** all_iterations_data) 1141e5c31af7Sopenharmony_ci{ 1142e5c31af7Sopenharmony_ci /* Iterate through one tessellated set of vertices for a given primitive type 1143e5c31af7Sopenharmony_ci * and identify outer vertices. Make sure exactly the same vertices can be 1144e5c31af7Sopenharmony_ci * found in the other set of vertices, generated with different input tessellation 1145e5c31af7Sopenharmony_ci * level. 1146e5c31af7Sopenharmony_ci */ 1147e5c31af7Sopenharmony_ci for (int n_primitive_type = 0; n_primitive_type < 2; /* triangles / quads */ 1148e5c31af7Sopenharmony_ci ++n_primitive_type) 1149e5c31af7Sopenharmony_ci { 1150e5c31af7Sopenharmony_ci const float* data1_ptr = (const float*)all_iterations_data[n_primitive_type * 2 + 0]; 1151e5c31af7Sopenharmony_ci const float* data2_ptr = (const float*)all_iterations_data[n_primitive_type * 2 + 1]; 1152e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_mode = (n_primitive_type == 0) ? 1153e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES : 1154e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS; 1155e5c31af7Sopenharmony_ci std::vector<_vertex> outer_vertices; 1156e5c31af7Sopenharmony_ci 1157e5c31af7Sopenharmony_ci /* Iterate through all data1 vertices.. */ 1158e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < m_n_tessellated_vertices[n_primitive_type * 2]; ++n_vertex) 1159e5c31af7Sopenharmony_ci { 1160e5c31af7Sopenharmony_ci /* Check if any of the components is equal to 0 or 1. If so, this could 1161e5c31af7Sopenharmony_ci * be an edge vertex. 1162e5c31af7Sopenharmony_ci */ 1163e5c31af7Sopenharmony_ci const float* vertex_ptr = data1_ptr + n_vertex * 3; /* components */ 1164e5c31af7Sopenharmony_ci 1165e5c31af7Sopenharmony_ci if (TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, vertex_ptr)) 1166e5c31af7Sopenharmony_ci { 1167e5c31af7Sopenharmony_ci /* Only add the vertex if it has not been added already to the vector */ 1168e5c31af7Sopenharmony_ci bool has_already_been_added = false; 1169e5c31af7Sopenharmony_ci 1170e5c31af7Sopenharmony_ci for (std::vector<_vertex>::const_iterator vertex_iterator = outer_vertices.begin(); 1171e5c31af7Sopenharmony_ci vertex_iterator != outer_vertices.end(); vertex_iterator++) 1172e5c31af7Sopenharmony_ci { 1173e5c31af7Sopenharmony_ci if (vertex_iterator->u == vertex_ptr[0] && vertex_iterator->v == vertex_ptr[1] && 1174e5c31af7Sopenharmony_ci vertex_iterator->w == vertex_ptr[2]) 1175e5c31af7Sopenharmony_ci { 1176e5c31af7Sopenharmony_ci has_already_been_added = true; 1177e5c31af7Sopenharmony_ci 1178e5c31af7Sopenharmony_ci break; 1179e5c31af7Sopenharmony_ci } 1180e5c31af7Sopenharmony_ci } /* for (all outer vertices stored so far) */ 1181e5c31af7Sopenharmony_ci 1182e5c31af7Sopenharmony_ci if (!has_already_been_added) 1183e5c31af7Sopenharmony_ci { 1184e5c31af7Sopenharmony_ci _vertex vertex; 1185e5c31af7Sopenharmony_ci 1186e5c31af7Sopenharmony_ci vertex.u = vertex_ptr[0]; 1187e5c31af7Sopenharmony_ci vertex.v = vertex_ptr[1]; 1188e5c31af7Sopenharmony_ci vertex.w = vertex_ptr[2]; 1189e5c31af7Sopenharmony_ci 1190e5c31af7Sopenharmony_ci outer_vertices.push_back(vertex); 1191e5c31af7Sopenharmony_ci } 1192e5c31af7Sopenharmony_ci } /* if (input vertex is located on outer edge) */ 1193e5c31af7Sopenharmony_ci } /* for (all input vertices) */ 1194e5c31af7Sopenharmony_ci 1195e5c31af7Sopenharmony_ci DE_ASSERT(outer_vertices.size() != 0); 1196e5c31af7Sopenharmony_ci 1197e5c31af7Sopenharmony_ci /* Now that we know where outer vertices are, make sure they are present in the other data set */ 1198e5c31af7Sopenharmony_ci for (std::vector<_vertex>::const_iterator ref_vertex_iterator = outer_vertices.begin(); 1199e5c31af7Sopenharmony_ci ref_vertex_iterator != outer_vertices.end(); ref_vertex_iterator++) 1200e5c31af7Sopenharmony_ci { 1201e5c31af7Sopenharmony_ci bool has_been_found = false; 1202e5c31af7Sopenharmony_ci const _vertex& ref_vertex = *ref_vertex_iterator; 1203e5c31af7Sopenharmony_ci 1204e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < m_n_tessellated_vertices[n_primitive_type * 2 + 1]; ++n_vertex) 1205e5c31af7Sopenharmony_ci { 1206e5c31af7Sopenharmony_ci const float* vertex_ptr = data2_ptr + n_vertex * 3; /* components */ 1207e5c31af7Sopenharmony_ci 1208e5c31af7Sopenharmony_ci if (vertex_ptr[0] == ref_vertex.u && vertex_ptr[1] == ref_vertex.v && vertex_ptr[2] == ref_vertex.w) 1209e5c31af7Sopenharmony_ci { 1210e5c31af7Sopenharmony_ci has_been_found = true; 1211e5c31af7Sopenharmony_ci 1212e5c31af7Sopenharmony_ci break; 1213e5c31af7Sopenharmony_ci } 1214e5c31af7Sopenharmony_ci } /* for (all vertices in the other data set) */ 1215e5c31af7Sopenharmony_ci 1216e5c31af7Sopenharmony_ci if (!has_been_found) 1217e5c31af7Sopenharmony_ci { 1218e5c31af7Sopenharmony_ci float cmp_inner_tess_levels[2]; 1219e5c31af7Sopenharmony_ci float cmp_outer_tess_levels[4]; 1220e5c31af7Sopenharmony_ci bool cmp_point_mode; 1221e5c31af7Sopenharmony_ci _tessellation_primitive_mode cmp_primitive_mode; 1222e5c31af7Sopenharmony_ci _tessellation_shader_vertex_ordering cmp_vertex_ordering; 1223e5c31af7Sopenharmony_ci std::string primitive_type = (n_primitive_type == 0) ? "triangles" : "quads"; 1224e5c31af7Sopenharmony_ci float ref_inner_tess_levels[2]; 1225e5c31af7Sopenharmony_ci float ref_outer_tess_levels[4]; 1226e5c31af7Sopenharmony_ci bool ref_point_mode; 1227e5c31af7Sopenharmony_ci _tessellation_primitive_mode ref_primitive_mode; 1228e5c31af7Sopenharmony_ci _tessellation_shader_vertex_ordering ref_vertex_ordering; 1229e5c31af7Sopenharmony_ci 1230e5c31af7Sopenharmony_ci getIterationProperties(n_primitive_type * 2, ref_inner_tess_levels, ref_outer_tess_levels, 1231e5c31af7Sopenharmony_ci &ref_point_mode, &ref_primitive_mode, &ref_vertex_ordering, NULL); 1232e5c31af7Sopenharmony_ci getIterationProperties(n_primitive_type * 2 + 1, cmp_inner_tess_levels, cmp_outer_tess_levels, 1233e5c31af7Sopenharmony_ci &cmp_point_mode, &cmp_primitive_mode, &cmp_vertex_ordering, NULL); 1234e5c31af7Sopenharmony_ci 1235e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Outer vertex" 1236e5c31af7Sopenharmony_ci << " (" << ref_vertex.u << ", " << ref_vertex.v << ", " << ref_vertex.w << ")" 1237e5c31af7Sopenharmony_ci << " was not found in tessellated data coordinate set generated" 1238e5c31af7Sopenharmony_ci << " for primitive type: " << primitive_type.c_str() 1239e5c31af7Sopenharmony_ci << ". Reference inner tessellation level:" 1240e5c31af7Sopenharmony_ci << " (" << ref_inner_tess_levels[0] << ", " << ref_inner_tess_levels[1] 1241e5c31af7Sopenharmony_ci << "), reference outer tessellation level:" 1242e5c31af7Sopenharmony_ci << " (" << ref_outer_tess_levels[0] << ", " << ref_outer_tess_levels[1] << ", " 1243e5c31af7Sopenharmony_ci << ref_outer_tess_levels[2] << ", " << ref_outer_tess_levels[3] 1244e5c31af7Sopenharmony_ci << "), test inner tessellation level:" 1245e5c31af7Sopenharmony_ci << " (" << cmp_inner_tess_levels[0] << ", " << cmp_inner_tess_levels[1] 1246e5c31af7Sopenharmony_ci << "), reference outer tessellation level:" 1247e5c31af7Sopenharmony_ci << " (" << cmp_outer_tess_levels[0] << ", " << cmp_outer_tess_levels[1] << ", " 1248e5c31af7Sopenharmony_ci << cmp_outer_tess_levels[2] << ", " << cmp_outer_tess_levels[3] << ")." 1249e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1250e5c31af7Sopenharmony_ci 1251e5c31af7Sopenharmony_ci TCU_FAIL("Outer edge vertex was not found in tessellated coordinate set generated for " 1252e5c31af7Sopenharmony_ci "the same outer tessellation levels and vertex spacing, but different inner " 1253e5c31af7Sopenharmony_ci "tessellation levels"); 1254e5c31af7Sopenharmony_ci } /* if (outer edge vertex was not found in the other set) */ 1255e5c31af7Sopenharmony_ci } /* for (all outer edge vertices) */ 1256e5c31af7Sopenharmony_ci } /* for (both primitive types) */ 1257e5c31af7Sopenharmony_ci} 1258e5c31af7Sopenharmony_ci 1259e5c31af7Sopenharmony_ci/** Constructor. 1260e5c31af7Sopenharmony_ci * 1261e5c31af7Sopenharmony_ci * @param context Rendering context. 1262e5c31af7Sopenharmony_ci * 1263e5c31af7Sopenharmony_ci **/ 1264e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule3Test::TessellationShaderInvarianceRule3Test(Context& context, 1265e5c31af7Sopenharmony_ci const ExtParameters& extParams) 1266e5c31af7Sopenharmony_ci : TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule3", 1267e5c31af7Sopenharmony_ci "Verifies conformance with third invariance rule") 1268e5c31af7Sopenharmony_ci{ 1269e5c31af7Sopenharmony_ci} 1270e5c31af7Sopenharmony_ci 1271e5c31af7Sopenharmony_ci/** Destructor. */ 1272e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule3Test::~TessellationShaderInvarianceRule3Test() 1273e5c31af7Sopenharmony_ci{ 1274e5c31af7Sopenharmony_ci /* Left blank intentionally */ 1275e5c31af7Sopenharmony_ci} 1276e5c31af7Sopenharmony_ci 1277e5c31af7Sopenharmony_ci/** Retrieves amount of iterations the base test implementation should run before 1278e5c31af7Sopenharmony_ci * calling global verification routine. 1279e5c31af7Sopenharmony_ci * 1280e5c31af7Sopenharmony_ci * @return A value that depends on initTestIterations() behavior. 1281e5c31af7Sopenharmony_ci **/ 1282e5c31af7Sopenharmony_ciunsigned int TessellationShaderInvarianceRule3Test::getAmountOfIterations() 1283e5c31af7Sopenharmony_ci{ 1284e5c31af7Sopenharmony_ci if (m_test_iterations.size() == 0) 1285e5c31af7Sopenharmony_ci { 1286e5c31af7Sopenharmony_ci initTestIterations(); 1287e5c31af7Sopenharmony_ci } 1288e5c31af7Sopenharmony_ci 1289e5c31af7Sopenharmony_ci return (unsigned int)m_test_iterations.size(); 1290e5c31af7Sopenharmony_ci} 1291e5c31af7Sopenharmony_ci 1292e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation properties. 1293e5c31af7Sopenharmony_ci * 1294e5c31af7Sopenharmony_ci * @param n_iteration Iteration index to retrieve the properties for. 1295e5c31af7Sopenharmony_ci * @param out_inner_tess_levels Deref will be used to store iteration-specific inner 1296e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 1297e5c31af7Sopenharmony_ci * @param out_outer_tess_levels Deref will be used to store iteration-specific outer 1298e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 1299e5c31af7Sopenharmony_ci * @param out_point_mode Deref will be used to store iteration-specific flag 1300e5c31af7Sopenharmony_ci * telling whether point mode should be enabled for given pass. 1301e5c31af7Sopenharmony_ci * Must not be NULL. 1302e5c31af7Sopenharmony_ci * @param out_primitive_mode Deref will be used to store iteration-specific primitive 1303e5c31af7Sopenharmony_ci * mode. Must not be NULL. 1304e5c31af7Sopenharmony_ci * @param out_vertex_ordering Deref will be used to store iteration-specific vertex 1305e5c31af7Sopenharmony_ci * ordering. Must not be NULL. 1306e5c31af7Sopenharmony_ci * @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object 1307e5c31af7Sopenharmony_ci * storage should offer for the draw call to succeed. Can 1308e5c31af7Sopenharmony_ci * be NULL. 1309e5c31af7Sopenharmony_ci **/ 1310e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule3Test::getIterationProperties( 1311e5c31af7Sopenharmony_ci unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode, 1312e5c31af7Sopenharmony_ci _tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering, 1313e5c31af7Sopenharmony_ci unsigned int* out_result_buffer_size) 1314e5c31af7Sopenharmony_ci{ 1315e5c31af7Sopenharmony_ci DE_ASSERT(m_test_iterations.size() > n_iteration); 1316e5c31af7Sopenharmony_ci 1317e5c31af7Sopenharmony_ci _test_iteration& test_iteration = m_test_iterations[n_iteration]; 1318e5c31af7Sopenharmony_ci 1319e5c31af7Sopenharmony_ci memcpy(out_inner_tess_levels, test_iteration.inner_tess_levels, sizeof(test_iteration.inner_tess_levels)); 1320e5c31af7Sopenharmony_ci memcpy(out_outer_tess_levels, test_iteration.outer_tess_levels, sizeof(test_iteration.outer_tess_levels)); 1321e5c31af7Sopenharmony_ci 1322e5c31af7Sopenharmony_ci *out_point_mode = false; 1323e5c31af7Sopenharmony_ci *out_primitive_mode = test_iteration.primitive_mode; 1324e5c31af7Sopenharmony_ci *out_vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_CCW; 1325e5c31af7Sopenharmony_ci 1326e5c31af7Sopenharmony_ci if (out_result_buffer_size != DE_NULL) 1327e5c31af7Sopenharmony_ci { 1328e5c31af7Sopenharmony_ci *out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator( 1329e5c31af7Sopenharmony_ci *out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, test_iteration.vertex_spacing, 1330e5c31af7Sopenharmony_ci *out_point_mode); 1331e5c31af7Sopenharmony_ci test_iteration.n_vertices = *out_result_buffer_size; 1332e5c31af7Sopenharmony_ci *out_result_buffer_size = 1333e5c31af7Sopenharmony_ci static_cast<unsigned int>(*out_result_buffer_size * 3 /* components */ * sizeof(float)); 1334e5c31af7Sopenharmony_ci 1335e5c31af7Sopenharmony_ci DE_ASSERT(*out_result_buffer_size != 0); 1336e5c31af7Sopenharmony_ci } 1337e5c31af7Sopenharmony_ci} 1338e5c31af7Sopenharmony_ci 1339e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation evaluation shader code. 1340e5c31af7Sopenharmony_ci * 1341e5c31af7Sopenharmony_ci * @param n_iteration Iteration index, for which the source code is being obtained. 1342e5c31af7Sopenharmony_ci * 1343e5c31af7Sopenharmony_ci * @return Requested source code. 1344e5c31af7Sopenharmony_ci **/ 1345e5c31af7Sopenharmony_cistd::string TessellationShaderInvarianceRule3Test::getTECode(unsigned int n_iteration) 1346e5c31af7Sopenharmony_ci{ 1347e5c31af7Sopenharmony_ci DE_ASSERT(m_test_iterations.size() > n_iteration); 1348e5c31af7Sopenharmony_ci 1349e5c31af7Sopenharmony_ci const _test_iteration& test_iteration = m_test_iterations[n_iteration]; 1350e5c31af7Sopenharmony_ci 1351e5c31af7Sopenharmony_ci return TessellationShaderUtils::getGenericTECode(test_iteration.vertex_spacing, test_iteration.primitive_mode, 1352e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_ORDERING_CCW, false); /* point mode */ 1353e5c31af7Sopenharmony_ci} 1354e5c31af7Sopenharmony_ci 1355e5c31af7Sopenharmony_ci/** Initializes test iterations for the test. The following modes and inner/outer tess level 1356e5c31af7Sopenharmony_ci * configurations are used to form the test set: 1357e5c31af7Sopenharmony_ci * 1358e5c31af7Sopenharmony_ci * - Inner/outer tessellation level combinations as returned by 1359e5c31af7Sopenharmony_ci * TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode() 1360e5c31af7Sopenharmony_ci * - All primitive modes; 1361e5c31af7Sopenharmony_ci * - All vertex spacing modes; 1362e5c31af7Sopenharmony_ci * 1363e5c31af7Sopenharmony_ci * All permutations are used to generate the test set. 1364e5c31af7Sopenharmony_ci **/ 1365e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule3Test::initTestIterations() 1366e5c31af7Sopenharmony_ci{ 1367e5c31af7Sopenharmony_ci DE_ASSERT(m_test_iterations.size() == 0); 1368e5c31af7Sopenharmony_ci 1369e5c31af7Sopenharmony_ci /* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */ 1370e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1371e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_gen_level_value = 0; 1372e5c31af7Sopenharmony_ci 1373e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value); 1374e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 1375e5c31af7Sopenharmony_ci 1376e5c31af7Sopenharmony_ci /* Iterate through all primitive and vertex spacing modes */ 1377e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES, 1378e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, 1379e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES }; 1380e5c31af7Sopenharmony_ci _tessellation_shader_vertex_spacing vs_modes[] = { TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 1381e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN, 1382e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD }; 1383e5c31af7Sopenharmony_ci 1384e5c31af7Sopenharmony_ci const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]); 1385e5c31af7Sopenharmony_ci const unsigned int n_vs_modes = sizeof(vs_modes) / sizeof(vs_modes[0]); 1386e5c31af7Sopenharmony_ci 1387e5c31af7Sopenharmony_ci for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode) 1388e5c31af7Sopenharmony_ci { 1389e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode]; 1390e5c31af7Sopenharmony_ci 1391e5c31af7Sopenharmony_ci for (unsigned int n_vs_mode = 0; n_vs_mode < n_vs_modes; ++n_vs_mode) 1392e5c31af7Sopenharmony_ci { 1393e5c31af7Sopenharmony_ci _tessellation_shader_vertex_spacing vs_mode = vs_modes[n_vs_mode]; 1394e5c31af7Sopenharmony_ci 1395e5c31af7Sopenharmony_ci /* Retrieve inner/outer tessellation level combinations we want the tests to be run for */ 1396e5c31af7Sopenharmony_ci _tessellation_levels_set levels_set; 1397e5c31af7Sopenharmony_ci 1398e5c31af7Sopenharmony_ci levels_set = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode( 1399e5c31af7Sopenharmony_ci primitive_mode, gl_max_tess_gen_level_value, 1400e5c31af7Sopenharmony_ci TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE); 1401e5c31af7Sopenharmony_ci 1402e5c31af7Sopenharmony_ci /* Iterate through all configurations */ 1403e5c31af7Sopenharmony_ci for (_tessellation_levels_set_const_iterator levels_iterator = levels_set.begin(); 1404e5c31af7Sopenharmony_ci levels_iterator != levels_set.end(); levels_iterator++) 1405e5c31af7Sopenharmony_ci { 1406e5c31af7Sopenharmony_ci const _tessellation_levels& levels = *levels_iterator; 1407e5c31af7Sopenharmony_ci 1408e5c31af7Sopenharmony_ci /* Create a test descriptor for all the parameters we now have */ 1409e5c31af7Sopenharmony_ci _test_iteration test; 1410e5c31af7Sopenharmony_ci 1411e5c31af7Sopenharmony_ci memcpy(test.inner_tess_levels, levels.inner, sizeof(test.inner_tess_levels)); 1412e5c31af7Sopenharmony_ci memcpy(test.outer_tess_levels, levels.outer, sizeof(test.outer_tess_levels)); 1413e5c31af7Sopenharmony_ci 1414e5c31af7Sopenharmony_ci test.primitive_mode = primitive_mode; 1415e5c31af7Sopenharmony_ci test.vertex_spacing = vs_mode; 1416e5c31af7Sopenharmony_ci 1417e5c31af7Sopenharmony_ci m_test_iterations.push_back(test); 1418e5c31af7Sopenharmony_ci } /* for (all inner/outer tessellation levels) */ 1419e5c31af7Sopenharmony_ci } /* for (all vertex spacing modes) */ 1420e5c31af7Sopenharmony_ci } /* for (all primitive modes) */ 1421e5c31af7Sopenharmony_ci} 1422e5c31af7Sopenharmony_ci 1423e5c31af7Sopenharmony_ci/** Verifies result data on per-iteration basis. 1424e5c31af7Sopenharmony_ci * 1425e5c31af7Sopenharmony_ci * Throws TestError exception if an error occurs. 1426e5c31af7Sopenharmony_ci * 1427e5c31af7Sopenharmony_ci * @param n_iteration Index of iteration the check should be performed for. 1428e5c31af7Sopenharmony_ci * @param data Points to array of vec3s storing the vertices as 1429e5c31af7Sopenharmony_ci * generated by tessellation 1430e5c31af7Sopenharmony_ci **/ 1431e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule3Test::verifyResultDataForIteration(unsigned int n_iteration, const void* data) 1432e5c31af7Sopenharmony_ci{ 1433e5c31af7Sopenharmony_ci DE_ASSERT(m_test_iterations.size() > n_iteration); 1434e5c31af7Sopenharmony_ci 1435e5c31af7Sopenharmony_ci const glw::GLfloat* data_float = (const glw::GLfloat*)data; 1436e5c31af7Sopenharmony_ci const _test_iteration& test_iteration = m_test_iterations[n_iteration]; 1437e5c31af7Sopenharmony_ci 1438e5c31af7Sopenharmony_ci /* Iterate through all generated vertices.. */ 1439e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < test_iteration.n_vertices; ++n_vertex) 1440e5c31af7Sopenharmony_ci { 1441e5c31af7Sopenharmony_ci _vertex expected_vertex; 1442e5c31af7Sopenharmony_ci const glw::GLfloat* vertex_data = data_float + 3 /* components */ * n_vertex; 1443e5c31af7Sopenharmony_ci 1444e5c31af7Sopenharmony_ci expected_vertex.u = -1.0f; 1445e5c31af7Sopenharmony_ci expected_vertex.v = -1.0f; 1446e5c31af7Sopenharmony_ci expected_vertex.w = -1.0f; 1447e5c31af7Sopenharmony_ci 1448e5c31af7Sopenharmony_ci /* Make sure that for each vertex, the following language from the extension 1449e5c31af7Sopenharmony_ci * spec is followed: 1450e5c31af7Sopenharmony_ci */ 1451e5c31af7Sopenharmony_ci switch (test_iteration.primitive_mode) 1452e5c31af7Sopenharmony_ci { 1453e5c31af7Sopenharmony_ci case TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES: 1454e5c31af7Sopenharmony_ci { 1455e5c31af7Sopenharmony_ci /* For isoline tessellation, if it generates vertices at (0,x) and (1,x) 1456e5c31af7Sopenharmony_ci * where <x> is not zero, it will also generate vertices at exactly (0,1-x) 1457e5c31af7Sopenharmony_ci * and (1,1-x), respectively. 1458e5c31af7Sopenharmony_ci */ 1459e5c31af7Sopenharmony_ci if (vertex_data[0] == 0.0f && vertex_data[1] != 0.0f) 1460e5c31af7Sopenharmony_ci { 1461e5c31af7Sopenharmony_ci expected_vertex.u = vertex_data[0]; 1462e5c31af7Sopenharmony_ci expected_vertex.v = 1.0f - vertex_data[1]; 1463e5c31af7Sopenharmony_ci expected_vertex.w = -1.0f; 1464e5c31af7Sopenharmony_ci } 1465e5c31af7Sopenharmony_ci else if (vertex_data[0] == 1.0f && vertex_data[1] != 0.0f) 1466e5c31af7Sopenharmony_ci { 1467e5c31af7Sopenharmony_ci expected_vertex.u = vertex_data[0]; 1468e5c31af7Sopenharmony_ci expected_vertex.v = 1.0f - vertex_data[1]; 1469e5c31af7Sopenharmony_ci expected_vertex.w = -1.0f; 1470e5c31af7Sopenharmony_ci } 1471e5c31af7Sopenharmony_ci 1472e5c31af7Sopenharmony_ci break; 1473e5c31af7Sopenharmony_ci } /* case TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES: */ 1474e5c31af7Sopenharmony_ci 1475e5c31af7Sopenharmony_ci case TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS: 1476e5c31af7Sopenharmony_ci { 1477e5c31af7Sopenharmony_ci /* For quad tessellation, if the subdivision generates a vertex with 1478e5c31af7Sopenharmony_ci * coordinates of (x,0) or (0,x), it will also generate a vertex with 1479e5c31af7Sopenharmony_ci * coordinates of exactly (1-x,0) or (0,1-x), respectively. 1480e5c31af7Sopenharmony_ci */ 1481e5c31af7Sopenharmony_ci if (vertex_data[0] != 0.0f && vertex_data[1] == 0.0f) 1482e5c31af7Sopenharmony_ci { 1483e5c31af7Sopenharmony_ci expected_vertex.u = 1.0f - vertex_data[0]; 1484e5c31af7Sopenharmony_ci expected_vertex.v = vertex_data[1]; 1485e5c31af7Sopenharmony_ci expected_vertex.w = -1.0f; 1486e5c31af7Sopenharmony_ci } 1487e5c31af7Sopenharmony_ci else if (vertex_data[0] == 0.0f && vertex_data[1] != 0.0f) 1488e5c31af7Sopenharmony_ci { 1489e5c31af7Sopenharmony_ci expected_vertex.u = vertex_data[0]; 1490e5c31af7Sopenharmony_ci expected_vertex.v = 1.0f - vertex_data[1]; 1491e5c31af7Sopenharmony_ci expected_vertex.w = -1.0f; 1492e5c31af7Sopenharmony_ci } 1493e5c31af7Sopenharmony_ci 1494e5c31af7Sopenharmony_ci break; 1495e5c31af7Sopenharmony_ci } /* case TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS: */ 1496e5c31af7Sopenharmony_ci 1497e5c31af7Sopenharmony_ci case TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES: 1498e5c31af7Sopenharmony_ci { 1499e5c31af7Sopenharmony_ci /* For triangle tessellation, if the subdivision generates a vertex with 1500e5c31af7Sopenharmony_ci * tessellation coordinates of the form (0,x,1-x), (x,0,1-x), or (x,1-x,0), 1501e5c31af7Sopenharmony_ci * it will also generate a vertex with coordinates of exactly (0,1-x,x), 1502e5c31af7Sopenharmony_ci * (1-x,0,x), or (1-x,x,0), respectively. 1503e5c31af7Sopenharmony_ci */ 1504e5c31af7Sopenharmony_ci if (vertex_data[0] == 0.0f && vertex_data[1] != 0.0f && vertex_data[2] == (1.0f - vertex_data[1])) 1505e5c31af7Sopenharmony_ci { 1506e5c31af7Sopenharmony_ci expected_vertex.u = vertex_data[0]; 1507e5c31af7Sopenharmony_ci expected_vertex.v = vertex_data[2]; 1508e5c31af7Sopenharmony_ci expected_vertex.w = vertex_data[1]; 1509e5c31af7Sopenharmony_ci } 1510e5c31af7Sopenharmony_ci else if (vertex_data[0] != 0.0f && vertex_data[1] == 0.0f && vertex_data[2] == (1.0f - vertex_data[0])) 1511e5c31af7Sopenharmony_ci { 1512e5c31af7Sopenharmony_ci expected_vertex.u = vertex_data[2]; 1513e5c31af7Sopenharmony_ci expected_vertex.v = vertex_data[1]; 1514e5c31af7Sopenharmony_ci expected_vertex.w = vertex_data[0]; 1515e5c31af7Sopenharmony_ci } 1516e5c31af7Sopenharmony_ci else if (vertex_data[0] != 0.0f && vertex_data[1] == (1.0f - vertex_data[0]) && vertex_data[2] == 0.0f) 1517e5c31af7Sopenharmony_ci { 1518e5c31af7Sopenharmony_ci expected_vertex.u = vertex_data[1]; 1519e5c31af7Sopenharmony_ci expected_vertex.v = vertex_data[0]; 1520e5c31af7Sopenharmony_ci expected_vertex.w = vertex_data[2]; 1521e5c31af7Sopenharmony_ci } 1522e5c31af7Sopenharmony_ci 1523e5c31af7Sopenharmony_ci break; 1524e5c31af7Sopenharmony_ci } /* case TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES: */ 1525e5c31af7Sopenharmony_ci 1526e5c31af7Sopenharmony_ci default: 1527e5c31af7Sopenharmony_ci { 1528e5c31af7Sopenharmony_ci TCU_FAIL("Primitive mode unrecognized"); 1529e5c31af7Sopenharmony_ci } 1530e5c31af7Sopenharmony_ci } /* switch (test_iteration.primitive_mode) */ 1531e5c31af7Sopenharmony_ci 1532e5c31af7Sopenharmony_ci /* If any of the "expected vertex"'s components is no longer negative, 1533e5c31af7Sopenharmony_ci * make sure the vertex can be found in the result data */ 1534e5c31af7Sopenharmony_ci if (expected_vertex.u >= 0.0f || expected_vertex.v >= 0.0f || expected_vertex.w >= 0.0f) 1535e5c31af7Sopenharmony_ci { 1536e5c31af7Sopenharmony_ci bool has_been_found = false; 1537e5c31af7Sopenharmony_ci 1538e5c31af7Sopenharmony_ci for (unsigned int n_find_vertex = 0; n_find_vertex < test_iteration.n_vertices; ++n_find_vertex) 1539e5c31af7Sopenharmony_ci { 1540e5c31af7Sopenharmony_ci const glw::GLfloat* current_vertex_data = data_float + 3 /* components */ * n_find_vertex; 1541e5c31af7Sopenharmony_ci 1542e5c31af7Sopenharmony_ci const glw::GLfloat epsilon = 1e-4f; 1543e5c31af7Sopenharmony_ci glw::GLfloat absDelta[3] = { de::abs(current_vertex_data[0] - expected_vertex.u), 1544e5c31af7Sopenharmony_ci de::abs(current_vertex_data[1] - expected_vertex.v), 1545e5c31af7Sopenharmony_ci de::abs(current_vertex_data[2] - expected_vertex.w) }; 1546e5c31af7Sopenharmony_ci 1547e5c31af7Sopenharmony_ci if (absDelta[0] < epsilon && absDelta[1] < epsilon && 1548e5c31af7Sopenharmony_ci ((expected_vertex.w < 0.0f) || (expected_vertex.w >= 0.0f && absDelta[2] < epsilon))) 1549e5c31af7Sopenharmony_ci { 1550e5c31af7Sopenharmony_ci has_been_found = true; 1551e5c31af7Sopenharmony_ci 1552e5c31af7Sopenharmony_ci break; 1553e5c31af7Sopenharmony_ci } /* if (the vertex data matches the expected vertex data) */ 1554e5c31af7Sopenharmony_ci } /* for (all generated vertices)*/ 1555e5c31af7Sopenharmony_ci 1556e5c31af7Sopenharmony_ci if (!has_been_found) 1557e5c31af7Sopenharmony_ci { 1558e5c31af7Sopenharmony_ci TCU_FAIL("Expected symmetrical vertex data was not generated by the tessellator."); 1559e5c31af7Sopenharmony_ci } 1560e5c31af7Sopenharmony_ci } /* if (any of the components of expected_vertex is no longer negative) */ 1561e5c31af7Sopenharmony_ci } /* for (all generated vertices) */ 1562e5c31af7Sopenharmony_ci} 1563e5c31af7Sopenharmony_ci 1564e5c31af7Sopenharmony_ci/** Constructor. 1565e5c31af7Sopenharmony_ci * 1566e5c31af7Sopenharmony_ci * @param context Rendering context. 1567e5c31af7Sopenharmony_ci * 1568e5c31af7Sopenharmony_ci **/ 1569e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule4Test::TessellationShaderInvarianceRule4Test(Context& context, 1570e5c31af7Sopenharmony_ci const ExtParameters& extParams) 1571e5c31af7Sopenharmony_ci : TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule4", 1572e5c31af7Sopenharmony_ci "Verifies conformance with fourth invariance rule") 1573e5c31af7Sopenharmony_ci{ 1574e5c31af7Sopenharmony_ci} 1575e5c31af7Sopenharmony_ci 1576e5c31af7Sopenharmony_ci/** Destructor. */ 1577e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule4Test::~TessellationShaderInvarianceRule4Test() 1578e5c31af7Sopenharmony_ci{ 1579e5c31af7Sopenharmony_ci /* Left blank intentionally */ 1580e5c31af7Sopenharmony_ci} 1581e5c31af7Sopenharmony_ci 1582e5c31af7Sopenharmony_ci/** Retrieves amount of iterations the base test implementation should run before 1583e5c31af7Sopenharmony_ci * calling global verification routine. 1584e5c31af7Sopenharmony_ci * 1585e5c31af7Sopenharmony_ci * @return A value that depends on initTestIterations() behavior. 1586e5c31af7Sopenharmony_ci **/ 1587e5c31af7Sopenharmony_ciunsigned int TessellationShaderInvarianceRule4Test::getAmountOfIterations() 1588e5c31af7Sopenharmony_ci{ 1589e5c31af7Sopenharmony_ci if (m_test_iterations.size() == 0) 1590e5c31af7Sopenharmony_ci { 1591e5c31af7Sopenharmony_ci initTestIterations(); 1592e5c31af7Sopenharmony_ci } 1593e5c31af7Sopenharmony_ci 1594e5c31af7Sopenharmony_ci return (unsigned int)m_test_iterations.size(); 1595e5c31af7Sopenharmony_ci} 1596e5c31af7Sopenharmony_ci 1597e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation properties. 1598e5c31af7Sopenharmony_ci * 1599e5c31af7Sopenharmony_ci * @param n_iteration Iteration index to retrieve the properties for. 1600e5c31af7Sopenharmony_ci * @param out_inner_tess_levels Deref will be used to store iteration-specific inner 1601e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 1602e5c31af7Sopenharmony_ci * @param out_outer_tess_levels Deref will be used to store iteration-specific outer 1603e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 1604e5c31af7Sopenharmony_ci * @param out_point_mode Deref will be used to store iteration-specific flag 1605e5c31af7Sopenharmony_ci * telling whether point mode should be enabled for given pass. 1606e5c31af7Sopenharmony_ci * Must not be NULL. 1607e5c31af7Sopenharmony_ci * @param out_primitive_mode Deref will be used to store iteration-specific primitive 1608e5c31af7Sopenharmony_ci * mode. Must not be NULL. 1609e5c31af7Sopenharmony_ci * @param out_vertex_ordering Deref will be used to store iteration-specific vertex 1610e5c31af7Sopenharmony_ci * ordering. Must not be NULL. 1611e5c31af7Sopenharmony_ci * @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object 1612e5c31af7Sopenharmony_ci * storage should offer for the draw call to succeed. Can 1613e5c31af7Sopenharmony_ci * be NULL. 1614e5c31af7Sopenharmony_ci **/ 1615e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule4Test::getIterationProperties( 1616e5c31af7Sopenharmony_ci unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode, 1617e5c31af7Sopenharmony_ci _tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering, 1618e5c31af7Sopenharmony_ci unsigned int* out_result_buffer_size) 1619e5c31af7Sopenharmony_ci{ 1620e5c31af7Sopenharmony_ci DE_ASSERT(m_test_iterations.size() > n_iteration); 1621e5c31af7Sopenharmony_ci 1622e5c31af7Sopenharmony_ci _test_iteration& test_iteration = m_test_iterations[n_iteration]; 1623e5c31af7Sopenharmony_ci 1624e5c31af7Sopenharmony_ci memcpy(out_inner_tess_levels, test_iteration.inner_tess_levels, sizeof(test_iteration.inner_tess_levels)); 1625e5c31af7Sopenharmony_ci memcpy(out_outer_tess_levels, test_iteration.outer_tess_levels, sizeof(test_iteration.outer_tess_levels)); 1626e5c31af7Sopenharmony_ci 1627e5c31af7Sopenharmony_ci *out_point_mode = false; 1628e5c31af7Sopenharmony_ci *out_primitive_mode = test_iteration.primitive_mode; 1629e5c31af7Sopenharmony_ci *out_vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_CCW; 1630e5c31af7Sopenharmony_ci 1631e5c31af7Sopenharmony_ci if (out_result_buffer_size != DE_NULL) 1632e5c31af7Sopenharmony_ci { 1633e5c31af7Sopenharmony_ci *out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator( 1634e5c31af7Sopenharmony_ci *out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, test_iteration.vertex_spacing, 1635e5c31af7Sopenharmony_ci *out_point_mode); 1636e5c31af7Sopenharmony_ci test_iteration.n_vertices = *out_result_buffer_size; 1637e5c31af7Sopenharmony_ci *out_result_buffer_size = 1638e5c31af7Sopenharmony_ci static_cast<unsigned int>(*out_result_buffer_size * 3 /* components */ * sizeof(float)); 1639e5c31af7Sopenharmony_ci 1640e5c31af7Sopenharmony_ci DE_ASSERT(*out_result_buffer_size != 0); 1641e5c31af7Sopenharmony_ci } 1642e5c31af7Sopenharmony_ci} 1643e5c31af7Sopenharmony_ci 1644e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation evaluation shader code. 1645e5c31af7Sopenharmony_ci * 1646e5c31af7Sopenharmony_ci * @param n_iteration Iteration index, for which the source code is being obtained. 1647e5c31af7Sopenharmony_ci * 1648e5c31af7Sopenharmony_ci * @return Requested source code. 1649e5c31af7Sopenharmony_ci **/ 1650e5c31af7Sopenharmony_cistd::string TessellationShaderInvarianceRule4Test::getTECode(unsigned int n_iteration) 1651e5c31af7Sopenharmony_ci{ 1652e5c31af7Sopenharmony_ci DE_ASSERT(m_test_iterations.size() > n_iteration); 1653e5c31af7Sopenharmony_ci 1654e5c31af7Sopenharmony_ci const _test_iteration& test_iteration = m_test_iterations[n_iteration]; 1655e5c31af7Sopenharmony_ci 1656e5c31af7Sopenharmony_ci return TessellationShaderUtils::getGenericTECode(test_iteration.vertex_spacing, test_iteration.primitive_mode, 1657e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_ORDERING_CCW, false); /* point mode */ 1658e5c31af7Sopenharmony_ci} 1659e5c31af7Sopenharmony_ci 1660e5c31af7Sopenharmony_ci/** Initializes test iterations for the test. The following modes and inner/outer tess level 1661e5c31af7Sopenharmony_ci * configurations are used to form the test set: 1662e5c31af7Sopenharmony_ci * 1663e5c31af7Sopenharmony_ci * - Inner/outer tessellation level combinations as returned by 1664e5c31af7Sopenharmony_ci * TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode() 1665e5c31af7Sopenharmony_ci * - 'Quads' and 'Triangles' primitive modes; 1666e5c31af7Sopenharmony_ci * - All vertex spacing modes; 1667e5c31af7Sopenharmony_ci * 1668e5c31af7Sopenharmony_ci * All permutations are used to generate the test set. 1669e5c31af7Sopenharmony_ci **/ 1670e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule4Test::initTestIterations() 1671e5c31af7Sopenharmony_ci{ 1672e5c31af7Sopenharmony_ci DE_ASSERT(m_test_iterations.size() == 0); 1673e5c31af7Sopenharmony_ci 1674e5c31af7Sopenharmony_ci /* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */ 1675e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1676e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_gen_level_value = 0; 1677e5c31af7Sopenharmony_ci 1678e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value); 1679e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 1680e5c31af7Sopenharmony_ci 1681e5c31af7Sopenharmony_ci /* Iterate through all primitive and vertex spacing modes relevant to the test */ 1682e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, 1683e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES }; 1684e5c31af7Sopenharmony_ci _tessellation_shader_vertex_spacing vs_modes[] = { TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 1685e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN, 1686e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD }; 1687e5c31af7Sopenharmony_ci 1688e5c31af7Sopenharmony_ci const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]); 1689e5c31af7Sopenharmony_ci const unsigned int n_vs_modes = sizeof(vs_modes) / sizeof(vs_modes[0]); 1690e5c31af7Sopenharmony_ci 1691e5c31af7Sopenharmony_ci for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode) 1692e5c31af7Sopenharmony_ci { 1693e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode]; 1694e5c31af7Sopenharmony_ci 1695e5c31af7Sopenharmony_ci for (unsigned int n_vs_mode = 0; n_vs_mode < n_vs_modes; ++n_vs_mode) 1696e5c31af7Sopenharmony_ci { 1697e5c31af7Sopenharmony_ci _tessellation_shader_vertex_spacing vs_mode = vs_modes[n_vs_mode]; 1698e5c31af7Sopenharmony_ci 1699e5c31af7Sopenharmony_ci /* Retrieve inner/outer tessellation level combinations we want the tests to be run for */ 1700e5c31af7Sopenharmony_ci _tessellation_levels_set levels; 1701e5c31af7Sopenharmony_ci 1702e5c31af7Sopenharmony_ci levels = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode( 1703e5c31af7Sopenharmony_ci primitive_mode, gl_max_tess_gen_level_value, 1704e5c31af7Sopenharmony_ci TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE); 1705e5c31af7Sopenharmony_ci 1706e5c31af7Sopenharmony_ci /* Iterate through all configurations */ 1707e5c31af7Sopenharmony_ci for (_tessellation_levels_set_const_iterator levels_iterator = levels.begin(); 1708e5c31af7Sopenharmony_ci levels_iterator != levels.end(); levels_iterator++) 1709e5c31af7Sopenharmony_ci { 1710e5c31af7Sopenharmony_ci const _tessellation_levels& current_levels = *levels_iterator; 1711e5c31af7Sopenharmony_ci 1712e5c31af7Sopenharmony_ci /* Create a test descriptor for all the parameters we now have. 1713e5c31af7Sopenharmony_ci * 1714e5c31af7Sopenharmony_ci * The set we're operating on uses different outer tessellation level values, so we 1715e5c31af7Sopenharmony_ci * need to make sure the levels are set to the same FP values in order for the test 1716e5c31af7Sopenharmony_ci * to succeed. */ 1717e5c31af7Sopenharmony_ci _test_iteration test; 1718e5c31af7Sopenharmony_ci 1719e5c31af7Sopenharmony_ci memcpy(test.inner_tess_levels, current_levels.inner, sizeof(test.inner_tess_levels)); 1720e5c31af7Sopenharmony_ci 1721e5c31af7Sopenharmony_ci for (int n = 0; n < 4 /* outer tess levels */; ++n) 1722e5c31af7Sopenharmony_ci { 1723e5c31af7Sopenharmony_ci test.outer_tess_levels[n] = current_levels.outer[0]; 1724e5c31af7Sopenharmony_ci } 1725e5c31af7Sopenharmony_ci 1726e5c31af7Sopenharmony_ci test.primitive_mode = primitive_mode; 1727e5c31af7Sopenharmony_ci test.vertex_spacing = vs_mode; 1728e5c31af7Sopenharmony_ci 1729e5c31af7Sopenharmony_ci m_test_iterations.push_back(test); 1730e5c31af7Sopenharmony_ci } /* for (all inner/outer tessellation levels) */ 1731e5c31af7Sopenharmony_ci } /* for (all vertex spacing modes) */ 1732e5c31af7Sopenharmony_ci } /* for (all primitive modes) */ 1733e5c31af7Sopenharmony_ci} 1734e5c31af7Sopenharmony_ci 1735e5c31af7Sopenharmony_ci/** Verifies user-provided vertex data can be found in the provided vertex data array. 1736e5c31af7Sopenharmony_ci * 1737e5c31af7Sopenharmony_ci * @param vertex_data Vertex data array the requested vertex data are to be found in. 1738e5c31af7Sopenharmony_ci * @param n_vertices Amount of vertices declared in @param vertex_data; 1739e5c31af7Sopenharmony_ci * @param vertex_data_seeked Vertex data to be found in @param vertex_data; 1740e5c31af7Sopenharmony_ci * @param n_vertex_data_seeked_components Amount of components to take into account. 1741e5c31af7Sopenharmony_ci * 1742e5c31af7Sopenharmony_ci * @return true if the vertex data was found, false otherwise. 1743e5c31af7Sopenharmony_ci **/ 1744e5c31af7Sopenharmony_cibool TessellationShaderInvarianceRule4Test::isVertexDefined(const float* vertex_data, unsigned int n_vertices, 1745e5c31af7Sopenharmony_ci const float* vertex_data_seeked, 1746e5c31af7Sopenharmony_ci unsigned int n_vertex_data_seeked_components) 1747e5c31af7Sopenharmony_ci{ 1748e5c31af7Sopenharmony_ci bool result = false; 1749e5c31af7Sopenharmony_ci 1750e5c31af7Sopenharmony_ci DE_ASSERT(n_vertex_data_seeked_components >= 2); 1751e5c31af7Sopenharmony_ci 1752e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < n_vertices; ++n_vertex) 1753e5c31af7Sopenharmony_ci { 1754e5c31af7Sopenharmony_ci const float* current_vertex_data = vertex_data + 3 /* components */ * n_vertex; 1755e5c31af7Sopenharmony_ci 1756e5c31af7Sopenharmony_ci if ((vertex_data_seeked[0] == current_vertex_data[0]) && (vertex_data_seeked[1] == current_vertex_data[1]) && 1757e5c31af7Sopenharmony_ci ((n_vertex_data_seeked_components < 3) || 1758e5c31af7Sopenharmony_ci (n_vertex_data_seeked_components >= 3 && (vertex_data_seeked[2] == current_vertex_data[2])))) 1759e5c31af7Sopenharmony_ci { 1760e5c31af7Sopenharmony_ci result = true; 1761e5c31af7Sopenharmony_ci 1762e5c31af7Sopenharmony_ci break; 1763e5c31af7Sopenharmony_ci } /* if (components match) */ 1764e5c31af7Sopenharmony_ci } /* for (all vertices) */ 1765e5c31af7Sopenharmony_ci 1766e5c31af7Sopenharmony_ci return result; 1767e5c31af7Sopenharmony_ci} 1768e5c31af7Sopenharmony_ci 1769e5c31af7Sopenharmony_ci/** Verifies result data on per-iteration basis. 1770e5c31af7Sopenharmony_ci * 1771e5c31af7Sopenharmony_ci * Throws TestError exception if an error occurs. 1772e5c31af7Sopenharmony_ci * 1773e5c31af7Sopenharmony_ci * @param n_iteration Index of iteration the check should be performed for. 1774e5c31af7Sopenharmony_ci * @param data Points to array of vec3s storing the vertices as 1775e5c31af7Sopenharmony_ci * generated by tessellation 1776e5c31af7Sopenharmony_ci **/ 1777e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule4Test::verifyResultDataForIteration(unsigned int n_iteration, const void* data) 1778e5c31af7Sopenharmony_ci{ 1779e5c31af7Sopenharmony_ci DE_ASSERT(m_test_iterations.size() > n_iteration); 1780e5c31af7Sopenharmony_ci 1781e5c31af7Sopenharmony_ci const glw::GLfloat* data_float = (const glw::GLfloat*)data; 1782e5c31af7Sopenharmony_ci const _test_iteration& test_iteration = m_test_iterations[n_iteration]; 1783e5c31af7Sopenharmony_ci 1784e5c31af7Sopenharmony_ci /* Iterate through all generated vertices.. */ 1785e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < test_iteration.n_vertices; ++n_vertex) 1786e5c31af7Sopenharmony_ci { 1787e5c31af7Sopenharmony_ci std::vector<_vertex> expected_vertices; 1788e5c31af7Sopenharmony_ci const glw::GLfloat* vertex_data = data_float + 3 /* components */ * n_vertex; 1789e5c31af7Sopenharmony_ci 1790e5c31af7Sopenharmony_ci /* Make sure that for each vertex, the following language from the extension 1791e5c31af7Sopenharmony_ci * spec is followed: 1792e5c31af7Sopenharmony_ci */ 1793e5c31af7Sopenharmony_ci switch (test_iteration.primitive_mode) 1794e5c31af7Sopenharmony_ci { 1795e5c31af7Sopenharmony_ci case TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS: 1796e5c31af7Sopenharmony_ci { 1797e5c31af7Sopenharmony_ci /* For quad tessellation, if vertices at (x,0) and (1-x,0) are generated 1798e5c31af7Sopenharmony_ci * when subdividing the v==0 edge, vertices must be generated at (0,x) and 1799e5c31af7Sopenharmony_ci * (0,1-x) when subdividing an otherwise identical u==0 edge. 1800e5c31af7Sopenharmony_ci */ 1801e5c31af7Sopenharmony_ci if (vertex_data[0] != 0.0f && vertex_data[1] == 0.0f) 1802e5c31af7Sopenharmony_ci { 1803e5c31af7Sopenharmony_ci const float paired_vertex_data[] = { 1.0f - vertex_data[0], vertex_data[1] }; 1804e5c31af7Sopenharmony_ci 1805e5c31af7Sopenharmony_ci if (isVertexDefined(data_float, test_iteration.n_vertices, paired_vertex_data, 2)) /* components */ 1806e5c31af7Sopenharmony_ci { 1807e5c31af7Sopenharmony_ci _vertex expected_vertex; 1808e5c31af7Sopenharmony_ci 1809e5c31af7Sopenharmony_ci /* First expected vertex */ 1810e5c31af7Sopenharmony_ci expected_vertex.u = vertex_data[1]; 1811e5c31af7Sopenharmony_ci expected_vertex.v = vertex_data[0]; 1812e5c31af7Sopenharmony_ci expected_vertex.w = -1.0f; 1813e5c31af7Sopenharmony_ci 1814e5c31af7Sopenharmony_ci expected_vertices.push_back(expected_vertex); 1815e5c31af7Sopenharmony_ci 1816e5c31af7Sopenharmony_ci /* The other expected vertex */ 1817e5c31af7Sopenharmony_ci expected_vertex.u = vertex_data[1]; 1818e5c31af7Sopenharmony_ci expected_vertex.v = 1.0f - vertex_data[0]; 1819e5c31af7Sopenharmony_ci 1820e5c31af7Sopenharmony_ci expected_vertices.push_back(expected_vertex); 1821e5c31af7Sopenharmony_ci } /* if (the other required vertex is defined) */ 1822e5c31af7Sopenharmony_ci } /* if (the first required vertex is defined) */ 1823e5c31af7Sopenharmony_ci 1824e5c31af7Sopenharmony_ci break; 1825e5c31af7Sopenharmony_ci } /* case TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS: */ 1826e5c31af7Sopenharmony_ci 1827e5c31af7Sopenharmony_ci case TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES: 1828e5c31af7Sopenharmony_ci { 1829e5c31af7Sopenharmony_ci /* For triangular tessellation, if vertices at (x,1-x,0) and (1-x,x,0) are 1830e5c31af7Sopenharmony_ci * generated when subdividing the w==0 edge, vertices must be generated at 1831e5c31af7Sopenharmony_ci * (x,0,1-x) and (1-x,0,x) when subdividing an otherwise identical v==0 1832e5c31af7Sopenharmony_ci * edge. 1833e5c31af7Sopenharmony_ci */ 1834e5c31af7Sopenharmony_ci if (vertex_data[0] != 0.0f && vertex_data[1] == (1.0f - vertex_data[0]) && vertex_data[2] == 0) 1835e5c31af7Sopenharmony_ci { 1836e5c31af7Sopenharmony_ci const float paired_vertex_data[] = { vertex_data[1], vertex_data[0], vertex_data[2] }; 1837e5c31af7Sopenharmony_ci 1838e5c31af7Sopenharmony_ci if (isVertexDefined(data_float, test_iteration.n_vertices, paired_vertex_data, 3)) /* components */ 1839e5c31af7Sopenharmony_ci { 1840e5c31af7Sopenharmony_ci _vertex expected_vertex; 1841e5c31af7Sopenharmony_ci 1842e5c31af7Sopenharmony_ci /* First expected vertex */ 1843e5c31af7Sopenharmony_ci expected_vertex.u = vertex_data[0]; 1844e5c31af7Sopenharmony_ci expected_vertex.v = vertex_data[2]; 1845e5c31af7Sopenharmony_ci expected_vertex.w = vertex_data[1]; 1846e5c31af7Sopenharmony_ci 1847e5c31af7Sopenharmony_ci expected_vertices.push_back(expected_vertex); 1848e5c31af7Sopenharmony_ci 1849e5c31af7Sopenharmony_ci /* The other expected vertex */ 1850e5c31af7Sopenharmony_ci expected_vertex.u = vertex_data[1]; 1851e5c31af7Sopenharmony_ci expected_vertex.v = vertex_data[2]; 1852e5c31af7Sopenharmony_ci expected_vertex.w = vertex_data[0]; 1853e5c31af7Sopenharmony_ci 1854e5c31af7Sopenharmony_ci expected_vertices.push_back(expected_vertex); 1855e5c31af7Sopenharmony_ci } /* if (the other required vertex is defined) */ 1856e5c31af7Sopenharmony_ci } /* if (the firsst required vertex is defined) */ 1857e5c31af7Sopenharmony_ci 1858e5c31af7Sopenharmony_ci break; 1859e5c31af7Sopenharmony_ci } /* case TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES: */ 1860e5c31af7Sopenharmony_ci 1861e5c31af7Sopenharmony_ci default: 1862e5c31af7Sopenharmony_ci { 1863e5c31af7Sopenharmony_ci TCU_FAIL("Primitive mode unrecognized"); 1864e5c31af7Sopenharmony_ci } 1865e5c31af7Sopenharmony_ci } /* switch (test_iteration.primitive_mode) */ 1866e5c31af7Sopenharmony_ci 1867e5c31af7Sopenharmony_ci /* Iterate through all expected vertices */ 1868e5c31af7Sopenharmony_ci for (std::vector<_vertex>::const_iterator expected_vertex_iterator = expected_vertices.begin(); 1869e5c31af7Sopenharmony_ci expected_vertex_iterator != expected_vertices.end(); expected_vertex_iterator++) 1870e5c31af7Sopenharmony_ci { 1871e5c31af7Sopenharmony_ci const _vertex& expected_vertex = *expected_vertex_iterator; 1872e5c31af7Sopenharmony_ci const float expected_vertex_raw[] = { expected_vertex.u, expected_vertex.v, expected_vertex.w }; 1873e5c31af7Sopenharmony_ci bool has_been_found = false; 1874e5c31af7Sopenharmony_ci 1875e5c31af7Sopenharmony_ci has_been_found = isVertexDefined(data_float, test_iteration.n_vertices, expected_vertex_raw, 1876e5c31af7Sopenharmony_ci (expected_vertex.w < 0) ? 2 : 3); 1877e5c31af7Sopenharmony_ci 1878e5c31af7Sopenharmony_ci if (!has_been_found) 1879e5c31af7Sopenharmony_ci { 1880e5c31af7Sopenharmony_ci std::stringstream expected_vertex_sstream; 1881e5c31af7Sopenharmony_ci 1882e5c31af7Sopenharmony_ci expected_vertex_sstream << expected_vertex.u << ", " << expected_vertex.v; 1883e5c31af7Sopenharmony_ci 1884e5c31af7Sopenharmony_ci if (expected_vertex.w >= 0.0f) 1885e5c31af7Sopenharmony_ci { 1886e5c31af7Sopenharmony_ci expected_vertex_sstream << ", " << expected_vertex.w; 1887e5c31af7Sopenharmony_ci } 1888e5c31af7Sopenharmony_ci 1889e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "For primitive mode:" 1890e5c31af7Sopenharmony_ci << "[" 1891e5c31af7Sopenharmony_ci << TessellationShaderUtils::getESTokenForPrimitiveMode(test_iteration.primitive_mode) 1892e5c31af7Sopenharmony_ci << "]" 1893e5c31af7Sopenharmony_ci << "and vertex spacing mode:" 1894e5c31af7Sopenharmony_ci << "[" << TessellationShaderUtils::getESTokenForVertexSpacingMode( 1895e5c31af7Sopenharmony_ci test_iteration.vertex_spacing) 1896e5c31af7Sopenharmony_ci << "]" 1897e5c31af7Sopenharmony_ci << " and inner tessellation levels:[" << test_iteration.inner_tess_levels[0] << ", " 1898e5c31af7Sopenharmony_ci << test_iteration.inner_tess_levels[1] << ") " 1899e5c31af7Sopenharmony_ci << " and outer tessellation levels:[" << test_iteration.outer_tess_levels[0] << ", " 1900e5c31af7Sopenharmony_ci << test_iteration.outer_tess_levels[1] << ", " << test_iteration.outer_tess_levels[2] 1901e5c31af7Sopenharmony_ci << ", " << test_iteration.outer_tess_levels[3] << ") " 1902e5c31af7Sopenharmony_ci << " the following vertex was expected:[" << expected_vertex_sstream.str().c_str() 1903e5c31af7Sopenharmony_ci << "] but was not found in the tessellated cooordinate data set" 1904e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1905e5c31af7Sopenharmony_ci 1906e5c31af7Sopenharmony_ci TCU_FAIL("Expected symmetrical vertex data was not generated by the tessellator."); 1907e5c31af7Sopenharmony_ci } /* if (the expected vertex data was not found) */ 1908e5c31af7Sopenharmony_ci } /* for (all expected vertices) */ 1909e5c31af7Sopenharmony_ci } /* for (all generated vertices) */ 1910e5c31af7Sopenharmony_ci} 1911e5c31af7Sopenharmony_ci 1912e5c31af7Sopenharmony_ci/** Constructor. 1913e5c31af7Sopenharmony_ci * 1914e5c31af7Sopenharmony_ci * @param context Rendering context. 1915e5c31af7Sopenharmony_ci * 1916e5c31af7Sopenharmony_ci **/ 1917e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule5Test::TessellationShaderInvarianceRule5Test(Context& context, 1918e5c31af7Sopenharmony_ci const ExtParameters& extParams) 1919e5c31af7Sopenharmony_ci : TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule5", 1920e5c31af7Sopenharmony_ci "Verifies conformance with fifth invariance rule") 1921e5c31af7Sopenharmony_ci{ 1922e5c31af7Sopenharmony_ci} 1923e5c31af7Sopenharmony_ci 1924e5c31af7Sopenharmony_ci/** Destructor. */ 1925e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule5Test::~TessellationShaderInvarianceRule5Test() 1926e5c31af7Sopenharmony_ci{ 1927e5c31af7Sopenharmony_ci /* Left blank intentionally */ 1928e5c31af7Sopenharmony_ci} 1929e5c31af7Sopenharmony_ci 1930e5c31af7Sopenharmony_ci/** Retrieves amount of iterations the base test implementation should run before 1931e5c31af7Sopenharmony_ci * calling global verification routine. 1932e5c31af7Sopenharmony_ci * 1933e5c31af7Sopenharmony_ci * @return A value that depends on initTestIterations() behavior. 1934e5c31af7Sopenharmony_ci **/ 1935e5c31af7Sopenharmony_ciunsigned int TessellationShaderInvarianceRule5Test::getAmountOfIterations() 1936e5c31af7Sopenharmony_ci{ 1937e5c31af7Sopenharmony_ci if (m_test_quads_iterations.size() == 0 || m_test_triangles_iterations.size() == 0) 1938e5c31af7Sopenharmony_ci { 1939e5c31af7Sopenharmony_ci initTestIterations(); 1940e5c31af7Sopenharmony_ci } 1941e5c31af7Sopenharmony_ci 1942e5c31af7Sopenharmony_ci return (unsigned int)(m_test_quads_iterations.size() + m_test_triangles_iterations.size()); 1943e5c31af7Sopenharmony_ci} 1944e5c31af7Sopenharmony_ci 1945e5c31af7Sopenharmony_ci/** Retrieves _test_iteration instance specific for user-specified iteration index. 1946e5c31af7Sopenharmony_ci * 1947e5c31af7Sopenharmony_ci * @param n_iteration Iteration index to retrieve _test_iteration instance for. 1948e5c31af7Sopenharmony_ci * 1949e5c31af7Sopenharmony_ci * @return Iteration-specific _test_iteration instance. 1950e5c31af7Sopenharmony_ci * 1951e5c31af7Sopenharmony_ci **/ 1952e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule5Test::_test_iteration& TessellationShaderInvarianceRule5Test::getTestForIteration( 1953e5c31af7Sopenharmony_ci unsigned int n_iteration) 1954e5c31af7Sopenharmony_ci{ 1955e5c31af7Sopenharmony_ci unsigned int n_triangles_tests = (unsigned int)m_test_triangles_iterations.size(); 1956e5c31af7Sopenharmony_ci _test_iteration& test_iteration = (n_iteration < n_triangles_tests) ? 1957e5c31af7Sopenharmony_ci m_test_triangles_iterations[n_iteration] : 1958e5c31af7Sopenharmony_ci m_test_quads_iterations[n_iteration - n_triangles_tests]; 1959e5c31af7Sopenharmony_ci 1960e5c31af7Sopenharmony_ci return test_iteration; 1961e5c31af7Sopenharmony_ci} 1962e5c31af7Sopenharmony_ci 1963e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation properties. 1964e5c31af7Sopenharmony_ci * 1965e5c31af7Sopenharmony_ci * @param n_iteration Iteration index to retrieve the properties for. 1966e5c31af7Sopenharmony_ci * @param out_inner_tess_levels Deref will be used to store iteration-specific inner 1967e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 1968e5c31af7Sopenharmony_ci * @param out_outer_tess_levels Deref will be used to store iteration-specific outer 1969e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 1970e5c31af7Sopenharmony_ci * @param out_point_mode Deref will be used to store iteration-specific flag 1971e5c31af7Sopenharmony_ci * telling whether point mode should be enabled for given pass. 1972e5c31af7Sopenharmony_ci * Must not be NULL. 1973e5c31af7Sopenharmony_ci * @param out_primitive_mode Deref will be used to store iteration-specific primitive 1974e5c31af7Sopenharmony_ci * mode. Must not be NULL. 1975e5c31af7Sopenharmony_ci * @param out_vertex_ordering Deref will be used to store iteration-specific vertex 1976e5c31af7Sopenharmony_ci * ordering. Must not be NULL. 1977e5c31af7Sopenharmony_ci * @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object 1978e5c31af7Sopenharmony_ci * storage should offer for the draw call to succeed. Can 1979e5c31af7Sopenharmony_ci * be NULL. 1980e5c31af7Sopenharmony_ci **/ 1981e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule5Test::getIterationProperties( 1982e5c31af7Sopenharmony_ci unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode, 1983e5c31af7Sopenharmony_ci _tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering, 1984e5c31af7Sopenharmony_ci unsigned int* out_result_buffer_size) 1985e5c31af7Sopenharmony_ci{ 1986e5c31af7Sopenharmony_ci DE_ASSERT(m_test_triangles_iterations.size() + m_test_quads_iterations.size() > n_iteration); 1987e5c31af7Sopenharmony_ci 1988e5c31af7Sopenharmony_ci _test_iteration& test_iteration = getTestForIteration(n_iteration); 1989e5c31af7Sopenharmony_ci 1990e5c31af7Sopenharmony_ci memcpy(out_inner_tess_levels, test_iteration.inner_tess_levels, sizeof(test_iteration.inner_tess_levels)); 1991e5c31af7Sopenharmony_ci memcpy(out_outer_tess_levels, test_iteration.outer_tess_levels, sizeof(test_iteration.outer_tess_levels)); 1992e5c31af7Sopenharmony_ci 1993e5c31af7Sopenharmony_ci *out_point_mode = false; 1994e5c31af7Sopenharmony_ci *out_primitive_mode = test_iteration.primitive_mode; 1995e5c31af7Sopenharmony_ci *out_vertex_ordering = test_iteration.vertex_ordering; 1996e5c31af7Sopenharmony_ci 1997e5c31af7Sopenharmony_ci if (out_result_buffer_size != DE_NULL) 1998e5c31af7Sopenharmony_ci { 1999e5c31af7Sopenharmony_ci *out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator( 2000e5c31af7Sopenharmony_ci *out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 2001e5c31af7Sopenharmony_ci *out_point_mode); 2002e5c31af7Sopenharmony_ci test_iteration.n_vertices = *out_result_buffer_size; 2003e5c31af7Sopenharmony_ci *out_result_buffer_size = 2004e5c31af7Sopenharmony_ci static_cast<unsigned int>(*out_result_buffer_size * 3 /* components */ * sizeof(float)); 2005e5c31af7Sopenharmony_ci 2006e5c31af7Sopenharmony_ci DE_ASSERT(*out_result_buffer_size != 0); 2007e5c31af7Sopenharmony_ci } 2008e5c31af7Sopenharmony_ci} 2009e5c31af7Sopenharmony_ci 2010e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation evaluation shader code. 2011e5c31af7Sopenharmony_ci * 2012e5c31af7Sopenharmony_ci * @param n_iteration Iteration index, for which the source code is being obtained. 2013e5c31af7Sopenharmony_ci * 2014e5c31af7Sopenharmony_ci * @return Requested source code. 2015e5c31af7Sopenharmony_ci **/ 2016e5c31af7Sopenharmony_cistd::string TessellationShaderInvarianceRule5Test::getTECode(unsigned int n_iteration) 2017e5c31af7Sopenharmony_ci{ 2018e5c31af7Sopenharmony_ci DE_ASSERT(m_test_triangles_iterations.size() + m_test_quads_iterations.size() > n_iteration); 2019e5c31af7Sopenharmony_ci 2020e5c31af7Sopenharmony_ci const _test_iteration& test_iteration = getTestForIteration(n_iteration); 2021e5c31af7Sopenharmony_ci 2022e5c31af7Sopenharmony_ci return TessellationShaderUtils::getGenericTECode(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 2023e5c31af7Sopenharmony_ci test_iteration.primitive_mode, test_iteration.vertex_ordering, 2024e5c31af7Sopenharmony_ci false); /* point mode */ 2025e5c31af7Sopenharmony_ci} 2026e5c31af7Sopenharmony_ci 2027e5c31af7Sopenharmony_ci/** Initializes test iterations for the test. The following modes and inner/outer tess level 2028e5c31af7Sopenharmony_ci * configurations are used to form the test set: 2029e5c31af7Sopenharmony_ci * 2030e5c31af7Sopenharmony_ci * - Last inner/outer tessellation level combination as returned by 2031e5c31af7Sopenharmony_ci * TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode() 2032e5c31af7Sopenharmony_ci * - All primitive modes; 2033e5c31af7Sopenharmony_ci * - All vertex spacing modes; 2034e5c31af7Sopenharmony_ci * 2035e5c31af7Sopenharmony_ci * All permutations are used to generate the test set. 2036e5c31af7Sopenharmony_ci **/ 2037e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule5Test::initTestIterations() 2038e5c31af7Sopenharmony_ci{ 2039e5c31af7Sopenharmony_ci DE_ASSERT(m_test_quads_iterations.size() == 0 && m_test_triangles_iterations.size() == 0); 2040e5c31af7Sopenharmony_ci 2041e5c31af7Sopenharmony_ci /* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */ 2042e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2043e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_gen_level_value = 0; 2044e5c31af7Sopenharmony_ci 2045e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value); 2046e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 2047e5c31af7Sopenharmony_ci 2048e5c31af7Sopenharmony_ci /* Iterate through all primitive and vertex spacing modes relevant to the test */ 2049e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, 2050e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES }; 2051e5c31af7Sopenharmony_ci _tessellation_shader_vertex_ordering vo_modes[] = { 2052e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_ORDERING_CCW, TESSELLATION_SHADER_VERTEX_ORDERING_CW, 2053e5c31af7Sopenharmony_ci }; 2054e5c31af7Sopenharmony_ci 2055e5c31af7Sopenharmony_ci const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]); 2056e5c31af7Sopenharmony_ci const unsigned int n_vo_modes = sizeof(vo_modes) / sizeof(vo_modes[0]); 2057e5c31af7Sopenharmony_ci 2058e5c31af7Sopenharmony_ci for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode) 2059e5c31af7Sopenharmony_ci { 2060e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode]; 2061e5c31af7Sopenharmony_ci 2062e5c31af7Sopenharmony_ci for (unsigned int n_vo_mode = 0; n_vo_mode < n_vo_modes; ++n_vo_mode) 2063e5c31af7Sopenharmony_ci { 2064e5c31af7Sopenharmony_ci _tessellation_shader_vertex_ordering vertex_ordering = vo_modes[n_vo_mode]; 2065e5c31af7Sopenharmony_ci 2066e5c31af7Sopenharmony_ci /* Retrieve inner/outer tessellation level combinations we want the tests to be run for */ 2067e5c31af7Sopenharmony_ci _tessellation_levels_set levels_set; 2068e5c31af7Sopenharmony_ci 2069e5c31af7Sopenharmony_ci levels_set = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode( 2070e5c31af7Sopenharmony_ci primitive_mode, gl_max_tess_gen_level_value, 2071e5c31af7Sopenharmony_ci TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE); 2072e5c31af7Sopenharmony_ci 2073e5c31af7Sopenharmony_ci /* Only use the last inner/outer level configuration, as reported by the utils function. */ 2074e5c31af7Sopenharmony_ci const _tessellation_levels& levels = levels_set[levels_set.size() - 1]; 2075e5c31af7Sopenharmony_ci 2076e5c31af7Sopenharmony_ci /* Create a test descriptor for all the parameters we now have */ 2077e5c31af7Sopenharmony_ci _test_iteration test; 2078e5c31af7Sopenharmony_ci 2079e5c31af7Sopenharmony_ci memcpy(test.inner_tess_levels, levels.inner, sizeof(test.inner_tess_levels)); 2080e5c31af7Sopenharmony_ci memcpy(test.outer_tess_levels, levels.outer, sizeof(test.outer_tess_levels)); 2081e5c31af7Sopenharmony_ci 2082e5c31af7Sopenharmony_ci test.primitive_mode = primitive_mode; 2083e5c31af7Sopenharmony_ci test.vertex_ordering = vertex_ordering; 2084e5c31af7Sopenharmony_ci 2085e5c31af7Sopenharmony_ci if (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES) 2086e5c31af7Sopenharmony_ci { 2087e5c31af7Sopenharmony_ci m_test_triangles_iterations.push_back(test); 2088e5c31af7Sopenharmony_ci } 2089e5c31af7Sopenharmony_ci else 2090e5c31af7Sopenharmony_ci { 2091e5c31af7Sopenharmony_ci m_test_quads_iterations.push_back(test); 2092e5c31af7Sopenharmony_ci } 2093e5c31af7Sopenharmony_ci } /* for (all vertex spacing modes) */ 2094e5c31af7Sopenharmony_ci } /* for (all primitive modes) */ 2095e5c31af7Sopenharmony_ci} 2096e5c31af7Sopenharmony_ci 2097e5c31af7Sopenharmony_ci/** Verifies user-provided vertex data can be found in the provided vertex data array. 2098e5c31af7Sopenharmony_ci * 2099e5c31af7Sopenharmony_ci * @param vertex_data Vertex data array the requested vertex data are to be found in. 2100e5c31af7Sopenharmony_ci * @param n_vertices Amount of vertices declared in @param vertex_data; 2101e5c31af7Sopenharmony_ci * @param vertex_data_seeked Vertex data to be found in @param vertex_data; 2102e5c31af7Sopenharmony_ci * @param n_vertex_data_seeked_components Amount of components to take into account. 2103e5c31af7Sopenharmony_ci * 2104e5c31af7Sopenharmony_ci * @return true if the vertex data was found, false otherwise. 2105e5c31af7Sopenharmony_ci **/ 2106e5c31af7Sopenharmony_cibool TessellationShaderInvarianceRule5Test::isVertexDefined(const float* vertex_data, unsigned int n_vertices, 2107e5c31af7Sopenharmony_ci const float* vertex_data_seeked, 2108e5c31af7Sopenharmony_ci unsigned int n_vertex_data_seeked_components) 2109e5c31af7Sopenharmony_ci{ 2110e5c31af7Sopenharmony_ci const float epsilon = 1e-5f; 2111e5c31af7Sopenharmony_ci bool result = false; 2112e5c31af7Sopenharmony_ci 2113e5c31af7Sopenharmony_ci DE_ASSERT(n_vertex_data_seeked_components >= 2); 2114e5c31af7Sopenharmony_ci 2115e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < n_vertices; ++n_vertex) 2116e5c31af7Sopenharmony_ci { 2117e5c31af7Sopenharmony_ci const float* current_vertex_data = vertex_data + 3 /* components */ * n_vertex; 2118e5c31af7Sopenharmony_ci 2119e5c31af7Sopenharmony_ci if (de::abs(vertex_data_seeked[0] - current_vertex_data[0]) < epsilon && 2120e5c31af7Sopenharmony_ci de::abs(vertex_data_seeked[1] - current_vertex_data[1]) < epsilon && 2121e5c31af7Sopenharmony_ci ((n_vertex_data_seeked_components < 3) || 2122e5c31af7Sopenharmony_ci (n_vertex_data_seeked_components >= 3 && 2123e5c31af7Sopenharmony_ci de::abs(vertex_data_seeked[2] - current_vertex_data[2]) < epsilon))) 2124e5c31af7Sopenharmony_ci { 2125e5c31af7Sopenharmony_ci result = true; 2126e5c31af7Sopenharmony_ci 2127e5c31af7Sopenharmony_ci break; 2128e5c31af7Sopenharmony_ci } /* if (components match) */ 2129e5c31af7Sopenharmony_ci } /* for (all vertices) */ 2130e5c31af7Sopenharmony_ci 2131e5c31af7Sopenharmony_ci return result; 2132e5c31af7Sopenharmony_ci} 2133e5c31af7Sopenharmony_ci 2134e5c31af7Sopenharmony_ci/** Verifies result data. Accesses data generated by all iterations. 2135e5c31af7Sopenharmony_ci * 2136e5c31af7Sopenharmony_ci * Throws TestError exception if an error occurs. 2137e5c31af7Sopenharmony_ci * 2138e5c31af7Sopenharmony_ci * @param all_iterations_data An array of pointers to buffers, holding gl_TessCoord 2139e5c31af7Sopenharmony_ci * data generated by subsequent iterations. 2140e5c31af7Sopenharmony_ci **/ 2141e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule5Test::verifyResultData(const void** all_iterations_data) 2142e5c31af7Sopenharmony_ci{ 2143e5c31af7Sopenharmony_ci /* Run two separate iterations: 2144e5c31af7Sopenharmony_ci * 2145e5c31af7Sopenharmony_ci * a) triangles 2146e5c31af7Sopenharmony_ci * b) quads 2147e5c31af7Sopenharmony_ci */ 2148e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < 2 /* quads, triangles */; ++n_iteration) 2149e5c31af7Sopenharmony_ci { 2150e5c31af7Sopenharmony_ci const unsigned int n_base_iteration = 2151e5c31af7Sopenharmony_ci (n_iteration == 0) ? 0 : (unsigned int)m_test_triangles_iterations.size(); 2152e5c31af7Sopenharmony_ci const unsigned int set_size = (n_iteration == 0) ? (unsigned int)m_test_triangles_iterations.size() : 2153e5c31af7Sopenharmony_ci (unsigned int)m_test_quads_iterations.size(); 2154e5c31af7Sopenharmony_ci const _test_iterations& test_iterations = 2155e5c31af7Sopenharmony_ci (n_iteration == 0) ? m_test_triangles_iterations : m_test_quads_iterations; 2156e5c31af7Sopenharmony_ci 2157e5c31af7Sopenharmony_ci DE_ASSERT(test_iterations.size() != 0); 2158e5c31af7Sopenharmony_ci 2159e5c31af7Sopenharmony_ci /* For each iteration, verify that all vertices generated for all three vertex spacing modes. 2160e5c31af7Sopenharmony_ci * are exactly the same (but in different order) */ 2161e5c31af7Sopenharmony_ci const float* base_vertex_data = (const float*)all_iterations_data[n_base_iteration + 0]; 2162e5c31af7Sopenharmony_ci 2163e5c31af7Sopenharmony_ci for (unsigned int n_set = 1; n_set < set_size; ++n_set) 2164e5c31af7Sopenharmony_ci { 2165e5c31af7Sopenharmony_ci const float* set_vertex_data = (const float*)all_iterations_data[n_base_iteration + n_set]; 2166e5c31af7Sopenharmony_ci 2167e5c31af7Sopenharmony_ci /* Amount of vertices should not differ between sets */ 2168e5c31af7Sopenharmony_ci DE_ASSERT(test_iterations[0].n_vertices == test_iterations[n_set].n_vertices); 2169e5c31af7Sopenharmony_ci 2170e5c31af7Sopenharmony_ci /* Run through all vertices in base set and make sure they can be found in currently 2171e5c31af7Sopenharmony_ci * processed set */ 2172e5c31af7Sopenharmony_ci for (unsigned int n_base_vertex = 0; n_base_vertex < test_iterations[0].n_vertices; ++n_base_vertex) 2173e5c31af7Sopenharmony_ci { 2174e5c31af7Sopenharmony_ci const float* base_vertex = base_vertex_data + 3 /* components */ * n_base_vertex; 2175e5c31af7Sopenharmony_ci 2176e5c31af7Sopenharmony_ci if (!isVertexDefined(set_vertex_data, test_iterations[n_set].n_vertices, base_vertex, 2177e5c31af7Sopenharmony_ci 3)) /* components */ 2178e5c31af7Sopenharmony_ci { 2179e5c31af7Sopenharmony_ci const char* primitive_mode = (n_iteration == 0) ? "triangles" : "quads"; 2180e5c31af7Sopenharmony_ci 2181e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "For primitive mode [" << primitive_mode << "] " 2182e5c31af7Sopenharmony_ci << "a vertex with tessellation coordinates:[" << base_vertex[0] << ", " 2183e5c31af7Sopenharmony_ci << base_vertex[1] << ", " << base_vertex[2] << ") " 2184e5c31af7Sopenharmony_ci << "could not have been found for both vertex orderings." 2185e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 2186e5c31af7Sopenharmony_ci 2187e5c31af7Sopenharmony_ci TCU_FAIL("Implementation does not follow Rule 5."); 2188e5c31af7Sopenharmony_ci } 2189e5c31af7Sopenharmony_ci } /* for (all base set's vertices) */ 2190e5c31af7Sopenharmony_ci } /* for (all sets) */ 2191e5c31af7Sopenharmony_ci } /* for (both primitive types) */ 2192e5c31af7Sopenharmony_ci} 2193e5c31af7Sopenharmony_ci 2194e5c31af7Sopenharmony_ci/** Constructor. 2195e5c31af7Sopenharmony_ci * 2196e5c31af7Sopenharmony_ci * @param context Rendering context. 2197e5c31af7Sopenharmony_ci * 2198e5c31af7Sopenharmony_ci **/ 2199e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule6Test::TessellationShaderInvarianceRule6Test(Context& context, 2200e5c31af7Sopenharmony_ci const ExtParameters& extParams) 2201e5c31af7Sopenharmony_ci : TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule6", 2202e5c31af7Sopenharmony_ci "Verifies conformance with sixth invariance rule") 2203e5c31af7Sopenharmony_ci{ 2204e5c31af7Sopenharmony_ci} 2205e5c31af7Sopenharmony_ci 2206e5c31af7Sopenharmony_ci/** Destructor. */ 2207e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule6Test::~TessellationShaderInvarianceRule6Test() 2208e5c31af7Sopenharmony_ci{ 2209e5c31af7Sopenharmony_ci /* Left blank intentionally */ 2210e5c31af7Sopenharmony_ci} 2211e5c31af7Sopenharmony_ci 2212e5c31af7Sopenharmony_ci/** Retrieves amount of iterations the base test implementation should run before 2213e5c31af7Sopenharmony_ci * calling global verification routine. 2214e5c31af7Sopenharmony_ci * 2215e5c31af7Sopenharmony_ci * @return A value that depends on initTestIterations() behavior. 2216e5c31af7Sopenharmony_ci **/ 2217e5c31af7Sopenharmony_ciunsigned int TessellationShaderInvarianceRule6Test::getAmountOfIterations() 2218e5c31af7Sopenharmony_ci{ 2219e5c31af7Sopenharmony_ci if (m_test_quads_iterations.size() == 0 || m_test_triangles_iterations.size() == 0) 2220e5c31af7Sopenharmony_ci { 2221e5c31af7Sopenharmony_ci initTestIterations(); 2222e5c31af7Sopenharmony_ci } 2223e5c31af7Sopenharmony_ci 2224e5c31af7Sopenharmony_ci return (unsigned int)(m_test_quads_iterations.size() + m_test_triangles_iterations.size()); 2225e5c31af7Sopenharmony_ci} 2226e5c31af7Sopenharmony_ci 2227e5c31af7Sopenharmony_ci/** Retrieves _test_iteration instance specific for user-specified iteration index. 2228e5c31af7Sopenharmony_ci * 2229e5c31af7Sopenharmony_ci * @param n_iteration Iteration index to retrieve _test_iteration instance for. 2230e5c31af7Sopenharmony_ci * 2231e5c31af7Sopenharmony_ci * @return Iteration-specific _test_iteration instance. 2232e5c31af7Sopenharmony_ci * 2233e5c31af7Sopenharmony_ci **/ 2234e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule6Test::_test_iteration& TessellationShaderInvarianceRule6Test::getTestForIteration( 2235e5c31af7Sopenharmony_ci unsigned int n_iteration) 2236e5c31af7Sopenharmony_ci{ 2237e5c31af7Sopenharmony_ci unsigned int n_triangles_tests = (unsigned int)m_test_triangles_iterations.size(); 2238e5c31af7Sopenharmony_ci _test_iteration& test_iteration = (n_iteration < n_triangles_tests) ? 2239e5c31af7Sopenharmony_ci m_test_triangles_iterations[n_iteration] : 2240e5c31af7Sopenharmony_ci m_test_quads_iterations[n_iteration - n_triangles_tests]; 2241e5c31af7Sopenharmony_ci 2242e5c31af7Sopenharmony_ci return test_iteration; 2243e5c31af7Sopenharmony_ci} 2244e5c31af7Sopenharmony_ci 2245e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation properties. 2246e5c31af7Sopenharmony_ci * 2247e5c31af7Sopenharmony_ci * @param n_iteration Iteration index to retrieve the properties for. 2248e5c31af7Sopenharmony_ci * @param out_inner_tess_levels Deref will be used to store iteration-specific inner 2249e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 2250e5c31af7Sopenharmony_ci * @param out_outer_tess_levels Deref will be used to store iteration-specific outer 2251e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 2252e5c31af7Sopenharmony_ci * @param out_point_mode Deref will be used to store iteration-specific flag 2253e5c31af7Sopenharmony_ci * telling whether point mode should be enabled for given pass. 2254e5c31af7Sopenharmony_ci * Must not be NULL. 2255e5c31af7Sopenharmony_ci * @param out_primitive_mode Deref will be used to store iteration-specific primitive 2256e5c31af7Sopenharmony_ci * mode. Must not be NULL. 2257e5c31af7Sopenharmony_ci * @param out_vertex_ordering Deref will be used to store iteration-specific vertex 2258e5c31af7Sopenharmony_ci * ordering. Must not be NULL. 2259e5c31af7Sopenharmony_ci * @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object 2260e5c31af7Sopenharmony_ci * storage should offer for the draw call to succeed. Can 2261e5c31af7Sopenharmony_ci * be NULL. 2262e5c31af7Sopenharmony_ci **/ 2263e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule6Test::getIterationProperties( 2264e5c31af7Sopenharmony_ci unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode, 2265e5c31af7Sopenharmony_ci _tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering, 2266e5c31af7Sopenharmony_ci unsigned int* out_result_buffer_size) 2267e5c31af7Sopenharmony_ci{ 2268e5c31af7Sopenharmony_ci DE_ASSERT(m_test_triangles_iterations.size() + m_test_quads_iterations.size() > n_iteration); 2269e5c31af7Sopenharmony_ci 2270e5c31af7Sopenharmony_ci _test_iteration& test_iteration = getTestForIteration(n_iteration); 2271e5c31af7Sopenharmony_ci 2272e5c31af7Sopenharmony_ci memcpy(out_inner_tess_levels, test_iteration.inner_tess_levels, sizeof(test_iteration.inner_tess_levels)); 2273e5c31af7Sopenharmony_ci memcpy(out_outer_tess_levels, test_iteration.outer_tess_levels, sizeof(test_iteration.outer_tess_levels)); 2274e5c31af7Sopenharmony_ci 2275e5c31af7Sopenharmony_ci *out_point_mode = false; 2276e5c31af7Sopenharmony_ci *out_primitive_mode = test_iteration.primitive_mode; 2277e5c31af7Sopenharmony_ci *out_vertex_ordering = test_iteration.vertex_ordering; 2278e5c31af7Sopenharmony_ci 2279e5c31af7Sopenharmony_ci if (out_result_buffer_size != DE_NULL) 2280e5c31af7Sopenharmony_ci { 2281e5c31af7Sopenharmony_ci *out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator( 2282e5c31af7Sopenharmony_ci *out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 2283e5c31af7Sopenharmony_ci *out_point_mode); 2284e5c31af7Sopenharmony_ci test_iteration.n_vertices = *out_result_buffer_size; 2285e5c31af7Sopenharmony_ci *out_result_buffer_size = 2286e5c31af7Sopenharmony_ci static_cast<unsigned int>(*out_result_buffer_size * 3 /* components */ * sizeof(float)); 2287e5c31af7Sopenharmony_ci 2288e5c31af7Sopenharmony_ci DE_ASSERT(*out_result_buffer_size != 0); 2289e5c31af7Sopenharmony_ci } 2290e5c31af7Sopenharmony_ci} 2291e5c31af7Sopenharmony_ci 2292e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation evaluation shader code. 2293e5c31af7Sopenharmony_ci * 2294e5c31af7Sopenharmony_ci * @param n_iteration Iteration index, for which the source code is being obtained. 2295e5c31af7Sopenharmony_ci * 2296e5c31af7Sopenharmony_ci * @return Requested source code. 2297e5c31af7Sopenharmony_ci **/ 2298e5c31af7Sopenharmony_cistd::string TessellationShaderInvarianceRule6Test::getTECode(unsigned int n_iteration) 2299e5c31af7Sopenharmony_ci{ 2300e5c31af7Sopenharmony_ci DE_ASSERT(m_test_triangles_iterations.size() + m_test_quads_iterations.size() > n_iteration); 2301e5c31af7Sopenharmony_ci 2302e5c31af7Sopenharmony_ci const _test_iteration& test_iteration = getTestForIteration(n_iteration); 2303e5c31af7Sopenharmony_ci 2304e5c31af7Sopenharmony_ci return TessellationShaderUtils::getGenericTECode(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 2305e5c31af7Sopenharmony_ci test_iteration.primitive_mode, test_iteration.vertex_ordering, 2306e5c31af7Sopenharmony_ci false); /* point mode */ 2307e5c31af7Sopenharmony_ci} 2308e5c31af7Sopenharmony_ci 2309e5c31af7Sopenharmony_ci/** Initializes test iterations for the test. The following modes and inner/outer tess level 2310e5c31af7Sopenharmony_ci * configurations are used to form the test set: 2311e5c31af7Sopenharmony_ci * 2312e5c31af7Sopenharmony_ci * - Tessellation level combinations as returned by 2313e5c31af7Sopenharmony_ci * TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode() (however, the inner 2314e5c31af7Sopenharmony_ci * tessellation level values are all set to values corresponding to last item returned for 2315e5c31af7Sopenharmony_ci * the set) 2316e5c31af7Sopenharmony_ci * - All primitive modes; 2317e5c31af7Sopenharmony_ci * - All vertex ordering modes; 2318e5c31af7Sopenharmony_ci * 2319e5c31af7Sopenharmony_ci * All permutations are used to generate the test set. 2320e5c31af7Sopenharmony_ci **/ 2321e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule6Test::initTestIterations() 2322e5c31af7Sopenharmony_ci{ 2323e5c31af7Sopenharmony_ci DE_ASSERT(m_test_quads_iterations.size() == 0 && m_test_triangles_iterations.size() == 0); 2324e5c31af7Sopenharmony_ci 2325e5c31af7Sopenharmony_ci /* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */ 2326e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2327e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_gen_level_value = 0; 2328e5c31af7Sopenharmony_ci 2329e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value); 2330e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 2331e5c31af7Sopenharmony_ci 2332e5c31af7Sopenharmony_ci /* Iterate through all primitive and vertex spacing modes relevant to the test */ 2333e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES, 2334e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS }; 2335e5c31af7Sopenharmony_ci _tessellation_shader_vertex_ordering vertex_ordering_modes[] = { TESSELLATION_SHADER_VERTEX_ORDERING_CCW, 2336e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_ORDERING_CW }; 2337e5c31af7Sopenharmony_ci 2338e5c31af7Sopenharmony_ci const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]); 2339e5c31af7Sopenharmony_ci const unsigned int n_vo_modes = sizeof(vertex_ordering_modes) / sizeof(vertex_ordering_modes[0]); 2340e5c31af7Sopenharmony_ci 2341e5c31af7Sopenharmony_ci for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode) 2342e5c31af7Sopenharmony_ci { 2343e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode]; 2344e5c31af7Sopenharmony_ci 2345e5c31af7Sopenharmony_ci for (unsigned int n_vo_mode = 0; n_vo_mode < n_vo_modes; ++n_vo_mode) 2346e5c31af7Sopenharmony_ci { 2347e5c31af7Sopenharmony_ci _tessellation_shader_vertex_ordering vertex_ordering = vertex_ordering_modes[n_vo_mode]; 2348e5c31af7Sopenharmony_ci 2349e5c31af7Sopenharmony_ci /* Retrieve inner/outer tessellation level combinations we want the tests to be run for. 2350e5c31af7Sopenharmony_ci * Since each level set we will be provided by getTessellationLevelSetForPrimitiveMode() 2351e5c31af7Sopenharmony_ci * is unique and does not repeat, we'll just make sure the inner level values are set to 2352e5c31af7Sopenharmony_ci * the same set of values, so that the conditions the test must meet are actually met. 2353e5c31af7Sopenharmony_ci */ 2354e5c31af7Sopenharmony_ci float* inner_levels_to_use = DE_NULL; 2355e5c31af7Sopenharmony_ci _tessellation_levels_set levels_set; 2356e5c31af7Sopenharmony_ci unsigned int n_levels_sets = 0; 2357e5c31af7Sopenharmony_ci 2358e5c31af7Sopenharmony_ci levels_set = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode( 2359e5c31af7Sopenharmony_ci primitive_mode, gl_max_tess_gen_level_value, 2360e5c31af7Sopenharmony_ci TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE); 2361e5c31af7Sopenharmony_ci 2362e5c31af7Sopenharmony_ci n_levels_sets = (unsigned int)levels_set.size(); 2363e5c31af7Sopenharmony_ci inner_levels_to_use = levels_set[n_levels_sets - 1].inner; 2364e5c31af7Sopenharmony_ci 2365e5c31af7Sopenharmony_ci for (unsigned int n_levels_set = 0; n_levels_set < n_levels_sets - 1; n_levels_set++) 2366e5c31af7Sopenharmony_ci { 2367e5c31af7Sopenharmony_ci /* Make sure the Utils function was not changed and that inner level values 2368e5c31af7Sopenharmony_ci * are actually unique across the whole set */ 2369e5c31af7Sopenharmony_ci DE_ASSERT(levels_set[n_levels_set].inner[0] != levels_set[n_levels_sets - 1].inner[0] && 2370e5c31af7Sopenharmony_ci levels_set[n_levels_set].inner[1] != levels_set[n_levels_sets - 1].inner[1]); 2371e5c31af7Sopenharmony_ci 2372e5c31af7Sopenharmony_ci /* Force the last set's inner values to all level combinations we'll be using */ 2373e5c31af7Sopenharmony_ci memcpy(levels_set[n_levels_set].inner, inner_levels_to_use, sizeof(levels_set[n_levels_set].inner)); 2374e5c31af7Sopenharmony_ci } /* for (all sets retrieved from Utils function */ 2375e5c31af7Sopenharmony_ci 2376e5c31af7Sopenharmony_ci for (_tessellation_levels_set_const_iterator set_iterator = levels_set.begin(); 2377e5c31af7Sopenharmony_ci set_iterator != levels_set.end(); set_iterator++) 2378e5c31af7Sopenharmony_ci { 2379e5c31af7Sopenharmony_ci const _tessellation_levels& levels = *set_iterator; 2380e5c31af7Sopenharmony_ci 2381e5c31af7Sopenharmony_ci /* Create a test descriptor for all the parameters we now have */ 2382e5c31af7Sopenharmony_ci _test_iteration test; 2383e5c31af7Sopenharmony_ci 2384e5c31af7Sopenharmony_ci memcpy(test.inner_tess_levels, levels.inner, sizeof(test.inner_tess_levels)); 2385e5c31af7Sopenharmony_ci memcpy(test.outer_tess_levels, levels.outer, sizeof(test.outer_tess_levels)); 2386e5c31af7Sopenharmony_ci 2387e5c31af7Sopenharmony_ci test.primitive_mode = primitive_mode; 2388e5c31af7Sopenharmony_ci test.vertex_ordering = vertex_ordering; 2389e5c31af7Sopenharmony_ci 2390e5c31af7Sopenharmony_ci if (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES) 2391e5c31af7Sopenharmony_ci { 2392e5c31af7Sopenharmony_ci m_test_triangles_iterations.push_back(test); 2393e5c31af7Sopenharmony_ci } 2394e5c31af7Sopenharmony_ci else 2395e5c31af7Sopenharmony_ci { 2396e5c31af7Sopenharmony_ci m_test_quads_iterations.push_back(test); 2397e5c31af7Sopenharmony_ci } 2398e5c31af7Sopenharmony_ci } /* for (all level sets) */ 2399e5c31af7Sopenharmony_ci } /* for (all vertex ordering modes) */ 2400e5c31af7Sopenharmony_ci } /* for (all primitive modes) */ 2401e5c31af7Sopenharmony_ci} 2402e5c31af7Sopenharmony_ci 2403e5c31af7Sopenharmony_ci/** Verifies result data. Accesses data generated by all iterations. 2404e5c31af7Sopenharmony_ci * 2405e5c31af7Sopenharmony_ci * Throws TestError exception if an error occurs. 2406e5c31af7Sopenharmony_ci * 2407e5c31af7Sopenharmony_ci * @param all_iterations_data An array of pointers to buffers, holding gl_TessCoord 2408e5c31af7Sopenharmony_ci * data generated by subsequent iterations. 2409e5c31af7Sopenharmony_ci **/ 2410e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule6Test::verifyResultData(const void** all_iterations_data) 2411e5c31af7Sopenharmony_ci{ 2412e5c31af7Sopenharmony_ci /* Run two separate iterations: 2413e5c31af7Sopenharmony_ci * 2414e5c31af7Sopenharmony_ci * a) triangles 2415e5c31af7Sopenharmony_ci * b) quads 2416e5c31af7Sopenharmony_ci */ 2417e5c31af7Sopenharmony_ci 2418e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < 2 /* quads, triangles */; ++n_iteration) 2419e5c31af7Sopenharmony_ci { 2420e5c31af7Sopenharmony_ci const unsigned int n_base_iteration = 2421e5c31af7Sopenharmony_ci (n_iteration == 0) ? 0 : (unsigned int)m_test_triangles_iterations.size(); 2422e5c31af7Sopenharmony_ci 2423e5c31af7Sopenharmony_ci const unsigned int n_sets = (n_iteration == 0) ? (unsigned int)m_test_triangles_iterations.size() : 2424e5c31af7Sopenharmony_ci (unsigned int)m_test_quads_iterations.size(); 2425e5c31af7Sopenharmony_ci 2426e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_mode = (n_iteration == 0) ? 2427e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES : 2428e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS; 2429e5c31af7Sopenharmony_ci 2430e5c31af7Sopenharmony_ci const _test_iterations& test_iterations = 2431e5c31af7Sopenharmony_ci (n_iteration == 0) ? m_test_triangles_iterations : m_test_quads_iterations; 2432e5c31af7Sopenharmony_ci 2433e5c31af7Sopenharmony_ci const unsigned int n_triangles_in_base_set = test_iterations[0].n_vertices / 3 /* vertices per triangle */; 2434e5c31af7Sopenharmony_ci 2435e5c31af7Sopenharmony_ci DE_ASSERT(test_iterations.size() != 0); 2436e5c31af7Sopenharmony_ci 2437e5c31af7Sopenharmony_ci /* For each iteration, verify that all vertices generated for all three vertex spacing modes. 2438e5c31af7Sopenharmony_ci * are exactly the same (but in different order) */ 2439e5c31af7Sopenharmony_ci const _test_iteration& base_test = test_iterations[0]; 2440e5c31af7Sopenharmony_ci const float* base_vertex_data = (const float*)all_iterations_data[n_base_iteration + 0]; 2441e5c31af7Sopenharmony_ci 2442e5c31af7Sopenharmony_ci for (unsigned int n_set = 1; n_set < n_sets; ++n_set) 2443e5c31af7Sopenharmony_ci { 2444e5c31af7Sopenharmony_ci const _test_iteration& set_test = test_iterations[n_set]; 2445e5c31af7Sopenharmony_ci const float* set_vertex_data = (const float*)all_iterations_data[n_base_iteration + n_set]; 2446e5c31af7Sopenharmony_ci 2447e5c31af7Sopenharmony_ci /* We're operating on triangles so make sure the amount of vertices we're dealing with is 2448e5c31af7Sopenharmony_ci * divisible by 3 */ 2449e5c31af7Sopenharmony_ci DE_ASSERT((test_iterations[n_set].n_vertices % 3) == 0); 2450e5c31af7Sopenharmony_ci 2451e5c31af7Sopenharmony_ci const unsigned int n_triangles_in_curr_set = test_iterations[n_set].n_vertices / 3; 2452e5c31af7Sopenharmony_ci 2453e5c31af7Sopenharmony_ci /* Take base triangles and make sure they can be found in iteration-specific set. 2454e5c31af7Sopenharmony_ci * Now, thing to keep in mind here is that we must not assume any specific vertex 2455e5c31af7Sopenharmony_ci * and triangle order which is why the slow search. */ 2456e5c31af7Sopenharmony_ci for (unsigned int n_base_triangle = 0; n_base_triangle < n_triangles_in_base_set; ++n_base_triangle) 2457e5c31af7Sopenharmony_ci { 2458e5c31af7Sopenharmony_ci /* Extract base triangle data first */ 2459e5c31af7Sopenharmony_ci const float* base_triangle_vertex1 = base_vertex_data + 2460e5c31af7Sopenharmony_ci n_base_triangle * 3 * /* vertices per triangle */ 2461e5c31af7Sopenharmony_ci 3; /* components */ 2462e5c31af7Sopenharmony_ci const float* base_triangle_vertex2 = base_triangle_vertex1 + 3; /* components */ 2463e5c31af7Sopenharmony_ci const float* base_triangle_vertex3 = base_triangle_vertex2 + 3; /* components */ 2464e5c31af7Sopenharmony_ci 2465e5c31af7Sopenharmony_ci /* Only interior triangles should be left intact. Is this an interior triangle? */ 2466e5c31af7Sopenharmony_ci if (!TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, base_triangle_vertex1) && 2467e5c31af7Sopenharmony_ci !TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, base_triangle_vertex2) && 2468e5c31af7Sopenharmony_ci !TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, base_triangle_vertex3)) 2469e5c31af7Sopenharmony_ci { 2470e5c31af7Sopenharmony_ci /* Iterate through all triangles in considered set */ 2471e5c31af7Sopenharmony_ci bool has_base_set_triangle_been_found = false; 2472e5c31af7Sopenharmony_ci 2473e5c31af7Sopenharmony_ci for (unsigned int n_curr_set_triangle = 0; n_curr_set_triangle < n_triangles_in_curr_set; 2474e5c31af7Sopenharmony_ci ++n_curr_set_triangle) 2475e5c31af7Sopenharmony_ci { 2476e5c31af7Sopenharmony_ci const float* curr_triangle = set_vertex_data + 2477e5c31af7Sopenharmony_ci n_curr_set_triangle * 3 * /* vertices per triangle */ 2478e5c31af7Sopenharmony_ci 3; /* components */ 2479e5c31af7Sopenharmony_ci 2480e5c31af7Sopenharmony_ci if (TessellationShaderUtils::isTriangleDefined(base_triangle_vertex1, curr_triangle)) 2481e5c31af7Sopenharmony_ci { 2482e5c31af7Sopenharmony_ci has_base_set_triangle_been_found = true; 2483e5c31af7Sopenharmony_ci 2484e5c31af7Sopenharmony_ci break; 2485e5c31af7Sopenharmony_ci } 2486e5c31af7Sopenharmony_ci } /* for (all triangles in currently processed set) */ 2487e5c31af7Sopenharmony_ci 2488e5c31af7Sopenharmony_ci if (!has_base_set_triangle_been_found) 2489e5c31af7Sopenharmony_ci { 2490e5c31af7Sopenharmony_ci std::string primitive_mode_str = 2491e5c31af7Sopenharmony_ci TessellationShaderUtils::getESTokenForPrimitiveMode(base_test.primitive_mode); 2492e5c31af7Sopenharmony_ci 2493e5c31af7Sopenharmony_ci m_testCtx.getLog() 2494e5c31af7Sopenharmony_ci << tcu::TestLog::Message << "For primitive mode [" << primitive_mode_str << "]" 2495e5c31af7Sopenharmony_ci << ", base inner tessellation levels:" 2496e5c31af7Sopenharmony_ci << "[" << base_test.inner_tess_levels[0] << ", " << base_test.inner_tess_levels[1] << "]" 2497e5c31af7Sopenharmony_ci << ", base outer tessellation levels:" 2498e5c31af7Sopenharmony_ci << "[" << base_test.outer_tess_levels[0] << ", " << base_test.outer_tess_levels[1] << ", " 2499e5c31af7Sopenharmony_ci << base_test.outer_tess_levels[2] << ", " << base_test.outer_tess_levels[3] << "]" 2500e5c31af7Sopenharmony_ci << ", reference inner tessellation levels:" 2501e5c31af7Sopenharmony_ci << "[" << set_test.inner_tess_levels[0] << ", " << set_test.inner_tess_levels[1] << "]" 2502e5c31af7Sopenharmony_ci << ", reference outer tessellation levels:" 2503e5c31af7Sopenharmony_ci << "[" << set_test.outer_tess_levels[0] << ", " << set_test.outer_tess_levels[1] << ", " 2504e5c31af7Sopenharmony_ci << set_test.outer_tess_levels[2] << ", " << set_test.outer_tess_levels[3] << "]" 2505e5c31af7Sopenharmony_ci << ", the following triangle formed during base tessellation run was not found in " 2506e5c31af7Sopenharmony_ci "reference run:" 2507e5c31af7Sopenharmony_ci << "[" << base_triangle_vertex1[0] << ", " << base_triangle_vertex1[1] << ", " 2508e5c31af7Sopenharmony_ci << base_triangle_vertex1[2] << "]x" 2509e5c31af7Sopenharmony_ci << "[" << base_triangle_vertex2[0] << ", " << base_triangle_vertex2[1] << ", " 2510e5c31af7Sopenharmony_ci << base_triangle_vertex2[2] << "]x" 2511e5c31af7Sopenharmony_ci << "[" << base_triangle_vertex3[0] << ", " << base_triangle_vertex3[1] << ", " 2512e5c31af7Sopenharmony_ci << base_triangle_vertex3[2] 2513e5c31af7Sopenharmony_ci 2514e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 2515e5c31af7Sopenharmony_ci 2516e5c31af7Sopenharmony_ci TCU_FAIL("Implementation does not appear to be rule 6-conformant"); 2517e5c31af7Sopenharmony_ci } /* if (triangle created during base run was not found in reference run) */ 2518e5c31af7Sopenharmony_ci } /* if (base triangle is interior) */ 2519e5c31af7Sopenharmony_ci } /* for (all base set's vertices) */ 2520e5c31af7Sopenharmony_ci } /* for (all sets) */ 2521e5c31af7Sopenharmony_ci } /* for (both primitive types) */ 2522e5c31af7Sopenharmony_ci} 2523e5c31af7Sopenharmony_ci 2524e5c31af7Sopenharmony_ci/** Constructor. 2525e5c31af7Sopenharmony_ci * 2526e5c31af7Sopenharmony_ci * @param context Rendering context. 2527e5c31af7Sopenharmony_ci * 2528e5c31af7Sopenharmony_ci **/ 2529e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule7Test::TessellationShaderInvarianceRule7Test(Context& context, 2530e5c31af7Sopenharmony_ci const ExtParameters& extParams) 2531e5c31af7Sopenharmony_ci : TessellationShaderInvarianceBaseTest(context, extParams, "invariance_rule7", 2532e5c31af7Sopenharmony_ci "Verifies conformance with seventh invariance rule") 2533e5c31af7Sopenharmony_ci{ 2534e5c31af7Sopenharmony_ci} 2535e5c31af7Sopenharmony_ci 2536e5c31af7Sopenharmony_ci/** Destructor. */ 2537e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule7Test::~TessellationShaderInvarianceRule7Test() 2538e5c31af7Sopenharmony_ci{ 2539e5c31af7Sopenharmony_ci /* Left blank intentionally */ 2540e5c31af7Sopenharmony_ci} 2541e5c31af7Sopenharmony_ci 2542e5c31af7Sopenharmony_ci/** Retrieves amount of iterations the base test implementation should run before 2543e5c31af7Sopenharmony_ci * calling global verification routine. 2544e5c31af7Sopenharmony_ci * 2545e5c31af7Sopenharmony_ci * @return A value that depends on initTestIterations() behavior. 2546e5c31af7Sopenharmony_ci **/ 2547e5c31af7Sopenharmony_ciunsigned int TessellationShaderInvarianceRule7Test::getAmountOfIterations() 2548e5c31af7Sopenharmony_ci{ 2549e5c31af7Sopenharmony_ci if (m_test_quads_iterations.size() == 0 || m_test_triangles_iterations.size() == 0) 2550e5c31af7Sopenharmony_ci { 2551e5c31af7Sopenharmony_ci initTestIterations(); 2552e5c31af7Sopenharmony_ci } 2553e5c31af7Sopenharmony_ci 2554e5c31af7Sopenharmony_ci return (unsigned int)(m_test_quads_iterations.size() + m_test_triangles_iterations.size()); 2555e5c31af7Sopenharmony_ci} 2556e5c31af7Sopenharmony_ci 2557e5c31af7Sopenharmony_ci/** Retrieves index of a test iteration that was initialized with user-provided 2558e5c31af7Sopenharmony_ci * properties. 2559e5c31af7Sopenharmony_ci * 2560e5c31af7Sopenharmony_ci * @param is_triangles_iteration true if the seeked test iteration should have 2561e5c31af7Sopenharmony_ci * been run for 'triangles' primitive mode', false 2562e5c31af7Sopenharmony_ci * if 'quads' primitive mode run is seeked. 2563e5c31af7Sopenharmony_ci * @param inner_tess_levels Two FP values describing inner tessellation level 2564e5c31af7Sopenharmony_ci * values the seeked run should have used. 2565e5c31af7Sopenharmony_ci * @param outer_tess_levels Four FP values describing outer tessellation level 2566e5c31af7Sopenharmony_ci * values the seeked run should have used. 2567e5c31af7Sopenharmony_ci * @param vertex_ordering Vertex ordering mode the seeked run should have used. 2568e5c31af7Sopenharmony_ci * @param n_modified_outer_tess_level Tells which outer tessellation level should be 2569e5c31af7Sopenharmony_ci * excluded from checking. 2570e5c31af7Sopenharmony_ci * 2571e5c31af7Sopenharmony_ci * @return 0xFFFFFFFF if no test iteration was run for user-provided properties, 2572e5c31af7Sopenharmony_ci * actual index otherwise. 2573e5c31af7Sopenharmony_ci * 2574e5c31af7Sopenharmony_ci **/ 2575e5c31af7Sopenharmony_ciunsigned int TessellationShaderInvarianceRule7Test::getTestIterationIndex( 2576e5c31af7Sopenharmony_ci bool is_triangles_iteration, const float* inner_tess_levels, const float* outer_tess_levels, 2577e5c31af7Sopenharmony_ci _tessellation_shader_vertex_ordering vertex_ordering, unsigned int n_modified_outer_tess_level) 2578e5c31af7Sopenharmony_ci{ 2579e5c31af7Sopenharmony_ci const float epsilon = 1e-5f; 2580e5c31af7Sopenharmony_ci unsigned int result = 0xFFFFFFFF; 2581e5c31af7Sopenharmony_ci const _test_iterations& test_iterations = 2582e5c31af7Sopenharmony_ci (is_triangles_iteration) ? m_test_triangles_iterations : m_test_quads_iterations; 2583e5c31af7Sopenharmony_ci const unsigned int n_test_iterations = (unsigned int)test_iterations.size(); 2584e5c31af7Sopenharmony_ci 2585e5c31af7Sopenharmony_ci for (unsigned int n_test_iteration = 0; n_test_iteration < n_test_iterations; ++n_test_iteration) 2586e5c31af7Sopenharmony_ci { 2587e5c31af7Sopenharmony_ci _test_iteration test_iteration = test_iterations[n_test_iteration]; 2588e5c31af7Sopenharmony_ci 2589e5c31af7Sopenharmony_ci if (de::abs(test_iteration.inner_tess_levels[0] - inner_tess_levels[0]) < epsilon && 2590e5c31af7Sopenharmony_ci de::abs(test_iteration.inner_tess_levels[1] - inner_tess_levels[1]) < epsilon && 2591e5c31af7Sopenharmony_ci test_iteration.vertex_ordering == vertex_ordering && 2592e5c31af7Sopenharmony_ci test_iteration.n_modified_outer_tess_level == n_modified_outer_tess_level) 2593e5c31af7Sopenharmony_ci { 2594e5c31af7Sopenharmony_ci /* Only compare outer tessellation levels that have not been modified */ 2595e5c31af7Sopenharmony_ci if (((n_modified_outer_tess_level == 0) || 2596e5c31af7Sopenharmony_ci (n_modified_outer_tess_level != 0 && 2597e5c31af7Sopenharmony_ci de::abs(test_iteration.outer_tess_levels[0] - outer_tess_levels[0]) < epsilon)) && 2598e5c31af7Sopenharmony_ci ((n_modified_outer_tess_level == 1) || 2599e5c31af7Sopenharmony_ci (n_modified_outer_tess_level != 1 && 2600e5c31af7Sopenharmony_ci de::abs(test_iteration.outer_tess_levels[1] - outer_tess_levels[1]) < epsilon)) && 2601e5c31af7Sopenharmony_ci ((n_modified_outer_tess_level == 2) || 2602e5c31af7Sopenharmony_ci (n_modified_outer_tess_level != 2 && 2603e5c31af7Sopenharmony_ci de::abs(test_iteration.outer_tess_levels[2] - outer_tess_levels[2]) < epsilon)) && 2604e5c31af7Sopenharmony_ci ((n_modified_outer_tess_level == 3) || 2605e5c31af7Sopenharmony_ci (n_modified_outer_tess_level != 3 && 2606e5c31af7Sopenharmony_ci de::abs(test_iteration.outer_tess_levels[3] - outer_tess_levels[3]) < epsilon))) 2607e5c31af7Sopenharmony_ci { 2608e5c31af7Sopenharmony_ci result = n_test_iteration; 2609e5c31af7Sopenharmony_ci 2610e5c31af7Sopenharmony_ci break; 2611e5c31af7Sopenharmony_ci } 2612e5c31af7Sopenharmony_ci } 2613e5c31af7Sopenharmony_ci } /* for (all test iterations) */ 2614e5c31af7Sopenharmony_ci 2615e5c31af7Sopenharmony_ci return result; 2616e5c31af7Sopenharmony_ci} 2617e5c31af7Sopenharmony_ci 2618e5c31af7Sopenharmony_ci/** Retrieves _test_iteration instance specific for user-specified iteration index. 2619e5c31af7Sopenharmony_ci * 2620e5c31af7Sopenharmony_ci * @param n_iteration Iteration index to retrieve _test_iteration instance for. 2621e5c31af7Sopenharmony_ci * 2622e5c31af7Sopenharmony_ci * @return Iteration-specific _test_iteration instance. 2623e5c31af7Sopenharmony_ci * 2624e5c31af7Sopenharmony_ci **/ 2625e5c31af7Sopenharmony_ciTessellationShaderInvarianceRule7Test::_test_iteration& TessellationShaderInvarianceRule7Test::getTestForIteration( 2626e5c31af7Sopenharmony_ci unsigned int n_iteration) 2627e5c31af7Sopenharmony_ci{ 2628e5c31af7Sopenharmony_ci unsigned int n_triangles_tests = (unsigned int)m_test_triangles_iterations.size(); 2629e5c31af7Sopenharmony_ci _test_iteration& test_iteration = (n_iteration < n_triangles_tests) ? 2630e5c31af7Sopenharmony_ci m_test_triangles_iterations[n_iteration] : 2631e5c31af7Sopenharmony_ci m_test_quads_iterations[n_iteration - n_triangles_tests]; 2632e5c31af7Sopenharmony_ci 2633e5c31af7Sopenharmony_ci return test_iteration; 2634e5c31af7Sopenharmony_ci} 2635e5c31af7Sopenharmony_ci 2636e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation properties. 2637e5c31af7Sopenharmony_ci * 2638e5c31af7Sopenharmony_ci * @param n_iteration Iteration index to retrieve the properties for. 2639e5c31af7Sopenharmony_ci * @param out_inner_tess_levels Deref will be used to store iteration-specific inner 2640e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 2641e5c31af7Sopenharmony_ci * @param out_outer_tess_levels Deref will be used to store iteration-specific outer 2642e5c31af7Sopenharmony_ci * tessellation level values. Must not be NULL. 2643e5c31af7Sopenharmony_ci * @param out_point_mode Deref will be used to store iteration-specific flag 2644e5c31af7Sopenharmony_ci * telling whether point mode should be enabled for given pass. 2645e5c31af7Sopenharmony_ci * Must not be NULL. 2646e5c31af7Sopenharmony_ci * @param out_primitive_mode Deref will be used to store iteration-specific primitive 2647e5c31af7Sopenharmony_ci * mode. Must not be NULL. 2648e5c31af7Sopenharmony_ci * @param out_vertex_ordering Deref will be used to store iteration-specific vertex 2649e5c31af7Sopenharmony_ci * ordering. Must not be NULL. 2650e5c31af7Sopenharmony_ci * @param out_result_buffer_size Deref will be used to store amount of bytes XFB buffer object 2651e5c31af7Sopenharmony_ci * storage should offer for the draw call to succeed. Can 2652e5c31af7Sopenharmony_ci * be NULL. 2653e5c31af7Sopenharmony_ci **/ 2654e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule7Test::getIterationProperties( 2655e5c31af7Sopenharmony_ci unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels, bool* out_point_mode, 2656e5c31af7Sopenharmony_ci _tessellation_primitive_mode* out_primitive_mode, _tessellation_shader_vertex_ordering* out_vertex_ordering, 2657e5c31af7Sopenharmony_ci unsigned int* out_result_buffer_size) 2658e5c31af7Sopenharmony_ci{ 2659e5c31af7Sopenharmony_ci DE_ASSERT(m_test_triangles_iterations.size() + m_test_quads_iterations.size() > n_iteration); 2660e5c31af7Sopenharmony_ci 2661e5c31af7Sopenharmony_ci _test_iteration& test_iteration = getTestForIteration(n_iteration); 2662e5c31af7Sopenharmony_ci 2663e5c31af7Sopenharmony_ci memcpy(out_inner_tess_levels, test_iteration.inner_tess_levels, sizeof(test_iteration.inner_tess_levels)); 2664e5c31af7Sopenharmony_ci memcpy(out_outer_tess_levels, test_iteration.outer_tess_levels, sizeof(test_iteration.outer_tess_levels)); 2665e5c31af7Sopenharmony_ci 2666e5c31af7Sopenharmony_ci *out_point_mode = false; 2667e5c31af7Sopenharmony_ci *out_primitive_mode = test_iteration.primitive_mode; 2668e5c31af7Sopenharmony_ci *out_vertex_ordering = test_iteration.vertex_ordering; 2669e5c31af7Sopenharmony_ci 2670e5c31af7Sopenharmony_ci if (out_result_buffer_size != DE_NULL) 2671e5c31af7Sopenharmony_ci { 2672e5c31af7Sopenharmony_ci *out_result_buffer_size = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator( 2673e5c31af7Sopenharmony_ci *out_primitive_mode, out_inner_tess_levels, out_outer_tess_levels, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 2674e5c31af7Sopenharmony_ci *out_point_mode); 2675e5c31af7Sopenharmony_ci test_iteration.n_vertices = *out_result_buffer_size; 2676e5c31af7Sopenharmony_ci *out_result_buffer_size = 2677e5c31af7Sopenharmony_ci static_cast<unsigned int>(*out_result_buffer_size * 3 /* components */ * sizeof(float)); 2678e5c31af7Sopenharmony_ci 2679e5c31af7Sopenharmony_ci DE_ASSERT(*out_result_buffer_size != 0); 2680e5c31af7Sopenharmony_ci } 2681e5c31af7Sopenharmony_ci} 2682e5c31af7Sopenharmony_ci 2683e5c31af7Sopenharmony_ci/** Retrieves iteration-specific tessellation evaluation shader code. 2684e5c31af7Sopenharmony_ci * 2685e5c31af7Sopenharmony_ci * @param n_iteration Iteration index, for which the source code is being obtained. 2686e5c31af7Sopenharmony_ci * 2687e5c31af7Sopenharmony_ci * @return Requested source code. 2688e5c31af7Sopenharmony_ci **/ 2689e5c31af7Sopenharmony_cistd::string TessellationShaderInvarianceRule7Test::getTECode(unsigned int n_iteration) 2690e5c31af7Sopenharmony_ci{ 2691e5c31af7Sopenharmony_ci DE_ASSERT(m_test_triangles_iterations.size() + m_test_quads_iterations.size() > n_iteration); 2692e5c31af7Sopenharmony_ci 2693e5c31af7Sopenharmony_ci const _test_iteration& test_iteration = getTestForIteration(n_iteration); 2694e5c31af7Sopenharmony_ci 2695e5c31af7Sopenharmony_ci return TessellationShaderUtils::getGenericTECode(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 2696e5c31af7Sopenharmony_ci test_iteration.primitive_mode, test_iteration.vertex_ordering, 2697e5c31af7Sopenharmony_ci false); /* point mode */ 2698e5c31af7Sopenharmony_ci} 2699e5c31af7Sopenharmony_ci 2700e5c31af7Sopenharmony_ci/** Initializes test iterations for the test. The following modes and inner/outer tess level 2701e5c31af7Sopenharmony_ci * configurations are used to form the test set: 2702e5c31af7Sopenharmony_ci * 2703e5c31af7Sopenharmony_ci * - All inner/outer tessellation level combinations as returned by 2704e5c31af7Sopenharmony_ci * TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode() 2705e5c31af7Sopenharmony_ci * times 3 (for triangles) or 4 (for quads). For each combination, 2706e5c31af7Sopenharmony_ci * the test will capture tessellation coordinates multiple times, each 2707e5c31af7Sopenharmony_ci * time changing a different outer tessellation level value and leaving 2708e5c31af7Sopenharmony_ci * the rest intact. 2709e5c31af7Sopenharmony_ci * - All primitive modes; 2710e5c31af7Sopenharmony_ci * - All vertex spacing modes; 2711e5c31af7Sopenharmony_ci * 2712e5c31af7Sopenharmony_ci * All permutations are used to generate the test set. 2713e5c31af7Sopenharmony_ci **/ 2714e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule7Test::initTestIterations() 2715e5c31af7Sopenharmony_ci{ 2716e5c31af7Sopenharmony_ci DE_ASSERT(m_test_quads_iterations.size() == 0 && m_test_triangles_iterations.size() == 0); 2717e5c31af7Sopenharmony_ci 2718e5c31af7Sopenharmony_ci /* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */ 2719e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2720e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_gen_level_value = 0; 2721e5c31af7Sopenharmony_ci 2722e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value); 2723e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 2724e5c31af7Sopenharmony_ci 2725e5c31af7Sopenharmony_ci /* Iterate through all primitive and vertex spacing modes relevant to the test */ 2726e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, 2727e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES }; 2728e5c31af7Sopenharmony_ci _tessellation_shader_vertex_ordering vo_modes[] = { 2729e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_ORDERING_CCW, TESSELLATION_SHADER_VERTEX_ORDERING_CW, 2730e5c31af7Sopenharmony_ci }; 2731e5c31af7Sopenharmony_ci 2732e5c31af7Sopenharmony_ci const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]); 2733e5c31af7Sopenharmony_ci const unsigned int n_vo_modes = sizeof(vo_modes) / sizeof(vo_modes[0]); 2734e5c31af7Sopenharmony_ci 2735e5c31af7Sopenharmony_ci for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode) 2736e5c31af7Sopenharmony_ci { 2737e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode]; 2738e5c31af7Sopenharmony_ci const unsigned int n_relevant_outer_tess_levels = 2739e5c31af7Sopenharmony_ci (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS) ? 4 : 3; 2740e5c31af7Sopenharmony_ci 2741e5c31af7Sopenharmony_ci for (unsigned int n_vo_mode = 0; n_vo_mode < n_vo_modes; ++n_vo_mode) 2742e5c31af7Sopenharmony_ci { 2743e5c31af7Sopenharmony_ci _tessellation_shader_vertex_ordering vertex_ordering = vo_modes[n_vo_mode]; 2744e5c31af7Sopenharmony_ci 2745e5c31af7Sopenharmony_ci /* Retrieve inner/outer tessellation level combinations we want the tests to be run for */ 2746e5c31af7Sopenharmony_ci _tessellation_levels_set levels_set; 2747e5c31af7Sopenharmony_ci 2748e5c31af7Sopenharmony_ci levels_set = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode( 2749e5c31af7Sopenharmony_ci primitive_mode, gl_max_tess_gen_level_value, 2750e5c31af7Sopenharmony_ci TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE); 2751e5c31af7Sopenharmony_ci 2752e5c31af7Sopenharmony_ci /* Create test descriptor for all inner/outer level configurations we received from the utils function. */ 2753e5c31af7Sopenharmony_ci for (_tessellation_levels_set_const_iterator levels_set_iterator = levels_set.begin(); 2754e5c31af7Sopenharmony_ci levels_set_iterator != levels_set.end(); levels_set_iterator++) 2755e5c31af7Sopenharmony_ci { 2756e5c31af7Sopenharmony_ci const _tessellation_levels& levels = *levels_set_iterator; 2757e5c31af7Sopenharmony_ci 2758e5c31af7Sopenharmony_ci for (unsigned int n_outer_level_to_change = 0; 2759e5c31af7Sopenharmony_ci n_outer_level_to_change < n_relevant_outer_tess_levels + 1 /* base iteration */; 2760e5c31af7Sopenharmony_ci ++n_outer_level_to_change) 2761e5c31af7Sopenharmony_ci { 2762e5c31af7Sopenharmony_ci /* Create a test descriptor for all the parameters we now have */ 2763e5c31af7Sopenharmony_ci _test_iteration test; 2764e5c31af7Sopenharmony_ci 2765e5c31af7Sopenharmony_ci memcpy(test.inner_tess_levels, levels.inner, sizeof(test.inner_tess_levels)); 2766e5c31af7Sopenharmony_ci memcpy(test.outer_tess_levels, levels.outer, sizeof(test.outer_tess_levels)); 2767e5c31af7Sopenharmony_ci 2768e5c31af7Sopenharmony_ci test.primitive_mode = primitive_mode; 2769e5c31af7Sopenharmony_ci test.vertex_ordering = vertex_ordering; 2770e5c31af7Sopenharmony_ci 2771e5c31af7Sopenharmony_ci /* Change iteration-specific outer tessellation level to a different value, but only 2772e5c31af7Sopenharmony_ci * if we're not preparing a base iteration*/ 2773e5c31af7Sopenharmony_ci if (n_outer_level_to_change != n_relevant_outer_tess_levels) 2774e5c31af7Sopenharmony_ci { 2775e5c31af7Sopenharmony_ci test.n_modified_outer_tess_level = n_outer_level_to_change; 2776e5c31af7Sopenharmony_ci test.outer_tess_levels[n_outer_level_to_change] = (float)(gl_max_tess_gen_level_value) / 3.0f; 2777e5c31af7Sopenharmony_ci } 2778e5c31af7Sopenharmony_ci else 2779e5c31af7Sopenharmony_ci { 2780e5c31af7Sopenharmony_ci test.is_base_iteration = true; 2781e5c31af7Sopenharmony_ci } 2782e5c31af7Sopenharmony_ci 2783e5c31af7Sopenharmony_ci if (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES) 2784e5c31af7Sopenharmony_ci { 2785e5c31af7Sopenharmony_ci m_test_triangles_iterations.push_back(test); 2786e5c31af7Sopenharmony_ci } 2787e5c31af7Sopenharmony_ci else 2788e5c31af7Sopenharmony_ci { 2789e5c31af7Sopenharmony_ci m_test_quads_iterations.push_back(test); 2790e5c31af7Sopenharmony_ci } 2791e5c31af7Sopenharmony_ci } 2792e5c31af7Sopenharmony_ci } /* for (all levels set entries) */ 2793e5c31af7Sopenharmony_ci } /* for (all vertex spacing modes) */ 2794e5c31af7Sopenharmony_ci } /* for (all primitive modes) */ 2795e5c31af7Sopenharmony_ci} 2796e5c31af7Sopenharmony_ci 2797e5c31af7Sopenharmony_ci/** Tells whether a triangle is included in user-provided set of triangles. 2798e5c31af7Sopenharmony_ci * The triangle is expected to use an undefined vertex ordering. 2799e5c31af7Sopenharmony_ci * 2800e5c31af7Sopenharmony_ci * @param base_triangle_data 9 FP values defining 3 vertices of a triangle. 2801e5c31af7Sopenharmony_ci * @param vertex_data Vertex stream. It is expected these vertices 2802e5c31af7Sopenharmony_ci * form triangles. It is also assumed each vertex 2803e5c31af7Sopenharmony_ci * is expressed with 3 components. 2804e5c31af7Sopenharmony_ci * @param vertex_data_n_vertices Amount of vertices that can be found in @param 2805e5c31af7Sopenharmony_ci * vertex_data 2806e5c31af7Sopenharmony_ci * 2807e5c31af7Sopenharmony_ci * @return true if the triangle was found in user-provided triangle set, 2808e5c31af7Sopenharmony_ci * false otherwise. 2809e5c31af7Sopenharmony_ci * 2810e5c31af7Sopenharmony_ci **/ 2811e5c31af7Sopenharmony_cibool TessellationShaderInvarianceRule7Test::isTriangleDefinedInVertexDataSet(const float* base_triangle_data, 2812e5c31af7Sopenharmony_ci const float* vertex_data, 2813e5c31af7Sopenharmony_ci unsigned int vertex_data_n_vertices) 2814e5c31af7Sopenharmony_ci{ 2815e5c31af7Sopenharmony_ci bool result = false; 2816e5c31af7Sopenharmony_ci 2817e5c31af7Sopenharmony_ci for (unsigned int n_triangle = 0; n_triangle < vertex_data_n_vertices / 3 /* vertices per triangle */; n_triangle++) 2818e5c31af7Sopenharmony_ci { 2819e5c31af7Sopenharmony_ci const float* current_triangle_data = vertex_data + 2820e5c31af7Sopenharmony_ci n_triangle * 3 * /* vertices per triangle */ 2821e5c31af7Sopenharmony_ci 3; /* components */ 2822e5c31af7Sopenharmony_ci 2823e5c31af7Sopenharmony_ci if (TessellationShaderUtils::isTriangleDefined(current_triangle_data, base_triangle_data)) 2824e5c31af7Sopenharmony_ci { 2825e5c31af7Sopenharmony_ci result = true; 2826e5c31af7Sopenharmony_ci 2827e5c31af7Sopenharmony_ci break; 2828e5c31af7Sopenharmony_ci } 2829e5c31af7Sopenharmony_ci } /* for (all vertices) */ 2830e5c31af7Sopenharmony_ci 2831e5c31af7Sopenharmony_ci return result; 2832e5c31af7Sopenharmony_ci} 2833e5c31af7Sopenharmony_ci 2834e5c31af7Sopenharmony_ci/** Verifies result data. Accesses data generated by all iterations. 2835e5c31af7Sopenharmony_ci * 2836e5c31af7Sopenharmony_ci * Throws TestError exception if an error occurs. 2837e5c31af7Sopenharmony_ci * 2838e5c31af7Sopenharmony_ci * @param all_iterations_data An array of pointers to buffers, holding gl_TessCoord 2839e5c31af7Sopenharmony_ci * data generated by subsequent iterations. 2840e5c31af7Sopenharmony_ci **/ 2841e5c31af7Sopenharmony_civoid TessellationShaderInvarianceRule7Test::verifyResultData(const void** all_iterations_data) 2842e5c31af7Sopenharmony_ci{ 2843e5c31af7Sopenharmony_ci const float epsilon = 1e-5f; 2844e5c31af7Sopenharmony_ci 2845e5c31af7Sopenharmony_ci /* Run two separate iterations: 2846e5c31af7Sopenharmony_ci * 2847e5c31af7Sopenharmony_ci * a) triangles 2848e5c31af7Sopenharmony_ci * b) quads 2849e5c31af7Sopenharmony_ci */ 2850e5c31af7Sopenharmony_ci for (unsigned int n_iteration = 0; n_iteration < 2 /* triangles, quads */; ++n_iteration) 2851e5c31af7Sopenharmony_ci { 2852e5c31af7Sopenharmony_ci bool is_triangles_iteration = (n_iteration == 0); 2853e5c31af7Sopenharmony_ci const unsigned int n_base_iteration = 2854e5c31af7Sopenharmony_ci (n_iteration == 0) ? 0 : (unsigned int)m_test_triangles_iterations.size(); 2855e5c31af7Sopenharmony_ci const unsigned int n_relevant_outer_tess_levels = (is_triangles_iteration) ? 3 : 4; 2856e5c31af7Sopenharmony_ci 2857e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_mode = (n_iteration == 0) ? 2858e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES : 2859e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS; 2860e5c31af7Sopenharmony_ci 2861e5c31af7Sopenharmony_ci const _test_iterations& test_iterations = 2862e5c31af7Sopenharmony_ci (n_iteration == 0) ? m_test_triangles_iterations : m_test_quads_iterations; 2863e5c31af7Sopenharmony_ci 2864e5c31af7Sopenharmony_ci DE_ASSERT(test_iterations.size() != 0); 2865e5c31af7Sopenharmony_ci 2866e5c31af7Sopenharmony_ci /* Find a base iteration first */ 2867e5c31af7Sopenharmony_ci for (unsigned int n_base_test_iteration = 0; n_base_test_iteration < test_iterations.size(); 2868e5c31af7Sopenharmony_ci n_base_test_iteration++) 2869e5c31af7Sopenharmony_ci { 2870e5c31af7Sopenharmony_ci const _test_iteration& base_iteration = test_iterations[n_base_test_iteration]; 2871e5c31af7Sopenharmony_ci std::vector<int> ref_iteration_indices; 2872e5c31af7Sopenharmony_ci 2873e5c31af7Sopenharmony_ci if (!base_iteration.is_base_iteration) 2874e5c31af7Sopenharmony_ci { 2875e5c31af7Sopenharmony_ci continue; 2876e5c31af7Sopenharmony_ci } 2877e5c31af7Sopenharmony_ci 2878e5c31af7Sopenharmony_ci /* Retrieve reference test iterations */ 2879e5c31af7Sopenharmony_ci for (unsigned int n_reference_iteration = 0; n_reference_iteration < n_relevant_outer_tess_levels; 2880e5c31af7Sopenharmony_ci ++n_reference_iteration) 2881e5c31af7Sopenharmony_ci { 2882e5c31af7Sopenharmony_ci const unsigned int n_modified_outer_tess_level = 2883e5c31af7Sopenharmony_ci (base_iteration.n_modified_outer_tess_level + n_reference_iteration + 1) % 2884e5c31af7Sopenharmony_ci n_relevant_outer_tess_levels; 2885e5c31af7Sopenharmony_ci const unsigned int ref_iteration_index = getTestIterationIndex( 2886e5c31af7Sopenharmony_ci is_triangles_iteration, base_iteration.inner_tess_levels, base_iteration.outer_tess_levels, 2887e5c31af7Sopenharmony_ci base_iteration.vertex_ordering, n_modified_outer_tess_level); 2888e5c31af7Sopenharmony_ci 2889e5c31af7Sopenharmony_ci DE_ASSERT(ref_iteration_index != 0xFFFFFFFF); 2890e5c31af7Sopenharmony_ci DE_ASSERT(ref_iteration_index != n_base_test_iteration); 2891e5c31af7Sopenharmony_ci 2892e5c31af7Sopenharmony_ci ref_iteration_indices.push_back(ref_iteration_index); 2893e5c31af7Sopenharmony_ci } 2894e5c31af7Sopenharmony_ci 2895e5c31af7Sopenharmony_ci /* We can now start comparing base data with the information generated for 2896e5c31af7Sopenharmony_ci * reference iterations. */ 2897e5c31af7Sopenharmony_ci for (std::vector<int>::const_iterator ref_iteration_iterator = ref_iteration_indices.begin(); 2898e5c31af7Sopenharmony_ci ref_iteration_iterator != ref_iteration_indices.end(); ref_iteration_iterator++) 2899e5c31af7Sopenharmony_ci { 2900e5c31af7Sopenharmony_ci const int& n_ref_test_iteration = *ref_iteration_iterator; 2901e5c31af7Sopenharmony_ci const _test_iteration& ref_iteration = test_iterations[n_ref_test_iteration]; 2902e5c31af7Sopenharmony_ci 2903e5c31af7Sopenharmony_ci /* Now move through all triangles generated for base test iteration. Focus on the ones 2904e5c31af7Sopenharmony_ci * that connect the outer edge with one of the inner ones */ 2905e5c31af7Sopenharmony_ci const float* base_iteration_vertex_data = 2906e5c31af7Sopenharmony_ci (const float*)all_iterations_data[n_base_iteration + n_base_test_iteration]; 2907e5c31af7Sopenharmony_ci const float* ref_iteration_vertex_data = 2908e5c31af7Sopenharmony_ci (const float*)all_iterations_data[n_base_iteration + n_ref_test_iteration]; 2909e5c31af7Sopenharmony_ci 2910e5c31af7Sopenharmony_ci for (unsigned int n_base_triangle = 0; 2911e5c31af7Sopenharmony_ci n_base_triangle < base_iteration.n_vertices / 3; /* vertices per triangle */ 2912e5c31af7Sopenharmony_ci ++n_base_triangle) 2913e5c31af7Sopenharmony_ci { 2914e5c31af7Sopenharmony_ci const float* base_triangle_data = 2915e5c31af7Sopenharmony_ci base_iteration_vertex_data + n_base_triangle * 3 /* vertices */ * 3; /* components */ 2916e5c31af7Sopenharmony_ci 2917e5c31af7Sopenharmony_ci /* Is that the triangle type we're after? */ 2918e5c31af7Sopenharmony_ci const float* base_triangle_vertex1 = base_triangle_data; 2919e5c31af7Sopenharmony_ci const float* base_triangle_vertex2 = base_triangle_vertex1 + 3; /* components */ 2920e5c31af7Sopenharmony_ci const float* base_triangle_vertex3 = base_triangle_vertex2 + 3; /* components */ 2921e5c31af7Sopenharmony_ci bool is_base_triangle_vertex1_outer = 2922e5c31af7Sopenharmony_ci TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, base_triangle_vertex1); 2923e5c31af7Sopenharmony_ci bool is_base_triangle_vertex2_outer = 2924e5c31af7Sopenharmony_ci TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, base_triangle_vertex2); 2925e5c31af7Sopenharmony_ci bool is_base_triangle_vertex3_outer = 2926e5c31af7Sopenharmony_ci TessellationShaderUtils::isOuterEdgeVertex(primitive_mode, base_triangle_vertex3); 2927e5c31af7Sopenharmony_ci unsigned int n_outer_edge_vertices_found = 0; 2928e5c31af7Sopenharmony_ci 2929e5c31af7Sopenharmony_ci n_outer_edge_vertices_found += (is_base_triangle_vertex1_outer == true); 2930e5c31af7Sopenharmony_ci n_outer_edge_vertices_found += (is_base_triangle_vertex2_outer == true); 2931e5c31af7Sopenharmony_ci n_outer_edge_vertices_found += (is_base_triangle_vertex3_outer == true); 2932e5c31af7Sopenharmony_ci 2933e5c31af7Sopenharmony_ci if (n_outer_edge_vertices_found == 0) 2934e5c31af7Sopenharmony_ci { 2935e5c31af7Sopenharmony_ci /* This is an inner triangle, not really of our interest */ 2936e5c31af7Sopenharmony_ci continue; 2937e5c31af7Sopenharmony_ci } 2938e5c31af7Sopenharmony_ci 2939e5c31af7Sopenharmony_ci /* Which outer tessellation level describes the base data edge? */ 2940e5c31af7Sopenharmony_ci unsigned int n_base_tess_level = 0; 2941e5c31af7Sopenharmony_ci 2942e5c31af7Sopenharmony_ci if (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES) 2943e5c31af7Sopenharmony_ci { 2944e5c31af7Sopenharmony_ci if ((!is_base_triangle_vertex1_outer || 2945e5c31af7Sopenharmony_ci (is_base_triangle_vertex1_outer && base_triangle_vertex1[0] == 0.0f)) && 2946e5c31af7Sopenharmony_ci (!is_base_triangle_vertex2_outer || 2947e5c31af7Sopenharmony_ci (is_base_triangle_vertex2_outer && base_triangle_vertex2[0] == 0.0f)) && 2948e5c31af7Sopenharmony_ci (!is_base_triangle_vertex3_outer || 2949e5c31af7Sopenharmony_ci (is_base_triangle_vertex3_outer && base_triangle_vertex3[0] == 0.0f))) 2950e5c31af7Sopenharmony_ci { 2951e5c31af7Sopenharmony_ci n_base_tess_level = 0; 2952e5c31af7Sopenharmony_ci } 2953e5c31af7Sopenharmony_ci else if ((!is_base_triangle_vertex1_outer || 2954e5c31af7Sopenharmony_ci (is_base_triangle_vertex1_outer && base_triangle_vertex1[1] == 0.0f)) && 2955e5c31af7Sopenharmony_ci (!is_base_triangle_vertex2_outer || 2956e5c31af7Sopenharmony_ci (is_base_triangle_vertex2_outer && base_triangle_vertex2[1] == 0.0f)) && 2957e5c31af7Sopenharmony_ci (!is_base_triangle_vertex3_outer || 2958e5c31af7Sopenharmony_ci (is_base_triangle_vertex3_outer && base_triangle_vertex3[1] == 0.0f))) 2959e5c31af7Sopenharmony_ci { 2960e5c31af7Sopenharmony_ci n_base_tess_level = 1; 2961e5c31af7Sopenharmony_ci } 2962e5c31af7Sopenharmony_ci else 2963e5c31af7Sopenharmony_ci { 2964e5c31af7Sopenharmony_ci DE_ASSERT((!is_base_triangle_vertex1_outer || 2965e5c31af7Sopenharmony_ci (is_base_triangle_vertex1_outer && base_triangle_vertex1[2] == 0.0f)) && 2966e5c31af7Sopenharmony_ci (!is_base_triangle_vertex2_outer || 2967e5c31af7Sopenharmony_ci (is_base_triangle_vertex2_outer && base_triangle_vertex2[2] == 0.0f)) && 2968e5c31af7Sopenharmony_ci (!is_base_triangle_vertex3_outer || 2969e5c31af7Sopenharmony_ci (is_base_triangle_vertex3_outer && base_triangle_vertex3[2] == 0.0f))); 2970e5c31af7Sopenharmony_ci 2971e5c31af7Sopenharmony_ci n_base_tess_level = 2; 2972e5c31af7Sopenharmony_ci } 2973e5c31af7Sopenharmony_ci } /* if (primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES) */ 2974e5c31af7Sopenharmony_ci else 2975e5c31af7Sopenharmony_ci { 2976e5c31af7Sopenharmony_ci DE_ASSERT(primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS); 2977e5c31af7Sopenharmony_ci 2978e5c31af7Sopenharmony_ci std::size_t n_outer_edge_vertices = 0; 2979e5c31af7Sopenharmony_ci std::vector<const float*> outer_edge_vertices; 2980e5c31af7Sopenharmony_ci 2981e5c31af7Sopenharmony_ci if (is_base_triangle_vertex1_outer) 2982e5c31af7Sopenharmony_ci { 2983e5c31af7Sopenharmony_ci outer_edge_vertices.push_back(base_triangle_vertex1); 2984e5c31af7Sopenharmony_ci } 2985e5c31af7Sopenharmony_ci 2986e5c31af7Sopenharmony_ci if (is_base_triangle_vertex2_outer) 2987e5c31af7Sopenharmony_ci { 2988e5c31af7Sopenharmony_ci outer_edge_vertices.push_back(base_triangle_vertex2); 2989e5c31af7Sopenharmony_ci } 2990e5c31af7Sopenharmony_ci 2991e5c31af7Sopenharmony_ci if (is_base_triangle_vertex3_outer) 2992e5c31af7Sopenharmony_ci { 2993e5c31af7Sopenharmony_ci outer_edge_vertices.push_back(base_triangle_vertex3); 2994e5c31af7Sopenharmony_ci } 2995e5c31af7Sopenharmony_ci 2996e5c31af7Sopenharmony_ci n_outer_edge_vertices = outer_edge_vertices.size(); 2997e5c31af7Sopenharmony_ci 2998e5c31af7Sopenharmony_ci DE_ASSERT(n_outer_edge_vertices >= 1 && n_outer_edge_vertices <= 2); 2999e5c31af7Sopenharmony_ci 3000e5c31af7Sopenharmony_ci bool is_top_outer_edge = true; 3001e5c31af7Sopenharmony_ci bool is_right_outer_edge = true; 3002e5c31af7Sopenharmony_ci bool is_bottom_outer_edge = true; 3003e5c31af7Sopenharmony_ci bool is_left_outer_edge = true; 3004e5c31af7Sopenharmony_ci 3005e5c31af7Sopenharmony_ci /* Find which outer edges the vertices don't belong to. If one is in a corner, 3006e5c31af7Sopenharmony_ci * the other will clarify to which edge both vertices belong. */ 3007e5c31af7Sopenharmony_ci for (unsigned int n_vertex = 0; n_vertex < n_outer_edge_vertices; ++n_vertex) 3008e5c31af7Sopenharmony_ci { 3009e5c31af7Sopenharmony_ci /* Y < 1, not top outer edge */ 3010e5c31af7Sopenharmony_ci if (de::abs(outer_edge_vertices[n_vertex][1] - 1.0f) > epsilon) 3011e5c31af7Sopenharmony_ci { 3012e5c31af7Sopenharmony_ci is_top_outer_edge = false; 3013e5c31af7Sopenharmony_ci } 3014e5c31af7Sopenharmony_ci 3015e5c31af7Sopenharmony_ci /* X < 1, not right outer edge */ 3016e5c31af7Sopenharmony_ci if (de::abs(outer_edge_vertices[n_vertex][0] - 1.0f) > epsilon) 3017e5c31af7Sopenharmony_ci { 3018e5c31af7Sopenharmony_ci is_right_outer_edge = false; 3019e5c31af7Sopenharmony_ci } 3020e5c31af7Sopenharmony_ci 3021e5c31af7Sopenharmony_ci /* Y > 0, not bottom outer edge */ 3022e5c31af7Sopenharmony_ci if (de::abs(outer_edge_vertices[n_vertex][1]) > epsilon) 3023e5c31af7Sopenharmony_ci { 3024e5c31af7Sopenharmony_ci is_bottom_outer_edge = false; 3025e5c31af7Sopenharmony_ci } 3026e5c31af7Sopenharmony_ci 3027e5c31af7Sopenharmony_ci /* X > 0, not left outer edge */ 3028e5c31af7Sopenharmony_ci if (de::abs(outer_edge_vertices[n_vertex][0]) > epsilon) 3029e5c31af7Sopenharmony_ci { 3030e5c31af7Sopenharmony_ci is_left_outer_edge = false; 3031e5c31af7Sopenharmony_ci } 3032e5c31af7Sopenharmony_ci } 3033e5c31af7Sopenharmony_ci 3034e5c31af7Sopenharmony_ci if (n_outer_edge_vertices == 1) 3035e5c31af7Sopenharmony_ci { 3036e5c31af7Sopenharmony_ci /* A single vertex with corner-coordinates belongs to two edges. Choose one */ 3037e5c31af7Sopenharmony_ci bool x_is_0 = de::abs(outer_edge_vertices[0][0]) < epsilon; 3038e5c31af7Sopenharmony_ci bool x_is_1 = de::abs(outer_edge_vertices[0][0] - 1.0f) < epsilon; 3039e5c31af7Sopenharmony_ci bool y_is_0 = de::abs(outer_edge_vertices[0][1]) < epsilon; 3040e5c31af7Sopenharmony_ci bool y_is_1 = de::abs(outer_edge_vertices[0][1] - 1.0f) < epsilon; 3041e5c31af7Sopenharmony_ci 3042e5c31af7Sopenharmony_ci if (x_is_0 && y_is_0) 3043e5c31af7Sopenharmony_ci { 3044e5c31af7Sopenharmony_ci /* bottom edge */ 3045e5c31af7Sopenharmony_ci DE_ASSERT(is_left_outer_edge && is_bottom_outer_edge); 3046e5c31af7Sopenharmony_ci is_left_outer_edge = false; 3047e5c31af7Sopenharmony_ci } 3048e5c31af7Sopenharmony_ci else if (x_is_0 && y_is_1) 3049e5c31af7Sopenharmony_ci { 3050e5c31af7Sopenharmony_ci /* left edge */ 3051e5c31af7Sopenharmony_ci DE_ASSERT(is_left_outer_edge && is_top_outer_edge); 3052e5c31af7Sopenharmony_ci is_top_outer_edge = false; 3053e5c31af7Sopenharmony_ci } 3054e5c31af7Sopenharmony_ci else if (x_is_1 && y_is_0) 3055e5c31af7Sopenharmony_ci { 3056e5c31af7Sopenharmony_ci /* right edge */ 3057e5c31af7Sopenharmony_ci DE_ASSERT(is_right_outer_edge && is_bottom_outer_edge); 3058e5c31af7Sopenharmony_ci is_bottom_outer_edge = false; 3059e5c31af7Sopenharmony_ci } 3060e5c31af7Sopenharmony_ci else if (x_is_1 && y_is_1) 3061e5c31af7Sopenharmony_ci { 3062e5c31af7Sopenharmony_ci /* top edge */ 3063e5c31af7Sopenharmony_ci DE_ASSERT(is_right_outer_edge && is_top_outer_edge); 3064e5c31af7Sopenharmony_ci is_right_outer_edge = false; 3065e5c31af7Sopenharmony_ci } 3066e5c31af7Sopenharmony_ci else 3067e5c31af7Sopenharmony_ci { 3068e5c31af7Sopenharmony_ci /* Not a corner vertex, only one of the edge-flags is set */ 3069e5c31af7Sopenharmony_ci } 3070e5c31af7Sopenharmony_ci } 3071e5c31af7Sopenharmony_ci 3072e5c31af7Sopenharmony_ci /* Quick checks */ 3073e5c31af7Sopenharmony_ci DE_UNREF(is_top_outer_edge); 3074e5c31af7Sopenharmony_ci DE_ASSERT((is_left_outer_edge && !is_top_outer_edge && !is_bottom_outer_edge && 3075e5c31af7Sopenharmony_ci !is_right_outer_edge) || 3076e5c31af7Sopenharmony_ci (!is_left_outer_edge && is_top_outer_edge && !is_bottom_outer_edge && 3077e5c31af7Sopenharmony_ci !is_right_outer_edge) || 3078e5c31af7Sopenharmony_ci (!is_left_outer_edge && !is_top_outer_edge && is_bottom_outer_edge && 3079e5c31af7Sopenharmony_ci !is_right_outer_edge) || 3080e5c31af7Sopenharmony_ci (!is_left_outer_edge && !is_top_outer_edge && !is_bottom_outer_edge && 3081e5c31af7Sopenharmony_ci is_right_outer_edge)); 3082e5c31af7Sopenharmony_ci 3083e5c31af7Sopenharmony_ci /* We have all the data needed to determine which tessellation level describes 3084e5c31af7Sopenharmony_ci * subdivision of the edge that the triangle touches */ 3085e5c31af7Sopenharmony_ci if (is_left_outer_edge) 3086e5c31af7Sopenharmony_ci { 3087e5c31af7Sopenharmony_ci n_base_tess_level = 0; 3088e5c31af7Sopenharmony_ci } 3089e5c31af7Sopenharmony_ci else if (is_bottom_outer_edge) 3090e5c31af7Sopenharmony_ci { 3091e5c31af7Sopenharmony_ci n_base_tess_level = 1; 3092e5c31af7Sopenharmony_ci } 3093e5c31af7Sopenharmony_ci else if (is_right_outer_edge) 3094e5c31af7Sopenharmony_ci { 3095e5c31af7Sopenharmony_ci n_base_tess_level = 2; 3096e5c31af7Sopenharmony_ci } 3097e5c31af7Sopenharmony_ci else 3098e5c31af7Sopenharmony_ci { 3099e5c31af7Sopenharmony_ci n_base_tess_level = 3; 3100e5c31af7Sopenharmony_ci } 3101e5c31af7Sopenharmony_ci } 3102e5c31af7Sopenharmony_ci 3103e5c31af7Sopenharmony_ci /* We shouldn't perform the check if the edge we're processing was described 3104e5c31af7Sopenharmony_ci * by a different outer tessellation level in the reference data set */ 3105e5c31af7Sopenharmony_ci if (n_base_tess_level == ref_iteration.n_modified_outer_tess_level) 3106e5c31af7Sopenharmony_ci { 3107e5c31af7Sopenharmony_ci continue; 3108e5c31af7Sopenharmony_ci } 3109e5c31af7Sopenharmony_ci 3110e5c31af7Sopenharmony_ci /* This triangle should be present in both vertex data sets */ 3111e5c31af7Sopenharmony_ci if (!isTriangleDefinedInVertexDataSet(base_triangle_data, ref_iteration_vertex_data, 3112e5c31af7Sopenharmony_ci ref_iteration.n_vertices)) 3113e5c31af7Sopenharmony_ci { 3114e5c31af7Sopenharmony_ci const char* primitive_mode_str = (is_triangles_iteration) ? "triangles" : "quads"; 3115e5c31af7Sopenharmony_ci 3116e5c31af7Sopenharmony_ci m_testCtx.getLog() 3117e5c31af7Sopenharmony_ci << tcu::TestLog::Message << "For primitive mode [" << primitive_mode_str << "] " 3118e5c31af7Sopenharmony_ci << ", inner tessellation levels:" 3119e5c31af7Sopenharmony_ci << "[" << base_iteration.inner_tess_levels[0] << ", " << base_iteration.inner_tess_levels[1] 3120e5c31af7Sopenharmony_ci << "], outer tessellation levels:" 3121e5c31af7Sopenharmony_ci << "[" << base_iteration.outer_tess_levels[0] << ", " << base_iteration.outer_tess_levels[1] 3122e5c31af7Sopenharmony_ci << ", " << base_iteration.outer_tess_levels[2] << ", " 3123e5c31af7Sopenharmony_ci << base_iteration.outer_tess_levels[3] << "], a triangle connecting inner & outer edges:" 3124e5c31af7Sopenharmony_ci << "[" << base_triangle_vertex1[0] << ", " << base_triangle_vertex1[1] << ", " 3125e5c31af7Sopenharmony_ci << base_triangle_vertex1[2] << "]x" 3126e5c31af7Sopenharmony_ci << "[" << base_triangle_vertex2[0] << ", " << base_triangle_vertex2[1] << ", " 3127e5c31af7Sopenharmony_ci << base_triangle_vertex2[2] << "]x" 3128e5c31af7Sopenharmony_ci << "[" << base_triangle_vertex3[0] << ", " << base_triangle_vertex3[1] << ", " 3129e5c31af7Sopenharmony_ci << base_triangle_vertex3[2] << "] was not found for runs using CW and CCW vertex ordering, " 3130e5c31af7Sopenharmony_ci "which is against the extension specification's rule 7." 3131e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 3132e5c31af7Sopenharmony_ci 3133e5c31af7Sopenharmony_ci TCU_FAIL("Implementation is not conformant with Tessellation Rule 7"); 3134e5c31af7Sopenharmony_ci } 3135e5c31af7Sopenharmony_ci } /* for (all triangles generated for base test iteration) */ 3136e5c31af7Sopenharmony_ci } /* for (all reference iterations) */ 3137e5c31af7Sopenharmony_ci } /* for (all base test iterations) */ 3138e5c31af7Sopenharmony_ci } /* for (both primitive types) */ 3139e5c31af7Sopenharmony_ci} 3140e5c31af7Sopenharmony_ci 3141e5c31af7Sopenharmony_ci} /* namespace glcts */ 3142