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 "esextcTessellationShaderPoints.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_ciconst unsigned int TessellationShaderPointsgl_PointSize::m_rt_height = 35e5c31af7Sopenharmony_ci 16; /* note: update shaders if you change this value */ 36e5c31af7Sopenharmony_ciconst unsigned int TessellationShaderPointsgl_PointSize::m_rt_width = 37e5c31af7Sopenharmony_ci 16; /* note: update shaders if you change this value */ 38e5c31af7Sopenharmony_ci 39e5c31af7Sopenharmony_ci/** Constructor 40e5c31af7Sopenharmony_ci * 41e5c31af7Sopenharmony_ci * @param context Test context 42e5c31af7Sopenharmony_ci **/ 43e5c31af7Sopenharmony_ciTessellationShaderPointsTests::TessellationShaderPointsTests(glcts::Context& context, const ExtParameters& extParams) 44e5c31af7Sopenharmony_ci : TestCaseGroupBase(context, extParams, "tessellation_shader_point_mode", "Verifies point mode functionality") 45e5c31af7Sopenharmony_ci{ 46e5c31af7Sopenharmony_ci /* No implementation needed */ 47e5c31af7Sopenharmony_ci} 48e5c31af7Sopenharmony_ci 49e5c31af7Sopenharmony_ci/** 50e5c31af7Sopenharmony_ci * Initializes test groups for geometry shader tests 51e5c31af7Sopenharmony_ci **/ 52e5c31af7Sopenharmony_civoid TessellationShaderPointsTests::init(void) 53e5c31af7Sopenharmony_ci{ 54e5c31af7Sopenharmony_ci addChild(new glcts::TessellationShaderPointsgl_PointSize(m_context, m_extParams)); 55e5c31af7Sopenharmony_ci addChild(new glcts::TessellationShaderPointsVerification(m_context, m_extParams)); 56e5c31af7Sopenharmony_ci} 57e5c31af7Sopenharmony_ci 58e5c31af7Sopenharmony_ci/** Constructor 59e5c31af7Sopenharmony_ci * 60e5c31af7Sopenharmony_ci * @param context Test context 61e5c31af7Sopenharmony_ci * @param name Test case's name 62e5c31af7Sopenharmony_ci * @param description Test case's desricption 63e5c31af7Sopenharmony_ci **/ 64e5c31af7Sopenharmony_ciTessellationShaderPointsgl_PointSize::TessellationShaderPointsgl_PointSize(Context& context, 65e5c31af7Sopenharmony_ci const ExtParameters& extParams) 66e5c31af7Sopenharmony_ci : TestCaseBase(context, extParams, "point_rendering", "Verifies point size used to render points is taken from" 67e5c31af7Sopenharmony_ci " the right stage") 68e5c31af7Sopenharmony_ci , m_fbo_id(0) 69e5c31af7Sopenharmony_ci , m_to_id(0) 70e5c31af7Sopenharmony_ci , m_vao_id(0) 71e5c31af7Sopenharmony_ci{ 72e5c31af7Sopenharmony_ci /* Left blank on purpose */ 73e5c31af7Sopenharmony_ci} 74e5c31af7Sopenharmony_ci 75e5c31af7Sopenharmony_ci/** Deinitializes all ES objects created for the test. */ 76e5c31af7Sopenharmony_civoid TessellationShaderPointsgl_PointSize::deinit() 77e5c31af7Sopenharmony_ci{ 78e5c31af7Sopenharmony_ci /** Call base class' deinit() function */ 79e5c31af7Sopenharmony_ci TestCaseBase::deinit(); 80e5c31af7Sopenharmony_ci 81e5c31af7Sopenharmony_ci if (!m_is_tessellation_shader_supported) 82e5c31af7Sopenharmony_ci { 83e5c31af7Sopenharmony_ci return; 84e5c31af7Sopenharmony_ci } 85e5c31af7Sopenharmony_ci 86e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 87e5c31af7Sopenharmony_ci 88e5c31af7Sopenharmony_ci if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 89e5c31af7Sopenharmony_ci { 90e5c31af7Sopenharmony_ci /* Disable point size */ 91e5c31af7Sopenharmony_ci gl.disable(GL_PROGRAM_POINT_SIZE); 92e5c31af7Sopenharmony_ci } 93e5c31af7Sopenharmony_ci 94e5c31af7Sopenharmony_ci /* Reset the program object */ 95e5c31af7Sopenharmony_ci gl.useProgram(0); 96e5c31af7Sopenharmony_ci 97e5c31af7Sopenharmony_ci /* Revert GL_PATCH_VERTICES_EXT to default value */ 98e5c31af7Sopenharmony_ci gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3); 99e5c31af7Sopenharmony_ci 100e5c31af7Sopenharmony_ci /* Unbind vertex array object */ 101e5c31af7Sopenharmony_ci gl.bindVertexArray(0); 102e5c31af7Sopenharmony_ci 103e5c31af7Sopenharmony_ci /* Deinitialize test-specific objects */ 104e5c31af7Sopenharmony_ci for (_tests_iterator it = m_tests.begin(); it != m_tests.end(); ++it) 105e5c31af7Sopenharmony_ci { 106e5c31af7Sopenharmony_ci const _test_descriptor& test = *it; 107e5c31af7Sopenharmony_ci 108e5c31af7Sopenharmony_ci if (test.fs_id != 0) 109e5c31af7Sopenharmony_ci { 110e5c31af7Sopenharmony_ci gl.deleteShader(test.fs_id); 111e5c31af7Sopenharmony_ci } 112e5c31af7Sopenharmony_ci 113e5c31af7Sopenharmony_ci if (test.gs_id != 0) 114e5c31af7Sopenharmony_ci { 115e5c31af7Sopenharmony_ci gl.deleteShader(test.gs_id); 116e5c31af7Sopenharmony_ci } 117e5c31af7Sopenharmony_ci 118e5c31af7Sopenharmony_ci if (test.po_id != 0) 119e5c31af7Sopenharmony_ci { 120e5c31af7Sopenharmony_ci gl.deleteProgram(test.po_id); 121e5c31af7Sopenharmony_ci } 122e5c31af7Sopenharmony_ci 123e5c31af7Sopenharmony_ci if (test.tes_id != 0) 124e5c31af7Sopenharmony_ci { 125e5c31af7Sopenharmony_ci gl.deleteShader(test.tes_id); 126e5c31af7Sopenharmony_ci } 127e5c31af7Sopenharmony_ci 128e5c31af7Sopenharmony_ci if (test.tcs_id != 0) 129e5c31af7Sopenharmony_ci { 130e5c31af7Sopenharmony_ci gl.deleteShader(test.tcs_id); 131e5c31af7Sopenharmony_ci } 132e5c31af7Sopenharmony_ci 133e5c31af7Sopenharmony_ci if (test.vs_id != 0) 134e5c31af7Sopenharmony_ci { 135e5c31af7Sopenharmony_ci gl.deleteShader(test.vs_id); 136e5c31af7Sopenharmony_ci } 137e5c31af7Sopenharmony_ci } 138e5c31af7Sopenharmony_ci m_tests.clear(); 139e5c31af7Sopenharmony_ci 140e5c31af7Sopenharmony_ci if (m_fbo_id != 0) 141e5c31af7Sopenharmony_ci { 142e5c31af7Sopenharmony_ci gl.deleteFramebuffers(1, &m_fbo_id); 143e5c31af7Sopenharmony_ci 144e5c31af7Sopenharmony_ci m_fbo_id = 0; 145e5c31af7Sopenharmony_ci } 146e5c31af7Sopenharmony_ci 147e5c31af7Sopenharmony_ci if (m_to_id != 0) 148e5c31af7Sopenharmony_ci { 149e5c31af7Sopenharmony_ci gl.deleteTextures(1, &m_to_id); 150e5c31af7Sopenharmony_ci 151e5c31af7Sopenharmony_ci m_to_id = 0; 152e5c31af7Sopenharmony_ci } 153e5c31af7Sopenharmony_ci 154e5c31af7Sopenharmony_ci if (m_vao_id != 0) 155e5c31af7Sopenharmony_ci { 156e5c31af7Sopenharmony_ci gl.deleteVertexArrays(1, &m_vao_id); 157e5c31af7Sopenharmony_ci 158e5c31af7Sopenharmony_ci m_vao_id = 0; 159e5c31af7Sopenharmony_ci } 160e5c31af7Sopenharmony_ci} 161e5c31af7Sopenharmony_ci 162e5c31af7Sopenharmony_ci/** Initializes all ES objects that will be used for the test. */ 163e5c31af7Sopenharmony_civoid TessellationShaderPointsgl_PointSize::initTest() 164e5c31af7Sopenharmony_ci{ 165e5c31af7Sopenharmony_ci /* The test should only execute if maximum point size is at least 2 */ 166e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 167e5c31af7Sopenharmony_ci glw::GLint gl_max_point_size_value[2] = { 0 }; 168e5c31af7Sopenharmony_ci const int min_max_point_size = 2; 169e5c31af7Sopenharmony_ci 170e5c31af7Sopenharmony_ci if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 171e5c31af7Sopenharmony_ci { 172e5c31af7Sopenharmony_ci gl.getIntegerv(GL_POINT_SIZE_RANGE, gl_max_point_size_value); 173e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() for GL_POINT_SIZE_RANGE failed."); 174e5c31af7Sopenharmony_ci } 175e5c31af7Sopenharmony_ci else 176e5c31af7Sopenharmony_ci { 177e5c31af7Sopenharmony_ci gl.getIntegerv(GL_ALIASED_POINT_SIZE_RANGE, gl_max_point_size_value); 178e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() for GL_ALIASED_POINT_SIZE_RANGE failed."); 179e5c31af7Sopenharmony_ci } 180e5c31af7Sopenharmony_ci 181e5c31af7Sopenharmony_ci if (gl_max_point_size_value[1] < min_max_point_size) 182e5c31af7Sopenharmony_ci { 183e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Maximum point size is lower than 2."); 184e5c31af7Sopenharmony_ci } 185e5c31af7Sopenharmony_ci 186e5c31af7Sopenharmony_ci /* The test requires EXT_tessellation_shader, EXT_tessellation_shader_point_size */ 187e5c31af7Sopenharmony_ci if (!m_is_tessellation_shader_supported || !m_is_tessellation_shader_point_size_supported) 188e5c31af7Sopenharmony_ci { 189e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("At least one of the required extensions is not supported."); 190e5c31af7Sopenharmony_ci } 191e5c31af7Sopenharmony_ci 192e5c31af7Sopenharmony_ci /* Initialize vertex array object */ 193e5c31af7Sopenharmony_ci gl.genVertexArrays(1, &m_vao_id); 194e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 195e5c31af7Sopenharmony_ci 196e5c31af7Sopenharmony_ci gl.bindVertexArray(m_vao_id); 197e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 198e5c31af7Sopenharmony_ci 199e5c31af7Sopenharmony_ci /* Initialize fs+gs+vs test descriptor */ 200e5c31af7Sopenharmony_ci if (m_is_geometry_shader_extension_supported) 201e5c31af7Sopenharmony_ci { 202e5c31af7Sopenharmony_ci _test_descriptor pass_fs_gs_tes_vs; 203e5c31af7Sopenharmony_ci 204e5c31af7Sopenharmony_ci /* Configure shader bodies */ 205e5c31af7Sopenharmony_ci pass_fs_gs_tes_vs.fs_body = "${VERSION}\n" 206e5c31af7Sopenharmony_ci "\n" 207e5c31af7Sopenharmony_ci "precision highp float;\n" 208e5c31af7Sopenharmony_ci "\n" 209e5c31af7Sopenharmony_ci "in vec4 color;\n" 210e5c31af7Sopenharmony_ci "out vec4 result;\n" 211e5c31af7Sopenharmony_ci "\n" 212e5c31af7Sopenharmony_ci "void main()\n" 213e5c31af7Sopenharmony_ci "{\n" 214e5c31af7Sopenharmony_ci " result = color;\n" 215e5c31af7Sopenharmony_ci "}\n"; 216e5c31af7Sopenharmony_ci 217e5c31af7Sopenharmony_ci pass_fs_gs_tes_vs.gs_body = "${VERSION}\n" 218e5c31af7Sopenharmony_ci "\n" 219e5c31af7Sopenharmony_ci "${GEOMETRY_SHADER_REQUIRE}\n" 220e5c31af7Sopenharmony_ci "${GEOMETRY_POINT_SIZE_REQUIRE}\n" 221e5c31af7Sopenharmony_ci "\n" 222e5c31af7Sopenharmony_ci "layout(points) in;\n" 223e5c31af7Sopenharmony_ci "layout(points, max_vertices=5) out;\n" 224e5c31af7Sopenharmony_ci "\n" 225e5c31af7Sopenharmony_ci "out vec4 color;\n" 226e5c31af7Sopenharmony_ci "\n" 227e5c31af7Sopenharmony_ci "void main()\n" 228e5c31af7Sopenharmony_ci "{\n" 229e5c31af7Sopenharmony_ci " const float point_dx = 2.0 / 16.0 /* rendertarget width */;\n" 230e5c31af7Sopenharmony_ci " const float point_dy = 2.0 / 16.0 /* rendertarget_height */;\n" 231e5c31af7Sopenharmony_ci "\n" 232e5c31af7Sopenharmony_ci /* Center */ 233e5c31af7Sopenharmony_ci " color = vec4(0.1, 0.2, 0.3, 0.4);\n" 234e5c31af7Sopenharmony_ci " gl_PointSize = 2.0;\n" 235e5c31af7Sopenharmony_ci " gl_Position = vec4(point_dx + 0.0, point_dy + 0.0, 0.0, 1.0);\n" 236e5c31af7Sopenharmony_ci " EmitVertex();\n" 237e5c31af7Sopenharmony_ci "\n" 238e5c31af7Sopenharmony_ci /* Top-left corner */ 239e5c31af7Sopenharmony_ci " color = vec4(0.2, 0.3, 0.4, 0.5);\n" 240e5c31af7Sopenharmony_ci " gl_PointSize = 2.0;\n" 241e5c31af7Sopenharmony_ci " gl_Position = vec4(point_dx - 1.0, -point_dy + 1.0, 0.0, 1.0);\n" 242e5c31af7Sopenharmony_ci " EmitVertex();\n" 243e5c31af7Sopenharmony_ci "\n" 244e5c31af7Sopenharmony_ci /* Top-right corner */ 245e5c31af7Sopenharmony_ci " color = vec4(0.3, 0.4, 0.5, 0.6);\n" 246e5c31af7Sopenharmony_ci " gl_PointSize = 2.0;\n" 247e5c31af7Sopenharmony_ci " gl_Position = vec4(-point_dx + 1.0, -point_dy + 1.0, 0.0, 1.0);\n" 248e5c31af7Sopenharmony_ci " EmitVertex();\n" 249e5c31af7Sopenharmony_ci "\n" 250e5c31af7Sopenharmony_ci /* Bottom-left corner */ 251e5c31af7Sopenharmony_ci " color = vec4(0.4, 0.5, 0.6, 0.7);\n" 252e5c31af7Sopenharmony_ci " gl_PointSize = 2.0;\n" 253e5c31af7Sopenharmony_ci " gl_Position = vec4(point_dx - 1.0, point_dy - 1.0, 0.0, 1.0);\n" 254e5c31af7Sopenharmony_ci " EmitVertex();\n" 255e5c31af7Sopenharmony_ci "\n" 256e5c31af7Sopenharmony_ci /* Bottom-right corner */ 257e5c31af7Sopenharmony_ci " color = vec4(0.5, 0.6, 0.7, 0.8);\n" 258e5c31af7Sopenharmony_ci " gl_PointSize = 2.0;\n" 259e5c31af7Sopenharmony_ci " gl_Position = vec4(-point_dx + 1.0, point_dy - 1.0, 0.0, 1.0);\n" 260e5c31af7Sopenharmony_ci " EmitVertex();\n" 261e5c31af7Sopenharmony_ci "\n" 262e5c31af7Sopenharmony_ci "}\n"; 263e5c31af7Sopenharmony_ci 264e5c31af7Sopenharmony_ci pass_fs_gs_tes_vs.tes_body = "${VERSION}\n" 265e5c31af7Sopenharmony_ci "\n" 266e5c31af7Sopenharmony_ci "${TESSELLATION_SHADER_REQUIRE}\n" 267e5c31af7Sopenharmony_ci "${TESSELLATION_POINT_SIZE_REQUIRE}\n" 268e5c31af7Sopenharmony_ci "\n" 269e5c31af7Sopenharmony_ci "layout(isolines, point_mode) in;\n" 270e5c31af7Sopenharmony_ci "\n" 271e5c31af7Sopenharmony_ci "void main()\n" 272e5c31af7Sopenharmony_ci "{\n" 273e5c31af7Sopenharmony_ci " gl_PointSize = 0.1;\n" 274e5c31af7Sopenharmony_ci "}\n"; 275e5c31af7Sopenharmony_ci 276e5c31af7Sopenharmony_ci pass_fs_gs_tes_vs.tcs_body = "${VERSION}\n" 277e5c31af7Sopenharmony_ci "\n" 278e5c31af7Sopenharmony_ci "${TESSELLATION_SHADER_REQUIRE}\n" 279e5c31af7Sopenharmony_ci "${TESSELLATION_POINT_SIZE_REQUIRE}\n" 280e5c31af7Sopenharmony_ci "\n" 281e5c31af7Sopenharmony_ci "layout(vertices=1) out;\n" 282e5c31af7Sopenharmony_ci "\n" 283e5c31af7Sopenharmony_ci "void main()\n" 284e5c31af7Sopenharmony_ci "{\n" 285e5c31af7Sopenharmony_ci " gl_out[gl_InvocationID].gl_Position =\n" 286e5c31af7Sopenharmony_ci " gl_in[gl_InvocationID].gl_Position;\n" 287e5c31af7Sopenharmony_ci " gl_out[gl_InvocationID].gl_PointSize =\n" 288e5c31af7Sopenharmony_ci " gl_in[gl_InvocationID].gl_PointSize;\n" 289e5c31af7Sopenharmony_ci "\n" 290e5c31af7Sopenharmony_ci " gl_TessLevelOuter[0] = 1.0;\n" 291e5c31af7Sopenharmony_ci " gl_TessLevelOuter[1] = 1.0;\n" 292e5c31af7Sopenharmony_ci " gl_TessLevelOuter[2] = 1.0;\n" 293e5c31af7Sopenharmony_ci " gl_TessLevelOuter[3] = 1.0;\n" 294e5c31af7Sopenharmony_ci " gl_TessLevelInner[0] = 1.0;\n" 295e5c31af7Sopenharmony_ci " gl_TessLevelInner[1] = 1.0;\n" 296e5c31af7Sopenharmony_ci "}\n"; 297e5c31af7Sopenharmony_ci 298e5c31af7Sopenharmony_ci pass_fs_gs_tes_vs.vs_body = "${VERSION}\n" 299e5c31af7Sopenharmony_ci "\n" 300e5c31af7Sopenharmony_ci "void main()\n" 301e5c31af7Sopenharmony_ci "{\n" 302e5c31af7Sopenharmony_ci " gl_PointSize = 0.01;\n" 303e5c31af7Sopenharmony_ci "}\n"; 304e5c31af7Sopenharmony_ci 305e5c31af7Sopenharmony_ci pass_fs_gs_tes_vs.draw_call_count = 1; 306e5c31af7Sopenharmony_ci 307e5c31af7Sopenharmony_ci /* Store the descriptor in a vector that will be used by iterate() */ 308e5c31af7Sopenharmony_ci m_tests.push_back(pass_fs_gs_tes_vs); 309e5c31af7Sopenharmony_ci } /* if (m_is_geometry_shader_extension_supported) */ 310e5c31af7Sopenharmony_ci 311e5c31af7Sopenharmony_ci /* Initialize fs+te+vs test descriptor */ 312e5c31af7Sopenharmony_ci if (m_is_tessellation_shader_supported) 313e5c31af7Sopenharmony_ci { 314e5c31af7Sopenharmony_ci _test_descriptor pass_fs_tes_vs; 315e5c31af7Sopenharmony_ci 316e5c31af7Sopenharmony_ci /* Configure shader bodies */ 317e5c31af7Sopenharmony_ci pass_fs_tes_vs.fs_body = "${VERSION}\n" 318e5c31af7Sopenharmony_ci "\n" 319e5c31af7Sopenharmony_ci "precision highp float;\n" 320e5c31af7Sopenharmony_ci "\n" 321e5c31af7Sopenharmony_ci "in vec4 result_color;\n" 322e5c31af7Sopenharmony_ci "out vec4 result;\n" 323e5c31af7Sopenharmony_ci "\n" 324e5c31af7Sopenharmony_ci "void main()\n" 325e5c31af7Sopenharmony_ci "{\n" 326e5c31af7Sopenharmony_ci " result = result_color;\n" 327e5c31af7Sopenharmony_ci "}\n"; 328e5c31af7Sopenharmony_ci 329e5c31af7Sopenharmony_ci pass_fs_tes_vs.tes_body = "${VERSION}\n" 330e5c31af7Sopenharmony_ci "\n" 331e5c31af7Sopenharmony_ci "${TESSELLATION_SHADER_REQUIRE}\n" 332e5c31af7Sopenharmony_ci "${TESSELLATION_POINT_SIZE_REQUIRE}\n" 333e5c31af7Sopenharmony_ci "\n" 334e5c31af7Sopenharmony_ci "layout(isolines, point_mode) in;\n" 335e5c31af7Sopenharmony_ci "\n" 336e5c31af7Sopenharmony_ci "in vec4 tcColor[];\n" 337e5c31af7Sopenharmony_ci "out vec4 result_color;\n" 338e5c31af7Sopenharmony_ci "\n" 339e5c31af7Sopenharmony_ci "void main()\n" 340e5c31af7Sopenharmony_ci "{\n" 341e5c31af7Sopenharmony_ci " gl_PointSize = 2.0;\n" 342e5c31af7Sopenharmony_ci " gl_Position = gl_in[0].gl_Position;\n" 343e5c31af7Sopenharmony_ci " result_color = tcColor[0];\n" 344e5c31af7Sopenharmony_ci "}\n"; 345e5c31af7Sopenharmony_ci 346e5c31af7Sopenharmony_ci pass_fs_tes_vs.tcs_body = "${VERSION}\n" 347e5c31af7Sopenharmony_ci "\n" 348e5c31af7Sopenharmony_ci "${TESSELLATION_SHADER_REQUIRE}\n" 349e5c31af7Sopenharmony_ci "${TESSELLATION_POINT_SIZE_REQUIRE}\n" 350e5c31af7Sopenharmony_ci "\n" 351e5c31af7Sopenharmony_ci "layout(vertices=1) out;\n" 352e5c31af7Sopenharmony_ci "\n" 353e5c31af7Sopenharmony_ci "in vec4 color[];\n" 354e5c31af7Sopenharmony_ci "out vec4 tcColor[];\n" 355e5c31af7Sopenharmony_ci "\n" 356e5c31af7Sopenharmony_ci "void main()\n" 357e5c31af7Sopenharmony_ci "{\n" 358e5c31af7Sopenharmony_ci " tcColor[gl_InvocationID] = color[gl_InvocationID];\n" 359e5c31af7Sopenharmony_ci " gl_out[gl_InvocationID].gl_Position =\n" 360e5c31af7Sopenharmony_ci " gl_in[gl_InvocationID].gl_Position;\n" 361e5c31af7Sopenharmony_ci " gl_out[gl_InvocationID].gl_PointSize =\n" 362e5c31af7Sopenharmony_ci " gl_in[gl_InvocationID].gl_PointSize;\n" 363e5c31af7Sopenharmony_ci "\n" 364e5c31af7Sopenharmony_ci " gl_TessLevelOuter[0] = 1.0;\n" 365e5c31af7Sopenharmony_ci " gl_TessLevelOuter[1] = 1.0;\n" 366e5c31af7Sopenharmony_ci " gl_TessLevelOuter[2] = 1.0;\n" 367e5c31af7Sopenharmony_ci " gl_TessLevelOuter[3] = 1.0;\n" 368e5c31af7Sopenharmony_ci " gl_TessLevelInner[0] = 1.0;\n" 369e5c31af7Sopenharmony_ci " gl_TessLevelInner[1] = 1.0;\n" 370e5c31af7Sopenharmony_ci "}\n"; 371e5c31af7Sopenharmony_ci 372e5c31af7Sopenharmony_ci pass_fs_tes_vs.vs_body = "${VERSION}\n" 373e5c31af7Sopenharmony_ci "\n" 374e5c31af7Sopenharmony_ci "out vec4 color;\n" 375e5c31af7Sopenharmony_ci "\n" 376e5c31af7Sopenharmony_ci "void main()\n" 377e5c31af7Sopenharmony_ci "{\n" 378e5c31af7Sopenharmony_ci " const float point_dx = 2.0 / 16.0 /* rendertarget width */;\n" 379e5c31af7Sopenharmony_ci " const float point_dy = 2.0 / 16.0 /* rendertarget_height */;\n" 380e5c31af7Sopenharmony_ci "\n" 381e5c31af7Sopenharmony_ci " gl_PointSize = 0.1;\n" 382e5c31af7Sopenharmony_ci "\n" 383e5c31af7Sopenharmony_ci " switch (gl_VertexID)\n" 384e5c31af7Sopenharmony_ci " {\n" 385e5c31af7Sopenharmony_ci " case 0:\n" 386e5c31af7Sopenharmony_ci " {\n" 387e5c31af7Sopenharmony_ci /* Center */ 388e5c31af7Sopenharmony_ci " color = vec4(0.1, 0.2, 0.3, 0.4);\n" 389e5c31af7Sopenharmony_ci " gl_Position = vec4(point_dx + 0.0, point_dy + 0.0, 0.0, 1.0);\n" 390e5c31af7Sopenharmony_ci "\n" 391e5c31af7Sopenharmony_ci " break;\n" 392e5c31af7Sopenharmony_ci " }\n" 393e5c31af7Sopenharmony_ci "\n" 394e5c31af7Sopenharmony_ci " case 1:\n" 395e5c31af7Sopenharmony_ci " {\n" 396e5c31af7Sopenharmony_ci /* Top-left corner */ 397e5c31af7Sopenharmony_ci " color = vec4(0.2, 0.3, 0.4, 0.5);\n" 398e5c31af7Sopenharmony_ci " gl_Position = vec4(point_dx - 1.0, -point_dy + 1.0, 0.0, 1.0);\n" 399e5c31af7Sopenharmony_ci "\n" 400e5c31af7Sopenharmony_ci " break;\n" 401e5c31af7Sopenharmony_ci " }\n" 402e5c31af7Sopenharmony_ci "\n" 403e5c31af7Sopenharmony_ci " case 2:\n" 404e5c31af7Sopenharmony_ci " {\n" 405e5c31af7Sopenharmony_ci /* Top-right corner */ 406e5c31af7Sopenharmony_ci " color = vec4(0.3, 0.4, 0.5, 0.6);\n" 407e5c31af7Sopenharmony_ci " gl_Position = vec4(-point_dx + 1.0, -point_dy + 1.0, 0.0, 1.0);\n" 408e5c31af7Sopenharmony_ci "\n" 409e5c31af7Sopenharmony_ci " break;\n" 410e5c31af7Sopenharmony_ci " }\n" 411e5c31af7Sopenharmony_ci "\n" 412e5c31af7Sopenharmony_ci " case 3:\n" 413e5c31af7Sopenharmony_ci " {\n" 414e5c31af7Sopenharmony_ci /* Bottom-left corner */ 415e5c31af7Sopenharmony_ci " color = vec4(0.4, 0.5, 0.6, 0.7);\n" 416e5c31af7Sopenharmony_ci " gl_Position = vec4(point_dx - 1.0, point_dy - 1.0, 0.0, 1.0);\n" 417e5c31af7Sopenharmony_ci "\n" 418e5c31af7Sopenharmony_ci " break;\n" 419e5c31af7Sopenharmony_ci " }\n" 420e5c31af7Sopenharmony_ci "\n" 421e5c31af7Sopenharmony_ci " case 4:\n" 422e5c31af7Sopenharmony_ci " {\n" 423e5c31af7Sopenharmony_ci /* Bottom-right corner */ 424e5c31af7Sopenharmony_ci " color = vec4(0.5, 0.6, 0.7, 0.8);\n" 425e5c31af7Sopenharmony_ci " gl_Position = vec4(-point_dx + 1.0, point_dy - 1.0, 0.0, 1.0);\n" 426e5c31af7Sopenharmony_ci "\n" 427e5c31af7Sopenharmony_ci " break;\n" 428e5c31af7Sopenharmony_ci " }\n" 429e5c31af7Sopenharmony_ci " }\n" 430e5c31af7Sopenharmony_ci "}\n"; 431e5c31af7Sopenharmony_ci 432e5c31af7Sopenharmony_ci pass_fs_tes_vs.draw_call_count = 5; /* points in total */ 433e5c31af7Sopenharmony_ci 434e5c31af7Sopenharmony_ci /* Store the descriptor in a vector that will be used by iterate() */ 435e5c31af7Sopenharmony_ci m_tests.push_back(pass_fs_tes_vs); 436e5c31af7Sopenharmony_ci } /* if (m_is_tessellation_shader_supported) */ 437e5c31af7Sopenharmony_ci 438e5c31af7Sopenharmony_ci /* Set up a color texture we will be rendering to */ 439e5c31af7Sopenharmony_ci gl.genTextures(1, &m_to_id); 440e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 441e5c31af7Sopenharmony_ci 442e5c31af7Sopenharmony_ci gl.bindTexture(GL_TEXTURE_2D, m_to_id); 443e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed"); 444e5c31af7Sopenharmony_ci 445e5c31af7Sopenharmony_ci gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_rt_width, m_rt_height); 446e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() failed"); 447e5c31af7Sopenharmony_ci 448e5c31af7Sopenharmony_ci /* Set up a FBO we'll use for rendering */ 449e5c31af7Sopenharmony_ci gl.genFramebuffers(1, &m_fbo_id); 450e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed"); 451e5c31af7Sopenharmony_ci 452e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 453e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed"); 454e5c31af7Sopenharmony_ci 455e5c31af7Sopenharmony_ci gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */); 456e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed"); 457e5c31af7Sopenharmony_ci 458e5c31af7Sopenharmony_ci if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 459e5c31af7Sopenharmony_ci { 460e5c31af7Sopenharmony_ci /* Enable point size */ 461e5c31af7Sopenharmony_ci gl.enable(GL_PROGRAM_POINT_SIZE); 462e5c31af7Sopenharmony_ci } 463e5c31af7Sopenharmony_ci 464e5c31af7Sopenharmony_ci /* We're good to execute the test! */ 465e5c31af7Sopenharmony_ci} 466e5c31af7Sopenharmony_ci 467e5c31af7Sopenharmony_ci/** Executes the test. 468e5c31af7Sopenharmony_ci * 469e5c31af7Sopenharmony_ci * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 470e5c31af7Sopenharmony_ci * 471e5c31af7Sopenharmony_ci * Note the function throws exception should an error occur! 472e5c31af7Sopenharmony_ci * 473e5c31af7Sopenharmony_ci * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 474e5c31af7Sopenharmony_ci **/ 475e5c31af7Sopenharmony_citcu::TestNode::IterateResult TessellationShaderPointsgl_PointSize::iterate(void) 476e5c31af7Sopenharmony_ci{ 477e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 478e5c31af7Sopenharmony_ci 479e5c31af7Sopenharmony_ci initTest(); 480e5c31af7Sopenharmony_ci 481e5c31af7Sopenharmony_ci gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1); 482e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed"); 483e5c31af7Sopenharmony_ci 484e5c31af7Sopenharmony_ci /* Iterate through all test descriptors.. */ 485e5c31af7Sopenharmony_ci for (_tests_iterator test_iterator = m_tests.begin(); test_iterator != m_tests.end(); test_iterator++) 486e5c31af7Sopenharmony_ci { 487e5c31af7Sopenharmony_ci _test_descriptor& test = *test_iterator; 488e5c31af7Sopenharmony_ci 489e5c31af7Sopenharmony_ci /* Generate all shader objects we'll need */ 490e5c31af7Sopenharmony_ci if (test.fs_body != NULL) 491e5c31af7Sopenharmony_ci { 492e5c31af7Sopenharmony_ci test.fs_id = gl.createShader(GL_FRAGMENT_SHADER); 493e5c31af7Sopenharmony_ci } 494e5c31af7Sopenharmony_ci 495e5c31af7Sopenharmony_ci if (test.gs_body != NULL) 496e5c31af7Sopenharmony_ci { 497e5c31af7Sopenharmony_ci test.gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 498e5c31af7Sopenharmony_ci } 499e5c31af7Sopenharmony_ci 500e5c31af7Sopenharmony_ci if (test.tes_body != NULL) 501e5c31af7Sopenharmony_ci { 502e5c31af7Sopenharmony_ci test.tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 503e5c31af7Sopenharmony_ci } 504e5c31af7Sopenharmony_ci 505e5c31af7Sopenharmony_ci if (test.tcs_body != NULL) 506e5c31af7Sopenharmony_ci { 507e5c31af7Sopenharmony_ci test.tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 508e5c31af7Sopenharmony_ci } 509e5c31af7Sopenharmony_ci 510e5c31af7Sopenharmony_ci if (test.vs_body != NULL) 511e5c31af7Sopenharmony_ci { 512e5c31af7Sopenharmony_ci test.vs_id = gl.createShader(GL_VERTEX_SHADER); 513e5c31af7Sopenharmony_ci } 514e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed"); 515e5c31af7Sopenharmony_ci 516e5c31af7Sopenharmony_ci /* Generate a test program object before we continue */ 517e5c31af7Sopenharmony_ci test.po_id = gl.createProgram(); 518e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed"); 519e5c31af7Sopenharmony_ci 520e5c31af7Sopenharmony_ci bool link_success = 521e5c31af7Sopenharmony_ci buildProgram(test.po_id, test.fs_id, test.fs_id ? 1 : 0, &test.fs_body, test.gs_id, test.gs_id ? 1 : 0, 522e5c31af7Sopenharmony_ci &test.gs_body, test.tes_id, test.tes_id ? 1 : 0, &test.tes_body, test.tcs_id, 523e5c31af7Sopenharmony_ci test.tcs_id ? 1 : 0, &test.tcs_body, test.vs_id, test.vs_id ? 1 : 0, &test.vs_body); 524e5c31af7Sopenharmony_ci 525e5c31af7Sopenharmony_ci if (!link_success) 526e5c31af7Sopenharmony_ci { 527e5c31af7Sopenharmony_ci TCU_FAIL("Program linking failed"); 528e5c31af7Sopenharmony_ci } 529e5c31af7Sopenharmony_ci 530e5c31af7Sopenharmony_ci /* Prepare for rendering */ 531e5c31af7Sopenharmony_ci gl.clearColor(0.0f /* red */, 0.0f /* green */, 0.0f /* blue */, 0.0f /* alpha */); 532e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() failed"); 533e5c31af7Sopenharmony_ci 534e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT); 535e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glClear(GL_COLOR_BUFFER_BIT) failed"); 536e5c31af7Sopenharmony_ci 537e5c31af7Sopenharmony_ci gl.viewport(0 /* x */, 0 /* x */, m_rt_width, m_rt_height); 538e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed"); 539e5c31af7Sopenharmony_ci 540e5c31af7Sopenharmony_ci gl.useProgram(test.po_id); 541e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed"); 542e5c31af7Sopenharmony_ci 543e5c31af7Sopenharmony_ci /* Render */ 544e5c31af7Sopenharmony_ci gl.drawArrays(m_glExtTokens.PATCHES, 0 /* first */, test.draw_call_count); 545e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed"); 546e5c31af7Sopenharmony_ci 547e5c31af7Sopenharmony_ci /* Read back the rendered data */ 548e5c31af7Sopenharmony_ci unsigned char buffer[m_rt_width * m_rt_height * 4 /* components */] = { 0 }; 549e5c31af7Sopenharmony_ci 550e5c31af7Sopenharmony_ci gl.readPixels(0, /* x */ 551e5c31af7Sopenharmony_ci 0, /* y */ 552e5c31af7Sopenharmony_ci m_rt_width, m_rt_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 553e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed"); 554e5c31af7Sopenharmony_ci 555e5c31af7Sopenharmony_ci /* Verify all 5 points were rendered correctly */ 556e5c31af7Sopenharmony_ci const float epsilon = (float)1.0f / 255.0f; 557e5c31af7Sopenharmony_ci const unsigned int pixel_size = 4; /* components, GL_UNSIGNED_BYTE */ 558e5c31af7Sopenharmony_ci const float point_data[] = { 559e5c31af7Sopenharmony_ci /* x */ /* y */ /* r */ /* g */ /* b */ /* a */ 560e5c31af7Sopenharmony_ci 0.5f, 0.5f, 0.1f, 0.2f, 0.3f, 0.4f, /* center */ 561e5c31af7Sopenharmony_ci 0.0f, 1.0f, 0.2f, 0.3f, 0.4f, 0.5f, /* top-left */ 562e5c31af7Sopenharmony_ci 1.0f, 1.0f, 0.3f, 0.4f, 0.5f, 0.6f, /* top-right */ 563e5c31af7Sopenharmony_ci 0.0f, 0.0f, 0.4f, 0.5f, 0.6f, 0.7f, /* bottom-left */ 564e5c31af7Sopenharmony_ci 1.0f, 0.0f, 0.5f, 0.6f, 0.7f, 0.8f /* bottom-right */ 565e5c31af7Sopenharmony_ci }; 566e5c31af7Sopenharmony_ci const unsigned int row_size = pixel_size * m_rt_width; 567e5c31af7Sopenharmony_ci const unsigned int n_fields_per_point = 6; 568e5c31af7Sopenharmony_ci const unsigned int n_points = sizeof(point_data) / sizeof(point_data[0]) / n_fields_per_point; 569e5c31af7Sopenharmony_ci 570e5c31af7Sopenharmony_ci for (unsigned int n_point = 0; n_point < n_points; ++n_point) 571e5c31af7Sopenharmony_ci { 572e5c31af7Sopenharmony_ci int x = (int)(point_data[n_point * n_fields_per_point + 0] * float(m_rt_width - 1) + 0.5f); 573e5c31af7Sopenharmony_ci int y = (int)(point_data[n_point * n_fields_per_point + 1] * float(m_rt_height - 1) + 0.5f); 574e5c31af7Sopenharmony_ci float expected_color_r = point_data[n_point * n_fields_per_point + 2]; 575e5c31af7Sopenharmony_ci float expected_color_g = point_data[n_point * n_fields_per_point + 3]; 576e5c31af7Sopenharmony_ci float expected_color_b = point_data[n_point * n_fields_per_point + 4]; 577e5c31af7Sopenharmony_ci float expected_color_a = point_data[n_point * n_fields_per_point + 5]; 578e5c31af7Sopenharmony_ci 579e5c31af7Sopenharmony_ci const unsigned char* rendered_color_ubyte_ptr = buffer + row_size * y + x * pixel_size; 580e5c31af7Sopenharmony_ci const float rendered_color_r = float(rendered_color_ubyte_ptr[0]) / 255.0f; 581e5c31af7Sopenharmony_ci const float rendered_color_g = float(rendered_color_ubyte_ptr[1]) / 255.0f; 582e5c31af7Sopenharmony_ci const float rendered_color_b = float(rendered_color_ubyte_ptr[2]) / 255.0f; 583e5c31af7Sopenharmony_ci const float rendered_color_a = float(rendered_color_ubyte_ptr[3]) / 255.0f; 584e5c31af7Sopenharmony_ci 585e5c31af7Sopenharmony_ci /* Compare the pixels */ 586e5c31af7Sopenharmony_ci if (de::abs(expected_color_r - rendered_color_r) > epsilon || 587e5c31af7Sopenharmony_ci de::abs(expected_color_g - rendered_color_g) > epsilon || 588e5c31af7Sopenharmony_ci de::abs(expected_color_b - rendered_color_b) > epsilon || 589e5c31af7Sopenharmony_ci de::abs(expected_color_a - rendered_color_a) > epsilon) 590e5c31af7Sopenharmony_ci { 591e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Pixel data comparison failed; expected: " 592e5c31af7Sopenharmony_ci << "(" << expected_color_r << ", " << expected_color_g << ", " << expected_color_b 593e5c31af7Sopenharmony_ci << ", " << expected_color_a << ") rendered: " 594e5c31af7Sopenharmony_ci << "(" << rendered_color_r << ", " << rendered_color_g << ", " << rendered_color_b 595e5c31af7Sopenharmony_ci << ", " << rendered_color_a << ") epsilon: " << epsilon << tcu::TestLog::EndMessage; 596e5c31af7Sopenharmony_ci 597e5c31af7Sopenharmony_ci TCU_FAIL("Pixel data comparison failed"); 598e5c31af7Sopenharmony_ci } 599e5c31af7Sopenharmony_ci } /* for (all points) */ 600e5c31af7Sopenharmony_ci } /* for (all tests) */ 601e5c31af7Sopenharmony_ci 602e5c31af7Sopenharmony_ci /* All done */ 603e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 604e5c31af7Sopenharmony_ci return STOP; 605e5c31af7Sopenharmony_ci} 606e5c31af7Sopenharmony_ci 607e5c31af7Sopenharmony_ci/** Constructor 608e5c31af7Sopenharmony_ci * 609e5c31af7Sopenharmony_ci * @param context Test context 610e5c31af7Sopenharmony_ci **/ 611e5c31af7Sopenharmony_ciTessellationShaderPointsVerification::TessellationShaderPointsVerification(Context& context, 612e5c31af7Sopenharmony_ci const ExtParameters& extParams) 613e5c31af7Sopenharmony_ci : TestCaseBase(context, extParams, "points_verification", 614e5c31af7Sopenharmony_ci "Verifies points generated by the tessellator unit do not duplicate " 615e5c31af7Sopenharmony_ci "and that their amount is correct") 616e5c31af7Sopenharmony_ci , m_utils(DE_NULL) 617e5c31af7Sopenharmony_ci , m_vao_id(0) 618e5c31af7Sopenharmony_ci{ 619e5c31af7Sopenharmony_ci /* Left blank on purpose */ 620e5c31af7Sopenharmony_ci} 621e5c31af7Sopenharmony_ci 622e5c31af7Sopenharmony_ci/* Deinitializes all ES Instances generated for the test */ 623e5c31af7Sopenharmony_civoid TessellationShaderPointsVerification::deinit() 624e5c31af7Sopenharmony_ci{ 625e5c31af7Sopenharmony_ci /* Call base class' deinit() */ 626e5c31af7Sopenharmony_ci TestCaseBase::deinit(); 627e5c31af7Sopenharmony_ci 628e5c31af7Sopenharmony_ci if (!m_is_tessellation_shader_supported) 629e5c31af7Sopenharmony_ci { 630e5c31af7Sopenharmony_ci return; 631e5c31af7Sopenharmony_ci } 632e5c31af7Sopenharmony_ci 633e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 634e5c31af7Sopenharmony_ci 635e5c31af7Sopenharmony_ci /* Unbind vertex array object */ 636e5c31af7Sopenharmony_ci gl.bindVertexArray(0); 637e5c31af7Sopenharmony_ci 638e5c31af7Sopenharmony_ci /* Delete utils instances */ 639e5c31af7Sopenharmony_ci if (m_utils != DE_NULL) 640e5c31af7Sopenharmony_ci { 641e5c31af7Sopenharmony_ci delete m_utils; 642e5c31af7Sopenharmony_ci 643e5c31af7Sopenharmony_ci m_utils = DE_NULL; 644e5c31af7Sopenharmony_ci } 645e5c31af7Sopenharmony_ci 646e5c31af7Sopenharmony_ci /* Delete vertex array object */ 647e5c31af7Sopenharmony_ci if (m_vao_id != 0) 648e5c31af7Sopenharmony_ci { 649e5c31af7Sopenharmony_ci gl.deleteVertexArrays(1, &m_vao_id); 650e5c31af7Sopenharmony_ci 651e5c31af7Sopenharmony_ci m_vao_id = 0; 652e5c31af7Sopenharmony_ci } 653e5c31af7Sopenharmony_ci} 654e5c31af7Sopenharmony_ci 655e5c31af7Sopenharmony_ci/** Initializes ES objects necessary to run the test. */ 656e5c31af7Sopenharmony_civoid TessellationShaderPointsVerification::initTest() 657e5c31af7Sopenharmony_ci{ 658e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 659e5c31af7Sopenharmony_ci 660e5c31af7Sopenharmony_ci /* Skip if required extensions are not supported. */ 661e5c31af7Sopenharmony_ci if (!m_is_tessellation_shader_supported) 662e5c31af7Sopenharmony_ci { 663e5c31af7Sopenharmony_ci throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 664e5c31af7Sopenharmony_ci } 665e5c31af7Sopenharmony_ci 666e5c31af7Sopenharmony_ci /* Initialize and bind vertex array object */ 667e5c31af7Sopenharmony_ci gl.genVertexArrays(1, &m_vao_id); 668e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 669e5c31af7Sopenharmony_ci 670e5c31af7Sopenharmony_ci gl.bindVertexArray(m_vao_id); 671e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 672e5c31af7Sopenharmony_ci 673e5c31af7Sopenharmony_ci /* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */ 674e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_gen_level_value = 0; 675e5c31af7Sopenharmony_ci 676e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value); 677e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 678e5c31af7Sopenharmony_ci 679e5c31af7Sopenharmony_ci /* Initialize all test iterations */ 680e5c31af7Sopenharmony_ci const _tessellation_primitive_mode primitive_modes[] = { TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS, 681e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES, 682e5c31af7Sopenharmony_ci TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES }; 683e5c31af7Sopenharmony_ci const unsigned int n_primitive_modes = sizeof(primitive_modes) / sizeof(primitive_modes[0]); 684e5c31af7Sopenharmony_ci 685e5c31af7Sopenharmony_ci const _tessellation_shader_vertex_spacing vertex_spacings[] = { 686e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD, TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 687e5c31af7Sopenharmony_ci TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN, 688e5c31af7Sopenharmony_ci }; 689e5c31af7Sopenharmony_ci const unsigned int n_vertex_spacings = sizeof(vertex_spacings) / sizeof(vertex_spacings[0]); 690e5c31af7Sopenharmony_ci 691e5c31af7Sopenharmony_ci for (unsigned int n_primitive_mode = 0; n_primitive_mode < n_primitive_modes; ++n_primitive_mode) 692e5c31af7Sopenharmony_ci { 693e5c31af7Sopenharmony_ci _tessellation_levels_set levels_set; 694e5c31af7Sopenharmony_ci _tessellation_primitive_mode primitive_mode = primitive_modes[n_primitive_mode]; 695e5c31af7Sopenharmony_ci 696e5c31af7Sopenharmony_ci levels_set = TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode( 697e5c31af7Sopenharmony_ci primitive_mode, gl_max_tess_gen_level_value, 698e5c31af7Sopenharmony_ci TESSELLATION_LEVEL_SET_FILTER_INNER_AND_OUTER_LEVELS_USE_DIFFERENT_VALUES); 699e5c31af7Sopenharmony_ci 700e5c31af7Sopenharmony_ci for (unsigned int n_vertex_spacing = 0; n_vertex_spacing < n_vertex_spacings; ++n_vertex_spacing) 701e5c31af7Sopenharmony_ci { 702e5c31af7Sopenharmony_ci _tessellation_shader_vertex_spacing vertex_spacing = vertex_spacings[n_vertex_spacing]; 703e5c31af7Sopenharmony_ci 704e5c31af7Sopenharmony_ci for (_tessellation_levels_set_const_iterator levels_set_iterator = levels_set.begin(); 705e5c31af7Sopenharmony_ci levels_set_iterator != levels_set.end(); levels_set_iterator++) 706e5c31af7Sopenharmony_ci { 707e5c31af7Sopenharmony_ci const _tessellation_levels& levels = *levels_set_iterator; 708e5c31af7Sopenharmony_ci 709e5c31af7Sopenharmony_ci /* Skip border cases that this test cannot handle */ 710e5c31af7Sopenharmony_ci if ((primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS || 711e5c31af7Sopenharmony_ci primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES) && 712e5c31af7Sopenharmony_ci vertex_spacing == TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD && 713e5c31af7Sopenharmony_ci (levels.inner[0] <= 1 || levels.inner[1] <= 1)) 714e5c31af7Sopenharmony_ci { 715e5c31af7Sopenharmony_ci continue; 716e5c31af7Sopenharmony_ci } 717e5c31af7Sopenharmony_ci 718e5c31af7Sopenharmony_ci /* Initialize a test run descriptor for the iteration-specific properties */ 719e5c31af7Sopenharmony_ci _run run; 720e5c31af7Sopenharmony_ci 721e5c31af7Sopenharmony_ci memcpy(run.inner, levels.inner, sizeof(run.inner)); 722e5c31af7Sopenharmony_ci memcpy(run.outer, levels.outer, sizeof(run.outer)); 723e5c31af7Sopenharmony_ci 724e5c31af7Sopenharmony_ci run.primitive_mode = primitive_mode; 725e5c31af7Sopenharmony_ci run.vertex_spacing = vertex_spacing; 726e5c31af7Sopenharmony_ci 727e5c31af7Sopenharmony_ci m_runs.push_back(run); 728e5c31af7Sopenharmony_ci } /* for (all level sets) */ 729e5c31af7Sopenharmony_ci } /* for (all vertex spacing modes) */ 730e5c31af7Sopenharmony_ci } /* for (all primitive modes) */ 731e5c31af7Sopenharmony_ci 732e5c31af7Sopenharmony_ci /* Initialize utils instance. 733e5c31af7Sopenharmony_ci */ 734e5c31af7Sopenharmony_ci m_utils = new TessellationShaderUtils(gl, this); 735e5c31af7Sopenharmony_ci} 736e5c31af7Sopenharmony_ci 737e5c31af7Sopenharmony_ci/** Executes the test. 738e5c31af7Sopenharmony_ci * 739e5c31af7Sopenharmony_ci * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 740e5c31af7Sopenharmony_ci * 741e5c31af7Sopenharmony_ci * Note the function throws exception should an error occur! 742e5c31af7Sopenharmony_ci * 743e5c31af7Sopenharmony_ci * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 744e5c31af7Sopenharmony_ci **/ 745e5c31af7Sopenharmony_citcu::TestNode::IterateResult TessellationShaderPointsVerification::iterate(void) 746e5c31af7Sopenharmony_ci{ 747e5c31af7Sopenharmony_ci initTest(); 748e5c31af7Sopenharmony_ci 749e5c31af7Sopenharmony_ci /* Do not execute if required extensions are not supported. */ 750e5c31af7Sopenharmony_ci if (!m_is_tessellation_shader_supported) 751e5c31af7Sopenharmony_ci { 752e5c31af7Sopenharmony_ci throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 753e5c31af7Sopenharmony_ci } 754e5c31af7Sopenharmony_ci 755e5c31af7Sopenharmony_ci /* Iterate through all the test descriptors */ 756e5c31af7Sopenharmony_ci for (std::vector<_run>::const_iterator run_iterator = m_runs.begin(); run_iterator != m_runs.end(); run_iterator++) 757e5c31af7Sopenharmony_ci { 758e5c31af7Sopenharmony_ci const _run& run = *run_iterator; 759e5c31af7Sopenharmony_ci std::vector<char> run_data; 760e5c31af7Sopenharmony_ci unsigned int run_n_vertices = 0; 761e5c31af7Sopenharmony_ci 762e5c31af7Sopenharmony_ci run_data = m_utils->getDataGeneratedByTessellator(run.inner, true, /* point_mode */ 763e5c31af7Sopenharmony_ci run.primitive_mode, TESSELLATION_SHADER_VERTEX_ORDERING_CCW, 764e5c31af7Sopenharmony_ci run.vertex_spacing, run.outer); 765e5c31af7Sopenharmony_ci 766e5c31af7Sopenharmony_ci run_n_vertices = m_utils->getAmountOfVerticesGeneratedByTessellator(run.primitive_mode, run.inner, run.outer, 767e5c31af7Sopenharmony_ci run.vertex_spacing, true); /* point_mode */ 768e5c31af7Sopenharmony_ci 769e5c31af7Sopenharmony_ci /* First, make sure a valid amount of duplicate vertices was found for a single data set */ 770e5c31af7Sopenharmony_ci verifyCorrectAmountOfDuplicateVertices(run, &run_data[0], run_n_vertices); 771e5c31af7Sopenharmony_ci 772e5c31af7Sopenharmony_ci /* Now, verify that amount of generated vertices is correct, given 773e5c31af7Sopenharmony_ci * tessellation shader stage configuration */ 774e5c31af7Sopenharmony_ci verifyCorrectAmountOfVertices(run, &run_data[0], run_n_vertices); 775e5c31af7Sopenharmony_ci } /* for (all tests) */ 776e5c31af7Sopenharmony_ci 777e5c31af7Sopenharmony_ci /* All done */ 778e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 779e5c31af7Sopenharmony_ci return STOP; 780e5c31af7Sopenharmony_ci} 781e5c31af7Sopenharmony_ci 782e5c31af7Sopenharmony_ci/** Verifies that a correct amount of vertices was generated, given test iteration-specific properties. 783e5c31af7Sopenharmony_ci * Throws a TestError exception in if an incorrect amount of vertices was generated by the tessellator. 784e5c31af7Sopenharmony_ci * 785e5c31af7Sopenharmony_ci * @param run Run descriptor. 786e5c31af7Sopenharmony_ci * @param run_data Data generated for the run. 787e5c31af7Sopenharmony_ci * @param run_n_vertices Amount of vertices present at @param run_data. 788e5c31af7Sopenharmony_ci */ 789e5c31af7Sopenharmony_civoid TessellationShaderPointsVerification::verifyCorrectAmountOfVertices(const _run& run, const void* run_data, 790e5c31af7Sopenharmony_ci unsigned int run_n_vertices) 791e5c31af7Sopenharmony_ci{ 792e5c31af7Sopenharmony_ci (void)run_data; 793e5c31af7Sopenharmony_ci 794e5c31af7Sopenharmony_ci const float epsilon = 1e-5f; 795e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 796e5c31af7Sopenharmony_ci unsigned int n_expected_vertices = 0; 797e5c31af7Sopenharmony_ci float post_vs_inner_tess_levels[2] = { 0.0f }; 798e5c31af7Sopenharmony_ci float post_vs_outer_tess_levels[4] = { 0.0f }; 799e5c31af7Sopenharmony_ci 800e5c31af7Sopenharmony_ci /* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value*/ 801e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_gen_level_value = 0; 802e5c31af7Sopenharmony_ci 803e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value); 804e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_TESS_GEN_LEVEL_EXT pname"); 805e5c31af7Sopenharmony_ci 806e5c31af7Sopenharmony_ci /* Determine vertex spacing that the tessellator should have used for current primitive mode */ 807e5c31af7Sopenharmony_ci glw::GLfloat actual_inner_levels[2] = { 0.0f }; 808e5c31af7Sopenharmony_ci _tessellation_shader_vertex_spacing actual_vs_mode = run.vertex_spacing; 809e5c31af7Sopenharmony_ci glw::GLfloat clamped_inner_levels[2] = { 0.0f }; 810e5c31af7Sopenharmony_ci 811e5c31af7Sopenharmony_ci memcpy(actual_inner_levels, run.inner, sizeof(run.inner)); 812e5c31af7Sopenharmony_ci 813e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing( 814e5c31af7Sopenharmony_ci run.vertex_spacing, actual_inner_levels[0], gl_max_tess_gen_level_value, clamped_inner_levels + 0, 815e5c31af7Sopenharmony_ci DE_NULL); /* out_clamped_and_rounded */ 816e5c31af7Sopenharmony_ci 817e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing( 818e5c31af7Sopenharmony_ci run.vertex_spacing, actual_inner_levels[1], gl_max_tess_gen_level_value, clamped_inner_levels + 1, 819e5c31af7Sopenharmony_ci DE_NULL); /* out_clamped_and_rounded */ 820e5c31af7Sopenharmony_ci 821e5c31af7Sopenharmony_ci if (run.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES) 822e5c31af7Sopenharmony_ci { 823e5c31af7Sopenharmony_ci /* For isolines tessellation, outer[1] is subdivided as per specified vertex spacing as specified. 824e5c31af7Sopenharmony_ci * outer[0] should be subdivided using equal vertex spacing. 825e5c31af7Sopenharmony_ci * 826e5c31af7Sopenharmony_ci * This is owing to the following language in the spec (* marks important subtleties): 827e5c31af7Sopenharmony_ci * 828e5c31af7Sopenharmony_ci * The *u==0* and *u==1* edges of the rectangle are subdivided according to the first outer 829e5c31af7Sopenharmony_ci * tessellation level. For the purposes of *this* subdivision, the tessellation spacing mode 830e5c31af7Sopenharmony_ci * is ignored and treated as "equal_spacing". 831e5c31af7Sopenharmony_ci */ 832e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, 833e5c31af7Sopenharmony_ci run.outer[0], gl_max_tess_gen_level_value, 834e5c31af7Sopenharmony_ci DE_NULL, /* out_clamped */ 835e5c31af7Sopenharmony_ci post_vs_outer_tess_levels); 836e5c31af7Sopenharmony_ci 837e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing( 838e5c31af7Sopenharmony_ci actual_vs_mode, run.outer[1], gl_max_tess_gen_level_value, DE_NULL, /* out_clamped */ 839e5c31af7Sopenharmony_ci post_vs_outer_tess_levels + 1); 840e5c31af7Sopenharmony_ci } 841e5c31af7Sopenharmony_ci 842e5c31af7Sopenharmony_ci if (run.primitive_mode == TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS) 843e5c31af7Sopenharmony_ci { 844e5c31af7Sopenharmony_ci /* As per extension spec: 845e5c31af7Sopenharmony_ci * 846e5c31af7Sopenharmony_ci * if either clamped inner tessellation level is one, that tessellation level 847e5c31af7Sopenharmony_ci * is treated as though it were originally specified as 1+epsilon, which would 848e5c31af7Sopenharmony_ci * rounded up to result in a two- or three-segment subdivision according to the 849e5c31af7Sopenharmony_ci * tessellation spacing. 850e5c31af7Sopenharmony_ci * 851e5c31af7Sopenharmony_ci **/ 852e5c31af7Sopenharmony_ci if (de::abs(clamped_inner_levels[0] - 1.0f) < epsilon) 853e5c31af7Sopenharmony_ci { 854e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing( 855e5c31af7Sopenharmony_ci run.vertex_spacing, clamped_inner_levels[0] + 1.0f, /* epsilon */ 856e5c31af7Sopenharmony_ci gl_max_tess_gen_level_value, DE_NULL, /* out_clamped */ 857e5c31af7Sopenharmony_ci actual_inner_levels + 0); 858e5c31af7Sopenharmony_ci } 859e5c31af7Sopenharmony_ci 860e5c31af7Sopenharmony_ci if (de::abs(clamped_inner_levels[1] - 1.0f) < epsilon) 861e5c31af7Sopenharmony_ci { 862e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing( 863e5c31af7Sopenharmony_ci run.vertex_spacing, clamped_inner_levels[1] + 1.0f, /* epsilon */ 864e5c31af7Sopenharmony_ci gl_max_tess_gen_level_value, DE_NULL, /* out_clamped */ 865e5c31af7Sopenharmony_ci actual_inner_levels + 1); 866e5c31af7Sopenharmony_ci } 867e5c31af7Sopenharmony_ci } 868e5c31af7Sopenharmony_ci 869e5c31af7Sopenharmony_ci /* Retrieve tessellation level values, taking vertex spacing setting into account */ 870e5c31af7Sopenharmony_ci for (int n = 0; n < 2 /* inner tessellation level values */; ++n) 871e5c31af7Sopenharmony_ci { 872e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing( 873e5c31af7Sopenharmony_ci actual_vs_mode, actual_inner_levels[n], gl_max_tess_gen_level_value, DE_NULL, /* out_clamped */ 874e5c31af7Sopenharmony_ci post_vs_inner_tess_levels + n); 875e5c31af7Sopenharmony_ci } 876e5c31af7Sopenharmony_ci 877e5c31af7Sopenharmony_ci if (run.primitive_mode != TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES) 878e5c31af7Sopenharmony_ci { 879e5c31af7Sopenharmony_ci for (int n = 0; n < 4 /* outer tessellation level values */; ++n) 880e5c31af7Sopenharmony_ci { 881e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing( 882e5c31af7Sopenharmony_ci actual_vs_mode, run.outer[n], gl_max_tess_gen_level_value, DE_NULL, /* out_clamped */ 883e5c31af7Sopenharmony_ci post_vs_outer_tess_levels + n); 884e5c31af7Sopenharmony_ci } 885e5c31af7Sopenharmony_ci } 886e5c31af7Sopenharmony_ci 887e5c31af7Sopenharmony_ci /* Calculate amount of vertices that should be generated in point mode */ 888e5c31af7Sopenharmony_ci switch (run.primitive_mode) 889e5c31af7Sopenharmony_ci { 890e5c31af7Sopenharmony_ci case TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES: 891e5c31af7Sopenharmony_ci { 892e5c31af7Sopenharmony_ci n_expected_vertices = int(post_vs_outer_tess_levels[0]) * int(post_vs_outer_tess_levels[1] + 1); 893e5c31af7Sopenharmony_ci 894e5c31af7Sopenharmony_ci break; 895e5c31af7Sopenharmony_ci } 896e5c31af7Sopenharmony_ci 897e5c31af7Sopenharmony_ci case TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS: 898e5c31af7Sopenharmony_ci { 899e5c31af7Sopenharmony_ci n_expected_vertices = /* outer quad */ 900e5c31af7Sopenharmony_ci int(post_vs_outer_tess_levels[0]) + int(post_vs_outer_tess_levels[1]) + int(post_vs_outer_tess_levels[2]) + 901e5c31af7Sopenharmony_ci int(post_vs_outer_tess_levels[3]) + 902e5c31af7Sopenharmony_ci /* inner quad */ 903e5c31af7Sopenharmony_ci (int(post_vs_inner_tess_levels[0]) - 1) * (int(post_vs_inner_tess_levels[1]) - 1); 904e5c31af7Sopenharmony_ci 905e5c31af7Sopenharmony_ci break; 906e5c31af7Sopenharmony_ci } 907e5c31af7Sopenharmony_ci 908e5c31af7Sopenharmony_ci case TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES: 909e5c31af7Sopenharmony_ci { 910e5c31af7Sopenharmony_ci /* If the first inner tessellation level and all three outer tessellation 911e5c31af7Sopenharmony_ci * levels are exactly one after clamping and rounding, only a single triangle 912e5c31af7Sopenharmony_ci * with (u,v,w) coordinates of (0,0,1), (1,0,0), and (0,1,0) is generated. 913e5c31af7Sopenharmony_ci */ 914e5c31af7Sopenharmony_ci if (de::abs(run.inner[0] - 1.0f) < epsilon && de::abs(run.outer[0] - 1.0f) < epsilon && 915e5c31af7Sopenharmony_ci de::abs(run.outer[1] - 1.0f) < epsilon && de::abs(run.outer[2] - 1.0f) < epsilon) 916e5c31af7Sopenharmony_ci { 917e5c31af7Sopenharmony_ci n_expected_vertices = 3; 918e5c31af7Sopenharmony_ci } 919e5c31af7Sopenharmony_ci else 920e5c31af7Sopenharmony_ci { 921e5c31af7Sopenharmony_ci /* If the inner tessellation level is one and any of the outer tessellation 922e5c31af7Sopenharmony_ci * levels is greater than one, the inner tessellation level is treated as 923e5c31af7Sopenharmony_ci * though it were originally specified as 1+epsilon and will be rounded up to 924e5c31af7Sopenharmony_ci * result in a two- or three-segment subdivision according to the 925e5c31af7Sopenharmony_ci * tessellation spacing. 926e5c31af7Sopenharmony_ci */ 927e5c31af7Sopenharmony_ci if (de::abs(run.inner[0] - 1.0f) < epsilon && 928e5c31af7Sopenharmony_ci (run.outer[0] > 1.0f || run.outer[1] > 1.0f || run.outer[2] > 1.0f)) 929e5c31af7Sopenharmony_ci { 930e5c31af7Sopenharmony_ci TessellationShaderUtils::getTessellationLevelAfterVertexSpacing( 931e5c31af7Sopenharmony_ci run.vertex_spacing, 2.0f, gl_max_tess_gen_level_value, DE_NULL, /* out_clamped */ 932e5c31af7Sopenharmony_ci post_vs_inner_tess_levels); 933e5c31af7Sopenharmony_ci } 934e5c31af7Sopenharmony_ci 935e5c31af7Sopenharmony_ci /* Count vertices making up concentric inner triangles */ 936e5c31af7Sopenharmony_ci n_expected_vertices = (int)post_vs_outer_tess_levels[0] + (int)post_vs_outer_tess_levels[1] + 937e5c31af7Sopenharmony_ci (int)post_vs_outer_tess_levels[2]; 938e5c31af7Sopenharmony_ci 939e5c31af7Sopenharmony_ci for (int n = (int)post_vs_inner_tess_levels[0]; n >= 0; n -= 2) 940e5c31af7Sopenharmony_ci { 941e5c31af7Sopenharmony_ci /* For the outermost inner triangle, the inner triangle is degenerate - 942e5c31af7Sopenharmony_ci * a single point at the center of the triangle -- if <n> is two. 943e5c31af7Sopenharmony_ci */ 944e5c31af7Sopenharmony_ci if (n == 2) 945e5c31af7Sopenharmony_ci { 946e5c31af7Sopenharmony_ci n_expected_vertices++; /* degenerate vertex */ 947e5c31af7Sopenharmony_ci 948e5c31af7Sopenharmony_ci break; 949e5c31af7Sopenharmony_ci } 950e5c31af7Sopenharmony_ci 951e5c31af7Sopenharmony_ci /* If <n> is three, the edges of the inner triangle are not subdivided and is 952e5c31af7Sopenharmony_ci * the final triangle in the set of concentric triangles. 953e5c31af7Sopenharmony_ci */ 954e5c31af7Sopenharmony_ci if (n == 3) 955e5c31af7Sopenharmony_ci { 956e5c31af7Sopenharmony_ci n_expected_vertices += 3 /* vertices per triangle */; 957e5c31af7Sopenharmony_ci 958e5c31af7Sopenharmony_ci break; 959e5c31af7Sopenharmony_ci } 960e5c31af7Sopenharmony_ci 961e5c31af7Sopenharmony_ci /* Otherwise, each edge of the inner triangle is divided into <n>-2 segments, 962e5c31af7Sopenharmony_ci * with the <n>-1 vertices of this subdivision produced by intersecting the 963e5c31af7Sopenharmony_ci * inner edge with lines perpendicular to the edge running through the <n>-1 964e5c31af7Sopenharmony_ci * innermost vertices of the subdivision of the outer edge. 965e5c31af7Sopenharmony_ci */ 966e5c31af7Sopenharmony_ci if (n >= 2) 967e5c31af7Sopenharmony_ci { 968e5c31af7Sopenharmony_ci n_expected_vertices += (n - 2) * 3 /* triangle edges */; 969e5c31af7Sopenharmony_ci } 970e5c31af7Sopenharmony_ci else 971e5c31af7Sopenharmony_ci { 972e5c31af7Sopenharmony_ci /* Count in the degenerate point instead */ 973e5c31af7Sopenharmony_ci n_expected_vertices++; 974e5c31af7Sopenharmony_ci } 975e5c31af7Sopenharmony_ci } /* for (all inner triangles) */ 976e5c31af7Sopenharmony_ci } 977e5c31af7Sopenharmony_ci 978e5c31af7Sopenharmony_ci break; 979e5c31af7Sopenharmony_ci } 980e5c31af7Sopenharmony_ci 981e5c31af7Sopenharmony_ci default: 982e5c31af7Sopenharmony_ci { 983e5c31af7Sopenharmony_ci TCU_FAIL("Unrecognized primitive mode"); 984e5c31af7Sopenharmony_ci } 985e5c31af7Sopenharmony_ci } /* switch (test.primitive_mode) */ 986e5c31af7Sopenharmony_ci 987e5c31af7Sopenharmony_ci /* Compare two values */ 988e5c31af7Sopenharmony_ci if (run_n_vertices != n_expected_vertices) 989e5c31af7Sopenharmony_ci { 990e5c31af7Sopenharmony_ci std::string primitive_mode = TessellationShaderUtils::getESTokenForPrimitiveMode(run.primitive_mode); 991e5c31af7Sopenharmony_ci std::string vertex_spacing = TessellationShaderUtils::getESTokenForVertexSpacingMode(run.vertex_spacing); 992e5c31af7Sopenharmony_ci 993e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << run_n_vertices 994e5c31af7Sopenharmony_ci << " vertices were generated by the tessellator instead of expected " << n_expected_vertices 995e5c31af7Sopenharmony_ci << " for primitive mode [" << primitive_mode << "], vertex spacing mode [" << vertex_spacing 996e5c31af7Sopenharmony_ci << "], inner tessellation levels:[" << run.inner[0] << ", " << run.inner[1] 997e5c31af7Sopenharmony_ci << "], outer tessellation levels:[" << run.outer[0] << ", " << run.outer[1] << ", " 998e5c31af7Sopenharmony_ci << run.outer[2] << ", " << run.outer[3] << "], point mode enabled." 999e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1000e5c31af7Sopenharmony_ci 1001e5c31af7Sopenharmony_ci TCU_FAIL("Amount of vertices generated in point mode was incorrect"); 1002e5c31af7Sopenharmony_ci } /* if (test.n_vertices != n_expected_vertices) */ 1003e5c31af7Sopenharmony_ci} 1004e5c31af7Sopenharmony_ci 1005e5c31af7Sopenharmony_ci/** Verifies a valid amount of duplicate vertices is present in the set of coordinates 1006e5c31af7Sopenharmony_ci * generated by the tessellator, as described by user-provided test iteration descriptor. 1007e5c31af7Sopenharmony_ci * Throws a TestError exception if the vertex set does not meet the requirements. 1008e5c31af7Sopenharmony_ci * 1009e5c31af7Sopenharmony_ci * @param test Test iteration descriptor. 1010e5c31af7Sopenharmony_ci * @param run_data Data generated for the run. 1011e5c31af7Sopenharmony_ci * @param run_n_vertices Amount of vertices present at @param run_data. 1012e5c31af7Sopenharmony_ci **/ 1013e5c31af7Sopenharmony_civoid TessellationShaderPointsVerification::verifyCorrectAmountOfDuplicateVertices(const _run& run, const void* run_data, 1014e5c31af7Sopenharmony_ci unsigned int run_n_vertices) 1015e5c31af7Sopenharmony_ci{ 1016e5c31af7Sopenharmony_ci const float epsilon = 1e-5f; 1017e5c31af7Sopenharmony_ci unsigned int n_duplicate_vertices = 0; 1018e5c31af7Sopenharmony_ci 1019e5c31af7Sopenharmony_ci for (unsigned int n_vertex_a = 0; n_vertex_a < run_n_vertices; ++n_vertex_a) 1020e5c31af7Sopenharmony_ci { 1021e5c31af7Sopenharmony_ci const float* vertex_a = (const float*)run_data + n_vertex_a * 3; /* components */ 1022e5c31af7Sopenharmony_ci 1023e5c31af7Sopenharmony_ci for (unsigned int n_vertex_b = n_vertex_a + 1; n_vertex_b < run_n_vertices; ++n_vertex_b) 1024e5c31af7Sopenharmony_ci { 1025e5c31af7Sopenharmony_ci const float* vertex_b = (const float*)run_data + n_vertex_b * 3; /* components */ 1026e5c31af7Sopenharmony_ci 1027e5c31af7Sopenharmony_ci if (de::abs(vertex_a[0] - vertex_b[0]) < epsilon && de::abs(vertex_a[1] - vertex_b[1]) < epsilon && 1028e5c31af7Sopenharmony_ci de::abs(vertex_a[2] - vertex_b[2]) < epsilon) 1029e5c31af7Sopenharmony_ci { 1030e5c31af7Sopenharmony_ci n_duplicate_vertices++; 1031e5c31af7Sopenharmony_ci } 1032e5c31af7Sopenharmony_ci } /* for (all vertices) */ 1033e5c31af7Sopenharmony_ci } /* for (all vertices) */ 1034e5c31af7Sopenharmony_ci 1035e5c31af7Sopenharmony_ci if (n_duplicate_vertices != 0) 1036e5c31af7Sopenharmony_ci { 1037e5c31af7Sopenharmony_ci std::string vertex_spacing = TessellationShaderUtils::getESTokenForVertexSpacingMode(run.vertex_spacing); 1038e5c31af7Sopenharmony_ci 1039e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Duplicate vertices found for the following tesselelation" 1040e5c31af7Sopenharmony_ci " configuration: tessellation level:" 1041e5c31af7Sopenharmony_ci "[" 1042e5c31af7Sopenharmony_ci << run.inner[0] << ", " << run.inner[1] << "], " 1043e5c31af7Sopenharmony_ci "outer tessellation level:" 1044e5c31af7Sopenharmony_ci " [" 1045e5c31af7Sopenharmony_ci << run.outer[0] << ", " << run.outer[1] << ", " << run.outer[2] << ", " << run.outer[3] 1046e5c31af7Sopenharmony_ci << "], " 1047e5c31af7Sopenharmony_ci << "vertex spacing mode:[" << vertex_spacing.c_str() << "]" << tcu::TestLog::EndMessage; 1048e5c31af7Sopenharmony_ci 1049e5c31af7Sopenharmony_ci TCU_FAIL("Duplicate vertex found"); 1050e5c31af7Sopenharmony_ci } 1051e5c31af7Sopenharmony_ci} 1052e5c31af7Sopenharmony_ci 1053e5c31af7Sopenharmony_ci} /* namespace glcts */ 1054