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 "gluDefs.hpp" 25e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 26e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 27e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 28e5c31af7Sopenharmony_ci 29e5c31af7Sopenharmony_ci#include "esextcGeometryShaderAdjacency.hpp" 30e5c31af7Sopenharmony_ci#include <math.h> 31e5c31af7Sopenharmony_ci 32e5c31af7Sopenharmony_cinamespace glcts 33e5c31af7Sopenharmony_ci{ 34e5c31af7Sopenharmony_ci/** Constructor 35e5c31af7Sopenharmony_ci * 36e5c31af7Sopenharmony_ci **/ 37e5c31af7Sopenharmony_ciAdjacencyGrid::AdjacencyGrid() 38e5c31af7Sopenharmony_ci : m_line_segments(0), m_points(0), m_triangles(0), m_n_points(0), m_n_segments(0), m_n_triangles(0) 39e5c31af7Sopenharmony_ci{ 40e5c31af7Sopenharmony_ci /* Nothing to be done here */ 41e5c31af7Sopenharmony_ci} 42e5c31af7Sopenharmony_ci 43e5c31af7Sopenharmony_ci/** Destructor 44e5c31af7Sopenharmony_ci * 45e5c31af7Sopenharmony_ci **/ 46e5c31af7Sopenharmony_ciAdjacencyGrid::~AdjacencyGrid() 47e5c31af7Sopenharmony_ci{ 48e5c31af7Sopenharmony_ci if (m_line_segments) 49e5c31af7Sopenharmony_ci { 50e5c31af7Sopenharmony_ci delete[] m_line_segments; 51e5c31af7Sopenharmony_ci m_line_segments = 0; 52e5c31af7Sopenharmony_ci } 53e5c31af7Sopenharmony_ci 54e5c31af7Sopenharmony_ci if (m_points) 55e5c31af7Sopenharmony_ci { 56e5c31af7Sopenharmony_ci delete[] m_points; 57e5c31af7Sopenharmony_ci m_points = 0; 58e5c31af7Sopenharmony_ci } 59e5c31af7Sopenharmony_ci 60e5c31af7Sopenharmony_ci if (m_triangles) 61e5c31af7Sopenharmony_ci { 62e5c31af7Sopenharmony_ci delete[] m_triangles; 63e5c31af7Sopenharmony_ci m_triangles = 0; 64e5c31af7Sopenharmony_ci } 65e5c31af7Sopenharmony_ci} 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_ci/** Constructor 68e5c31af7Sopenharmony_ci * 69e5c31af7Sopenharmony_ci **/ 70e5c31af7Sopenharmony_ciAdjacencyGridStrip::AdjacencyGridStrip() : m_n_points(0), m_points(0) 71e5c31af7Sopenharmony_ci{ 72e5c31af7Sopenharmony_ci /* Nothing to be done here */ 73e5c31af7Sopenharmony_ci} 74e5c31af7Sopenharmony_ci 75e5c31af7Sopenharmony_ci/** Destructor 76e5c31af7Sopenharmony_ci * 77e5c31af7Sopenharmony_ci **/ 78e5c31af7Sopenharmony_ciAdjacencyGridStrip::~AdjacencyGridStrip() 79e5c31af7Sopenharmony_ci{ 80e5c31af7Sopenharmony_ci if (m_points) 81e5c31af7Sopenharmony_ci { 82e5c31af7Sopenharmony_ci delete[] m_points; 83e5c31af7Sopenharmony_ci } 84e5c31af7Sopenharmony_ci} 85e5c31af7Sopenharmony_ci 86e5c31af7Sopenharmony_ci/** Constructor 87e5c31af7Sopenharmony_ci * 88e5c31af7Sopenharmony_ci **/ 89e5c31af7Sopenharmony_ciAdjacencyTestData::AdjacencyTestData() 90e5c31af7Sopenharmony_ci : m_gs_code(0) 91e5c31af7Sopenharmony_ci , m_mode(0) 92e5c31af7Sopenharmony_ci , m_n_vertices(0) 93e5c31af7Sopenharmony_ci , m_grid(0) 94e5c31af7Sopenharmony_ci , m_geometry_bo_size(0) 95e5c31af7Sopenharmony_ci , m_index_data_bo_size(0) 96e5c31af7Sopenharmony_ci , m_vertex_data_bo_size(0) 97e5c31af7Sopenharmony_ci , m_expected_adjacency_geometry(0) 98e5c31af7Sopenharmony_ci , m_expected_geometry(0) 99e5c31af7Sopenharmony_ci , m_alternate_expected_adjacency_geometry(0) 100e5c31af7Sopenharmony_ci , m_alternate_expected_geometry(0) 101e5c31af7Sopenharmony_ci , m_index_data(0) 102e5c31af7Sopenharmony_ci , m_tf_mode(0) 103e5c31af7Sopenharmony_ci , m_vertex_data(0) 104e5c31af7Sopenharmony_ci{ 105e5c31af7Sopenharmony_ci /* Nothing to be done here */ 106e5c31af7Sopenharmony_ci} 107e5c31af7Sopenharmony_ci 108e5c31af7Sopenharmony_ci/** Destructor 109e5c31af7Sopenharmony_ci * 110e5c31af7Sopenharmony_ci **/ 111e5c31af7Sopenharmony_ciAdjacencyTestData::~AdjacencyTestData() 112e5c31af7Sopenharmony_ci{ 113e5c31af7Sopenharmony_ci if (m_expected_adjacency_geometry) 114e5c31af7Sopenharmony_ci { 115e5c31af7Sopenharmony_ci delete[] m_expected_adjacency_geometry; 116e5c31af7Sopenharmony_ci m_expected_adjacency_geometry = 0; 117e5c31af7Sopenharmony_ci } 118e5c31af7Sopenharmony_ci 119e5c31af7Sopenharmony_ci if (m_expected_geometry) 120e5c31af7Sopenharmony_ci { 121e5c31af7Sopenharmony_ci delete[] m_expected_geometry; 122e5c31af7Sopenharmony_ci m_expected_geometry = 0; 123e5c31af7Sopenharmony_ci } 124e5c31af7Sopenharmony_ci 125e5c31af7Sopenharmony_ci if (m_alternate_expected_adjacency_geometry) 126e5c31af7Sopenharmony_ci { 127e5c31af7Sopenharmony_ci delete[] m_alternate_expected_adjacency_geometry; 128e5c31af7Sopenharmony_ci m_alternate_expected_adjacency_geometry = 0; 129e5c31af7Sopenharmony_ci } 130e5c31af7Sopenharmony_ci 131e5c31af7Sopenharmony_ci if (m_alternate_expected_geometry) 132e5c31af7Sopenharmony_ci { 133e5c31af7Sopenharmony_ci delete[] m_alternate_expected_geometry; 134e5c31af7Sopenharmony_ci m_alternate_expected_geometry = 0; 135e5c31af7Sopenharmony_ci } 136e5c31af7Sopenharmony_ci 137e5c31af7Sopenharmony_ci if (m_vertex_data) 138e5c31af7Sopenharmony_ci { 139e5c31af7Sopenharmony_ci delete[] m_vertex_data; 140e5c31af7Sopenharmony_ci m_vertex_data = 0; 141e5c31af7Sopenharmony_ci } 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci if (m_index_data) 144e5c31af7Sopenharmony_ci { 145e5c31af7Sopenharmony_ci delete[] m_index_data; 146e5c31af7Sopenharmony_ci m_index_data = 0; 147e5c31af7Sopenharmony_ci } 148e5c31af7Sopenharmony_ci 149e5c31af7Sopenharmony_ci if (m_grid) 150e5c31af7Sopenharmony_ci { 151e5c31af7Sopenharmony_ci delete m_grid; 152e5c31af7Sopenharmony_ci m_grid = 0; 153e5c31af7Sopenharmony_ci } 154e5c31af7Sopenharmony_ci} 155e5c31af7Sopenharmony_ci 156e5c31af7Sopenharmony_ci/** Constructor 157e5c31af7Sopenharmony_ci * 158e5c31af7Sopenharmony_ci * @param context Test context 159e5c31af7Sopenharmony_ci * @param name Test case's name 160e5c31af7Sopenharmony_ci * @param description Test case's desricption 161e5c31af7Sopenharmony_ci **/ 162e5c31af7Sopenharmony_ciGeometryShaderAdjacency::GeometryShaderAdjacency(Context& context, const ExtParameters& extParams, const char* name, 163e5c31af7Sopenharmony_ci const char* description, AdjacencyTestData& testData) 164e5c31af7Sopenharmony_ci : TestCaseBase(context, extParams, name, description) 165e5c31af7Sopenharmony_ci , m_adjacency_geometry_bo_id(0) 166e5c31af7Sopenharmony_ci , m_fs_id(0) 167e5c31af7Sopenharmony_ci , m_geometry_bo_id(0) 168e5c31af7Sopenharmony_ci , m_gs_id(0) 169e5c31af7Sopenharmony_ci , m_index_data_bo_id(0) 170e5c31af7Sopenharmony_ci , m_vertex_data_bo_id(0) 171e5c31af7Sopenharmony_ci , m_po_id(0) 172e5c31af7Sopenharmony_ci , m_test_data(testData) 173e5c31af7Sopenharmony_ci , m_vao_id(0) 174e5c31af7Sopenharmony_ci , m_vs_id(0) 175e5c31af7Sopenharmony_ci , m_components_input(2) 176e5c31af7Sopenharmony_ci , m_epsilon(0.00001F) 177e5c31af7Sopenharmony_ci , m_position_attribute_location(0) 178e5c31af7Sopenharmony_ci{ 179e5c31af7Sopenharmony_ci /* Nothing to be done here */ 180e5c31af7Sopenharmony_ci} 181e5c31af7Sopenharmony_ci 182e5c31af7Sopenharmony_ci/** Deinitializes GLES objects created during the test. 183e5c31af7Sopenharmony_ci * 184e5c31af7Sopenharmony_ci */ 185e5c31af7Sopenharmony_civoid GeometryShaderAdjacency::deinit(void) 186e5c31af7Sopenharmony_ci{ 187e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 188e5c31af7Sopenharmony_ci 189e5c31af7Sopenharmony_ci /* Reset OpenGL ES state */ 190e5c31af7Sopenharmony_ci gl.useProgram(0); 191e5c31af7Sopenharmony_ci gl.bindVertexArray(0); 192e5c31af7Sopenharmony_ci gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0); 193e5c31af7Sopenharmony_ci gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, 0); 194e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, 0); 195e5c31af7Sopenharmony_ci 196e5c31af7Sopenharmony_ci if (m_po_id != 0) 197e5c31af7Sopenharmony_ci { 198e5c31af7Sopenharmony_ci gl.deleteProgram(m_po_id); 199e5c31af7Sopenharmony_ci } 200e5c31af7Sopenharmony_ci 201e5c31af7Sopenharmony_ci if (m_fs_id != 0) 202e5c31af7Sopenharmony_ci { 203e5c31af7Sopenharmony_ci gl.deleteShader(m_fs_id); 204e5c31af7Sopenharmony_ci } 205e5c31af7Sopenharmony_ci 206e5c31af7Sopenharmony_ci if (m_gs_id != 0) 207e5c31af7Sopenharmony_ci { 208e5c31af7Sopenharmony_ci gl.deleteShader(m_gs_id); 209e5c31af7Sopenharmony_ci } 210e5c31af7Sopenharmony_ci 211e5c31af7Sopenharmony_ci if (m_vs_id != 0) 212e5c31af7Sopenharmony_ci { 213e5c31af7Sopenharmony_ci gl.deleteShader(m_vs_id); 214e5c31af7Sopenharmony_ci } 215e5c31af7Sopenharmony_ci 216e5c31af7Sopenharmony_ci if (m_adjacency_geometry_bo_id != 0) 217e5c31af7Sopenharmony_ci { 218e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_adjacency_geometry_bo_id); 219e5c31af7Sopenharmony_ci } 220e5c31af7Sopenharmony_ci if (m_geometry_bo_id != 0) 221e5c31af7Sopenharmony_ci { 222e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_geometry_bo_id); 223e5c31af7Sopenharmony_ci } 224e5c31af7Sopenharmony_ci 225e5c31af7Sopenharmony_ci if (m_index_data_bo_id != 0) 226e5c31af7Sopenharmony_ci { 227e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_index_data_bo_id); 228e5c31af7Sopenharmony_ci } 229e5c31af7Sopenharmony_ci 230e5c31af7Sopenharmony_ci if (m_vertex_data_bo_id != 0) 231e5c31af7Sopenharmony_ci { 232e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_vertex_data_bo_id); 233e5c31af7Sopenharmony_ci } 234e5c31af7Sopenharmony_ci 235e5c31af7Sopenharmony_ci if (m_vao_id != 0) 236e5c31af7Sopenharmony_ci { 237e5c31af7Sopenharmony_ci gl.deleteVertexArrays(1, &m_vao_id); 238e5c31af7Sopenharmony_ci } 239e5c31af7Sopenharmony_ci 240e5c31af7Sopenharmony_ci TestCaseBase::deinit(); 241e5c31af7Sopenharmony_ci} 242e5c31af7Sopenharmony_ci 243e5c31af7Sopenharmony_ci/** Returns code for Fragment Shader 244e5c31af7Sopenharmony_ci * @return pointer to literal with Fragment Shader code 245e5c31af7Sopenharmony_ci **/ 246e5c31af7Sopenharmony_ciconst char* GeometryShaderAdjacency::getFragmentShaderCode() 247e5c31af7Sopenharmony_ci{ 248e5c31af7Sopenharmony_ci static const char* result = "${VERSION}\n" 249e5c31af7Sopenharmony_ci "\n" 250e5c31af7Sopenharmony_ci "precision highp float;\n" 251e5c31af7Sopenharmony_ci "\n" 252e5c31af7Sopenharmony_ci "void main()\n" 253e5c31af7Sopenharmony_ci "{\n" 254e5c31af7Sopenharmony_ci "}\n"; 255e5c31af7Sopenharmony_ci return result; 256e5c31af7Sopenharmony_ci} 257e5c31af7Sopenharmony_ci 258e5c31af7Sopenharmony_ci/** Returns code for Vertex Shader 259e5c31af7Sopenharmony_ci * @return pointer to literal with Vertex Shader code 260e5c31af7Sopenharmony_ci **/ 261e5c31af7Sopenharmony_ciconst char* GeometryShaderAdjacency::getVertexShaderCode() 262e5c31af7Sopenharmony_ci{ 263e5c31af7Sopenharmony_ci static const char* result = "${VERSION}\n" 264e5c31af7Sopenharmony_ci "\n" 265e5c31af7Sopenharmony_ci "precision highp float;\n" 266e5c31af7Sopenharmony_ci "\n" 267e5c31af7Sopenharmony_ci "layout(location = 0) in vec2 position_data;\n" 268e5c31af7Sopenharmony_ci "\n" 269e5c31af7Sopenharmony_ci "void main()\n" 270e5c31af7Sopenharmony_ci "{\n" 271e5c31af7Sopenharmony_ci " gl_Position = vec4(position_data, 0, 1);\n" 272e5c31af7Sopenharmony_ci "}\n"; 273e5c31af7Sopenharmony_ci return result; 274e5c31af7Sopenharmony_ci} 275e5c31af7Sopenharmony_ci 276e5c31af7Sopenharmony_ci/** Initializes GLES objects used during the test. 277e5c31af7Sopenharmony_ci * 278e5c31af7Sopenharmony_ci **/ 279e5c31af7Sopenharmony_civoid GeometryShaderAdjacency::initTest(void) 280e5c31af7Sopenharmony_ci{ 281e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 282e5c31af7Sopenharmony_ci 283e5c31af7Sopenharmony_ci /* check if EXT_geometry_shader extension is supported */ 284e5c31af7Sopenharmony_ci if (!m_is_geometry_shader_extension_supported) 285e5c31af7Sopenharmony_ci { 286e5c31af7Sopenharmony_ci throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 287e5c31af7Sopenharmony_ci } 288e5c31af7Sopenharmony_ci 289e5c31af7Sopenharmony_ci gl.genVertexArrays(1, &m_vao_id); 290e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 291e5c31af7Sopenharmony_ci 292e5c31af7Sopenharmony_ci /* Get shader code */ 293e5c31af7Sopenharmony_ci const char* fsCode = getFragmentShaderCode(); 294e5c31af7Sopenharmony_ci const char* gsCode = m_test_data.m_gs_code; 295e5c31af7Sopenharmony_ci const char* vsCode = getVertexShaderCode(); 296e5c31af7Sopenharmony_ci 297e5c31af7Sopenharmony_ci /* Create shader and program objects */ 298e5c31af7Sopenharmony_ci m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 299e5c31af7Sopenharmony_ci m_vs_id = gl.createShader(GL_VERTEX_SHADER); 300e5c31af7Sopenharmony_ci m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 301e5c31af7Sopenharmony_ci m_po_id = gl.createProgram(); 302e5c31af7Sopenharmony_ci 303e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program/shader objects."); 304e5c31af7Sopenharmony_ci 305e5c31af7Sopenharmony_ci /* If gs code is available set gs out data for transformfeedback*/ 306e5c31af7Sopenharmony_ci if (m_test_data.m_gs_code) 307e5c31af7Sopenharmony_ci { 308e5c31af7Sopenharmony_ci const char* varyings[] = { "out_adjacent_geometry", "out_geometry" }; 309e5c31af7Sopenharmony_ci 310e5c31af7Sopenharmony_ci gl.transformFeedbackVaryings(m_po_id, 2, varyings, GL_SEPARATE_ATTRIBS); 311e5c31af7Sopenharmony_ci } 312e5c31af7Sopenharmony_ci else 313e5c31af7Sopenharmony_ci { 314e5c31af7Sopenharmony_ci const char* varyings[] = { "gl_Position" }; 315e5c31af7Sopenharmony_ci 316e5c31af7Sopenharmony_ci gl.transformFeedbackVaryings(m_po_id, 1, varyings, GL_SEPARATE_ATTRIBS); 317e5c31af7Sopenharmony_ci } 318e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring vertex array object!"); 319e5c31af7Sopenharmony_ci 320e5c31af7Sopenharmony_ci /* Build program */ 321e5c31af7Sopenharmony_ci if (!buildProgram(m_po_id, m_fs_id, 1, /* parts */ &fsCode, (gsCode) ? m_gs_id : 0, (gsCode) ? 1 : 0, 322e5c31af7Sopenharmony_ci (gsCode) ? &gsCode : 0, m_vs_id, 1, /* parts */ &vsCode)) 323e5c31af7Sopenharmony_ci { 324e5c31af7Sopenharmony_ci TCU_FAIL("Could not create a program object from a valid shader!"); 325e5c31af7Sopenharmony_ci } 326e5c31af7Sopenharmony_ci 327e5c31af7Sopenharmony_ci /* Generate buffers for input/output vertex data */ 328e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_vertex_data_bo_id); 329e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_adjacency_geometry_bo_id); 330e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_geometry_bo_id); 331e5c31af7Sopenharmony_ci 332e5c31af7Sopenharmony_ci /* Configure buffers for input/output vertex data */ 333e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, m_adjacency_geometry_bo_id); 334e5c31af7Sopenharmony_ci gl.bufferData(GL_ARRAY_BUFFER, m_test_data.m_geometry_bo_size * 4, 0, GL_DYNAMIC_DRAW); 335e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, m_geometry_bo_id); 336e5c31af7Sopenharmony_ci gl.bufferData(GL_ARRAY_BUFFER, m_test_data.m_geometry_bo_size * 4, 0, GL_DYNAMIC_DRAW); 337e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, m_vertex_data_bo_id); 338e5c31af7Sopenharmony_ci gl.bufferData(GL_ARRAY_BUFFER, m_test_data.m_vertex_data_bo_size, m_test_data.m_vertex_data, GL_DYNAMIC_DRAW); 339e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, 0); 340e5c31af7Sopenharmony_ci 341e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring vertex buffer objects for vertex data!"); 342e5c31af7Sopenharmony_ci 343e5c31af7Sopenharmony_ci /* Configure buffer for index data */ 344e5c31af7Sopenharmony_ci if (m_test_data.m_index_data_bo_size > 0) 345e5c31af7Sopenharmony_ci { 346e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_index_data_bo_id); 347e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_data_bo_id); 348e5c31af7Sopenharmony_ci gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, m_test_data.m_index_data_bo_size, m_test_data.m_index_data, 349e5c31af7Sopenharmony_ci GL_DYNAMIC_DRAW); 350e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 351e5c31af7Sopenharmony_ci 352e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring vertex buffer objects for index data!"); 353e5c31af7Sopenharmony_ci } 354e5c31af7Sopenharmony_ci} 355e5c31af7Sopenharmony_ci 356e5c31af7Sopenharmony_ci/** Executes the test. 357e5c31af7Sopenharmony_ci * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 358e5c31af7Sopenharmony_ci * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 359e5c31af7Sopenharmony_ci * Note the function throws exception should an error occur! 360e5c31af7Sopenharmony_ci **/ 361e5c31af7Sopenharmony_citcu::TestNode::IterateResult GeometryShaderAdjacency::iterate(void) 362e5c31af7Sopenharmony_ci{ 363e5c31af7Sopenharmony_ci initTest(); 364e5c31af7Sopenharmony_ci 365e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 366e5c31af7Sopenharmony_ci 367e5c31af7Sopenharmony_ci /** Bind a vertex array object */ 368e5c31af7Sopenharmony_ci gl.bindVertexArray(m_vao_id); 369e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 370e5c31af7Sopenharmony_ci 371e5c31af7Sopenharmony_ci /* Bind buffer objects used as data store for transform feedback to TF binding points*/ 372e5c31af7Sopenharmony_ci if (m_test_data.m_gs_code) 373e5c31af7Sopenharmony_ci { 374e5c31af7Sopenharmony_ci gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_adjacency_geometry_bo_id); 375e5c31af7Sopenharmony_ci gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, m_geometry_bo_id); 376e5c31af7Sopenharmony_ci } 377e5c31af7Sopenharmony_ci else 378e5c31af7Sopenharmony_ci { 379e5c31af7Sopenharmony_ci gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_geometry_bo_id); 380e5c31af7Sopenharmony_ci } 381e5c31af7Sopenharmony_ci 382e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring transform feedback buffer binding points!"); 383e5c31af7Sopenharmony_ci 384e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, m_vertex_data_bo_id); 385e5c31af7Sopenharmony_ci m_position_attribute_location = gl.getAttribLocation(m_po_id, "position_data"); 386e5c31af7Sopenharmony_ci gl.vertexAttribPointer(m_position_attribute_location, m_components_input, GL_FLOAT, GL_FALSE, 0, 0); 387e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(m_position_attribute_location); 388e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting vertex attribute array for position_data attribute"); 389e5c31af7Sopenharmony_ci 390e5c31af7Sopenharmony_ci /* bind index buffer */ 391e5c31af7Sopenharmony_ci if (m_test_data.m_index_data_bo_size > 0) 392e5c31af7Sopenharmony_ci { 393e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_data_bo_id); 394e5c31af7Sopenharmony_ci } 395e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding index data buffer"); 396e5c31af7Sopenharmony_ci 397e5c31af7Sopenharmony_ci /* Configure program */ 398e5c31af7Sopenharmony_ci gl.enable(GL_RASTERIZER_DISCARD); 399e5c31af7Sopenharmony_ci gl.useProgram(m_po_id); 400e5c31af7Sopenharmony_ci gl.beginTransformFeedback(m_test_data.m_tf_mode); 401e5c31af7Sopenharmony_ci 402e5c31af7Sopenharmony_ci glw::GLuint nVertices = m_test_data.m_n_vertices * ((m_test_data.m_mode == m_glExtTokens.LINE_STRIP_ADJACENCY || 403e5c31af7Sopenharmony_ci m_test_data.m_mode == m_glExtTokens.TRIANGLE_STRIP_ADJACENCY) ? 404e5c31af7Sopenharmony_ci 1 : 405e5c31af7Sopenharmony_ci 2 /* include adjacency info */); 406e5c31af7Sopenharmony_ci 407e5c31af7Sopenharmony_ci /* Use glDrawElements if data is indicied */ 408e5c31af7Sopenharmony_ci if (m_test_data.m_index_data_bo_size > 0) 409e5c31af7Sopenharmony_ci { 410e5c31af7Sopenharmony_ci gl.drawElements(m_test_data.m_mode, nVertices, GL_UNSIGNED_INT, 0); 411e5c31af7Sopenharmony_ci } 412e5c31af7Sopenharmony_ci /* Use glDrawArrays if data is non indicied */ 413e5c31af7Sopenharmony_ci else 414e5c31af7Sopenharmony_ci { 415e5c31af7Sopenharmony_ci gl.drawArrays(m_test_data.m_mode, 0, nVertices); 416e5c31af7Sopenharmony_ci } 417e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error while trying to render"); 418e5c31af7Sopenharmony_ci 419e5c31af7Sopenharmony_ci gl.disable(GL_RASTERIZER_DISCARD); 420e5c31af7Sopenharmony_ci gl.endTransformFeedback(); 421e5c31af7Sopenharmony_ci 422e5c31af7Sopenharmony_ci /* Map result buffer objects into client space */ 423e5c31af7Sopenharmony_ci float* result_adjacency_geometry_ptr = 0; 424e5c31af7Sopenharmony_ci float* result_geometry_ptr = 0; 425e5c31af7Sopenharmony_ci 426e5c31af7Sopenharmony_ci bool hasAlternateData = m_test_data.m_alternate_expected_geometry != nullptr && 427e5c31af7Sopenharmony_ci m_test_data.m_alternate_expected_adjacency_geometry != nullptr; 428e5c31af7Sopenharmony_ci bool adjacentMatchesExpected = true; 429e5c31af7Sopenharmony_ci bool adjacentMatchesAlternateExpected = hasAlternateData; 430e5c31af7Sopenharmony_ci 431e5c31af7Sopenharmony_ci /* If gs is available read adjacency data using TF and compare with expected data*/ 432e5c31af7Sopenharmony_ci if (m_test_data.m_gs_code) 433e5c31af7Sopenharmony_ci { 434e5c31af7Sopenharmony_ci gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_adjacency_geometry_bo_id); 435e5c31af7Sopenharmony_ci result_adjacency_geometry_ptr = 436e5c31af7Sopenharmony_ci (float*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_test_data.m_geometry_bo_size, GL_MAP_READ_BIT); 437e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error when mapping data to client space"); 438e5c31af7Sopenharmony_ci 439e5c31af7Sopenharmony_ci std::stringstream sstreamExpected; 440e5c31af7Sopenharmony_ci std::stringstream sstreamAlternateExpected; 441e5c31af7Sopenharmony_ci std::stringstream sstreamResult; 442e5c31af7Sopenharmony_ci sstreamExpected << "["; 443e5c31af7Sopenharmony_ci if (hasAlternateData) 444e5c31af7Sopenharmony_ci sstreamAlternateExpected << "["; 445e5c31af7Sopenharmony_ci sstreamResult << "["; 446e5c31af7Sopenharmony_ci 447e5c31af7Sopenharmony_ci unsigned int differentExpectedIndex = 0; 448e5c31af7Sopenharmony_ci unsigned int differentAlternateExpectedIndex = 0; 449e5c31af7Sopenharmony_ci for (unsigned int n = 0; n < m_test_data.m_geometry_bo_size / sizeof(float); ++n) 450e5c31af7Sopenharmony_ci { 451e5c31af7Sopenharmony_ci sstreamExpected << m_test_data.m_expected_adjacency_geometry[n] << ", "; 452e5c31af7Sopenharmony_ci if (hasAlternateData) 453e5c31af7Sopenharmony_ci sstreamAlternateExpected << m_test_data.m_alternate_expected_adjacency_geometry[n] << ", "; 454e5c31af7Sopenharmony_ci sstreamResult << result_adjacency_geometry_ptr[n] << ", "; 455e5c31af7Sopenharmony_ci 456e5c31af7Sopenharmony_ci if (adjacentMatchesExpected && 457e5c31af7Sopenharmony_ci de::abs(result_adjacency_geometry_ptr[n] - 458e5c31af7Sopenharmony_ci m_test_data.m_expected_adjacency_geometry[n]) >= m_epsilon) 459e5c31af7Sopenharmony_ci { 460e5c31af7Sopenharmony_ci adjacentMatchesExpected = false; 461e5c31af7Sopenharmony_ci differentExpectedIndex = n; 462e5c31af7Sopenharmony_ci } 463e5c31af7Sopenharmony_ci if (adjacentMatchesAlternateExpected && 464e5c31af7Sopenharmony_ci de::abs(result_adjacency_geometry_ptr[n] - m_test_data.m_alternate_expected_adjacency_geometry[n]) >= 465e5c31af7Sopenharmony_ci m_epsilon) 466e5c31af7Sopenharmony_ci { 467e5c31af7Sopenharmony_ci adjacentMatchesAlternateExpected = false; 468e5c31af7Sopenharmony_ci differentAlternateExpectedIndex = n; 469e5c31af7Sopenharmony_ci } 470e5c31af7Sopenharmony_ci if (!adjacentMatchesExpected && !adjacentMatchesAlternateExpected) 471e5c31af7Sopenharmony_ci { 472e5c31af7Sopenharmony_ci gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 473e5c31af7Sopenharmony_ci 474e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "At [" << differentExpectedIndex 475e5c31af7Sopenharmony_ci << "] position adjacency buffer position Reference value is different than the " 476e5c31af7Sopenharmony_ci "rendered data (epsilon " 477e5c31af7Sopenharmony_ci << m_epsilon << " )" 478e5c31af7Sopenharmony_ci << " (" << m_test_data.m_expected_adjacency_geometry[differentExpectedIndex] 479e5c31af7Sopenharmony_ci << ") vs " 480e5c31af7Sopenharmony_ci << "(" << result_adjacency_geometry_ptr[differentExpectedIndex] << ")" 481e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 482e5c31af7Sopenharmony_ci 483e5c31af7Sopenharmony_ci if (hasAlternateData) 484e5c31af7Sopenharmony_ci { 485e5c31af7Sopenharmony_ci m_testCtx.getLog() 486e5c31af7Sopenharmony_ci << tcu::TestLog::Message << "At [" << differentAlternateExpectedIndex 487e5c31af7Sopenharmony_ci << "] alternate position adjacency buffer position Reference value is different than the " 488e5c31af7Sopenharmony_ci "rendered data (epsilon " 489e5c31af7Sopenharmony_ci << m_epsilon << " )" 490e5c31af7Sopenharmony_ci << " (" << m_test_data.m_alternate_expected_adjacency_geometry[differentAlternateExpectedIndex] 491e5c31af7Sopenharmony_ci << ") vs " 492e5c31af7Sopenharmony_ci << "(" << result_adjacency_geometry_ptr[differentAlternateExpectedIndex] << ")" 493e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 494e5c31af7Sopenharmony_ci } 495e5c31af7Sopenharmony_ci 496e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 497e5c31af7Sopenharmony_ci return STOP; 498e5c31af7Sopenharmony_ci } 499e5c31af7Sopenharmony_ci } 500e5c31af7Sopenharmony_ci 501e5c31af7Sopenharmony_ci sstreamExpected << "]"; 502e5c31af7Sopenharmony_ci if (hasAlternateData) 503e5c31af7Sopenharmony_ci sstreamAlternateExpected << "]"; 504e5c31af7Sopenharmony_ci sstreamResult << "]"; 505e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Adjacency Expected: " << sstreamExpected.str().c_str() 506e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 507e5c31af7Sopenharmony_ci if (hasAlternateData) 508e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 509e5c31af7Sopenharmony_ci << "Alternate adjacency Expected: " << sstreamAlternateExpected.str().c_str() 510e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 511e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Adjacency Result: " << sstreamResult.str().c_str() 512e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 513e5c31af7Sopenharmony_ci 514e5c31af7Sopenharmony_ci gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 515e5c31af7Sopenharmony_ci } 516e5c31af7Sopenharmony_ci 517e5c31af7Sopenharmony_ci /* Read vertex data using TF and compare with expected data*/ 518e5c31af7Sopenharmony_ci gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_geometry_bo_id); 519e5c31af7Sopenharmony_ci result_geometry_ptr = 520e5c31af7Sopenharmony_ci (float*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_test_data.m_geometry_bo_size, GL_MAP_READ_BIT); 521e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Error when mapping data to client space"); 522e5c31af7Sopenharmony_ci 523e5c31af7Sopenharmony_ci std::stringstream sstreamExpected; 524e5c31af7Sopenharmony_ci std::stringstream sstreamAlternateExpected; 525e5c31af7Sopenharmony_ci std::stringstream sstreamResult; 526e5c31af7Sopenharmony_ci sstreamExpected << "["; 527e5c31af7Sopenharmony_ci if (hasAlternateData) 528e5c31af7Sopenharmony_ci { 529e5c31af7Sopenharmony_ci sstreamAlternateExpected << "["; 530e5c31af7Sopenharmony_ci } 531e5c31af7Sopenharmony_ci sstreamResult << "["; 532e5c31af7Sopenharmony_ci 533e5c31af7Sopenharmony_ci bool matchesExpected = true; 534e5c31af7Sopenharmony_ci bool matchesAlternateExpected = hasAlternateData; 535e5c31af7Sopenharmony_ci unsigned int differentIndex = 0; 536e5c31af7Sopenharmony_ci unsigned int differentAlternateIndex = 0; 537e5c31af7Sopenharmony_ci 538e5c31af7Sopenharmony_ci for (unsigned int n = 0; n < m_test_data.m_geometry_bo_size / sizeof(float); ++n) 539e5c31af7Sopenharmony_ci { 540e5c31af7Sopenharmony_ci sstreamExpected << m_test_data.m_expected_geometry[n] << ", "; 541e5c31af7Sopenharmony_ci if (hasAlternateData) 542e5c31af7Sopenharmony_ci { 543e5c31af7Sopenharmony_ci sstreamAlternateExpected << m_test_data.m_alternate_expected_geometry[n] << ", "; 544e5c31af7Sopenharmony_ci } 545e5c31af7Sopenharmony_ci sstreamResult << result_geometry_ptr[n] << ", "; 546e5c31af7Sopenharmony_ci 547e5c31af7Sopenharmony_ci if (matchesExpected && de::abs(result_geometry_ptr[n] - m_test_data.m_expected_geometry[n]) >= m_epsilon) 548e5c31af7Sopenharmony_ci { 549e5c31af7Sopenharmony_ci matchesExpected = false; 550e5c31af7Sopenharmony_ci differentIndex = n; 551e5c31af7Sopenharmony_ci } 552e5c31af7Sopenharmony_ci if (matchesAlternateExpected && 553e5c31af7Sopenharmony_ci de::abs(result_geometry_ptr[n] - m_test_data.m_alternate_expected_geometry[n]) >= m_epsilon) 554e5c31af7Sopenharmony_ci { 555e5c31af7Sopenharmony_ci matchesAlternateExpected = false; 556e5c31af7Sopenharmony_ci differentAlternateIndex = n; 557e5c31af7Sopenharmony_ci } 558e5c31af7Sopenharmony_ci if (!matchesExpected && !matchesAlternateExpected) 559e5c31af7Sopenharmony_ci { 560e5c31af7Sopenharmony_ci gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 561e5c31af7Sopenharmony_ci 562e5c31af7Sopenharmony_ci m_testCtx.getLog() 563e5c31af7Sopenharmony_ci << tcu::TestLog::Message << "At [" << differentIndex 564e5c31af7Sopenharmony_ci << "] position geometry buffer position Reference value is different than the rendered data (epsilon " 565e5c31af7Sopenharmony_ci << m_epsilon << " )" 566e5c31af7Sopenharmony_ci << " (" << m_test_data.m_expected_geometry[differentIndex] << ") vs " 567e5c31af7Sopenharmony_ci << "(" << result_geometry_ptr[differentIndex] << ")" << tcu::TestLog::EndMessage; 568e5c31af7Sopenharmony_ci 569e5c31af7Sopenharmony_ci if (hasAlternateData) 570e5c31af7Sopenharmony_ci { 571e5c31af7Sopenharmony_ci m_testCtx.getLog() 572e5c31af7Sopenharmony_ci << tcu::TestLog::Message << "At [" << differentAlternateIndex 573e5c31af7Sopenharmony_ci << "] alternate position geometry buffer position Reference value is different than the rendered data (epsilon " 574e5c31af7Sopenharmony_ci << m_epsilon << " )" 575e5c31af7Sopenharmony_ci << " (" << m_test_data.m_alternate_expected_geometry[differentAlternateIndex] << ") vs " 576e5c31af7Sopenharmony_ci << "(" << result_geometry_ptr[differentAlternateIndex] << ")" << tcu::TestLog::EndMessage; 577e5c31af7Sopenharmony_ci } 578e5c31af7Sopenharmony_ci 579e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 580e5c31af7Sopenharmony_ci return STOP; 581e5c31af7Sopenharmony_ci } 582e5c31af7Sopenharmony_ci } 583e5c31af7Sopenharmony_ci 584e5c31af7Sopenharmony_ci if (matchesExpected && !adjacentMatchesExpected) 585e5c31af7Sopenharmony_ci { 586e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 587e5c31af7Sopenharmony_ci << "Geometry matches OpenGL ordering but adjacent geometry matches Vulkan ordering" 588e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 589e5c31af7Sopenharmony_ci 590e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 591e5c31af7Sopenharmony_ci return STOP; 592e5c31af7Sopenharmony_ci } 593e5c31af7Sopenharmony_ci if (matchesAlternateExpected && !adjacentMatchesAlternateExpected) 594e5c31af7Sopenharmony_ci { 595e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 596e5c31af7Sopenharmony_ci << "Geometry matches Vulkan ordering but adjacent geometry matches OpenGL ordering" 597e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 598e5c31af7Sopenharmony_ci 599e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 600e5c31af7Sopenharmony_ci return STOP; 601e5c31af7Sopenharmony_ci } 602e5c31af7Sopenharmony_ci 603e5c31af7Sopenharmony_ci sstreamExpected << "]"; 604e5c31af7Sopenharmony_ci sstreamResult << "]"; 605e5c31af7Sopenharmony_ci if (hasAlternateData) 606e5c31af7Sopenharmony_ci { 607e5c31af7Sopenharmony_ci sstreamAlternateExpected << "]"; 608e5c31af7Sopenharmony_ci 609e5c31af7Sopenharmony_ci sstreamExpected << "\nor\n" << sstreamAlternateExpected.str(); 610e5c31af7Sopenharmony_ci } 611e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Expected: " << sstreamExpected.str().c_str() 612e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 613e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Result: " << sstreamResult.str().c_str() 614e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 615e5c31af7Sopenharmony_ci 616e5c31af7Sopenharmony_ci gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 617e5c31af7Sopenharmony_ci 618e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 619e5c31af7Sopenharmony_ci return STOP; 620e5c31af7Sopenharmony_ci} 621e5c31af7Sopenharmony_ci 622e5c31af7Sopenharmony_ci} // namespace glcts 623