1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * OpenGL Conformance Test Suite 3e5c31af7Sopenharmony_ci * ----------------------------- 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright (c) 2015-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/** 25e5c31af7Sopenharmony_ci */ /*! 26e5c31af7Sopenharmony_ci * \file gl3cCullDistanceTests.cpp 27e5c31af7Sopenharmony_ci * \brief Cull Distance Test Suite Implementation 28e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/ 29e5c31af7Sopenharmony_ci 30e5c31af7Sopenharmony_ci#include "gl3cCullDistanceTests.hpp" 31e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp" 32e5c31af7Sopenharmony_ci#include "gluDefs.hpp" 33e5c31af7Sopenharmony_ci#include "gluStrUtil.hpp" 34e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 35e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 36e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp" 37e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 38e5c31af7Sopenharmony_ci 39e5c31af7Sopenharmony_ci#include <cmath> 40e5c31af7Sopenharmony_ci#include <sstream> 41e5c31af7Sopenharmony_ci#include <string> 42e5c31af7Sopenharmony_ci#include <vector> 43e5c31af7Sopenharmony_ci 44e5c31af7Sopenharmony_ci#ifndef GL_MAX_CULL_DISTANCES 45e5c31af7Sopenharmony_ci#define GL_MAX_CULL_DISTANCES (0x82F9) 46e5c31af7Sopenharmony_ci#endif 47e5c31af7Sopenharmony_ci#ifndef GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 48e5c31af7Sopenharmony_ci#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES (0x82FA) 49e5c31af7Sopenharmony_ci#endif 50e5c31af7Sopenharmony_ci 51e5c31af7Sopenharmony_cinamespace glcts 52e5c31af7Sopenharmony_ci{ 53e5c31af7Sopenharmony_ci/** @brief Build OpenGL program 54e5c31af7Sopenharmony_ci * 55e5c31af7Sopenharmony_ci * @param [in] gl OpenGL function bindings 56e5c31af7Sopenharmony_ci * @param [in] testCtx Context 57e5c31af7Sopenharmony_ci * @param [in] cs_body Compute shader source code 58e5c31af7Sopenharmony_ci * @param [in] fs_body Fragment shader source code 59e5c31af7Sopenharmony_ci * @param [in] gs_body Geometric shader source code 60e5c31af7Sopenharmony_ci * @param [in] tc_body Tessellation control shader source code 61e5c31af7Sopenharmony_ci * @param [in] te_body Tessellation evaluation shader source code 62e5c31af7Sopenharmony_ci * @param [in] vs_body Vertex shader source code 63e5c31af7Sopenharmony_ci * @param [in] n_tf_varyings Number of transform feedback varyings 64e5c31af7Sopenharmony_ci * @param [in] tf_varyings Transform feedback varyings names 65e5c31af7Sopenharmony_ci * 66e5c31af7Sopenharmony_ci * @param [out] out_program If succeeded output program GL handle, 0 otherwise. 67e5c31af7Sopenharmony_ci */ 68e5c31af7Sopenharmony_civoid CullDistance::Utilities::buildProgram(const glw::Functions& gl, tcu::TestContext& testCtx, 69e5c31af7Sopenharmony_ci const glw::GLchar* cs_body, const glw::GLchar* fs_body, 70e5c31af7Sopenharmony_ci const glw::GLchar* gs_body, const glw::GLchar* tc_body, 71e5c31af7Sopenharmony_ci const glw::GLchar* te_body, const glw::GLchar* vs_body, 72e5c31af7Sopenharmony_ci const glw::GLuint& n_tf_varyings, const glw::GLchar** tf_varyings, 73e5c31af7Sopenharmony_ci glw::GLuint* out_program) 74e5c31af7Sopenharmony_ci{ 75e5c31af7Sopenharmony_ci glw::GLuint po_id = 0; 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_ci struct _shaders_configuration 78e5c31af7Sopenharmony_ci { 79e5c31af7Sopenharmony_ci glw::GLenum type; 80e5c31af7Sopenharmony_ci const glw::GLchar* body; 81e5c31af7Sopenharmony_ci glw::GLuint id; 82e5c31af7Sopenharmony_ci } shaders_configuration[] = { { GL_COMPUTE_SHADER, cs_body, 0 }, { GL_FRAGMENT_SHADER, fs_body, 0 }, 83e5c31af7Sopenharmony_ci { GL_GEOMETRY_SHADER, gs_body, 0 }, { GL_TESS_CONTROL_SHADER, tc_body, 0 }, 84e5c31af7Sopenharmony_ci { GL_TESS_EVALUATION_SHADER, te_body, 0 }, { GL_VERTEX_SHADER, vs_body, 0 } }; 85e5c31af7Sopenharmony_ci 86e5c31af7Sopenharmony_ci const glw::GLuint n_shaders_configuration = sizeof(shaders_configuration) / sizeof(shaders_configuration[0]); 87e5c31af7Sopenharmony_ci 88e5c31af7Sopenharmony_ci /* Guard allocated OpenGL resources */ 89e5c31af7Sopenharmony_ci try 90e5c31af7Sopenharmony_ci { 91e5c31af7Sopenharmony_ci /* Create needed programs */ 92e5c31af7Sopenharmony_ci po_id = gl.createProgram(); 93e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 94e5c31af7Sopenharmony_ci 95e5c31af7Sopenharmony_ci for (glw::GLuint n_shader_index = 0; n_shader_index < n_shaders_configuration; n_shader_index++) 96e5c31af7Sopenharmony_ci { 97e5c31af7Sopenharmony_ci if (shaders_configuration[n_shader_index].body != DE_NULL) 98e5c31af7Sopenharmony_ci { 99e5c31af7Sopenharmony_ci /* Generate shader object */ 100e5c31af7Sopenharmony_ci shaders_configuration[n_shader_index].id = gl.createShader(shaders_configuration[n_shader_index].type); 101e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed"); 102e5c31af7Sopenharmony_ci 103e5c31af7Sopenharmony_ci glw::GLint compile_status = GL_FALSE; 104e5c31af7Sopenharmony_ci const glw::GLuint so_id = shaders_configuration[n_shader_index].id; 105e5c31af7Sopenharmony_ci 106e5c31af7Sopenharmony_ci /* Assign shader source code */ 107e5c31af7Sopenharmony_ci gl.shaderSource(shaders_configuration[n_shader_index].id, 1, /* count */ 108e5c31af7Sopenharmony_ci &shaders_configuration[n_shader_index].body, DE_NULL); /* length */ 109e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); 110e5c31af7Sopenharmony_ci 111e5c31af7Sopenharmony_ci gl.compileShader(so_id); 112e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 113e5c31af7Sopenharmony_ci 114e5c31af7Sopenharmony_ci gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status); 115e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 116e5c31af7Sopenharmony_ci 117e5c31af7Sopenharmony_ci if (compile_status == GL_FALSE) 118e5c31af7Sopenharmony_ci { 119e5c31af7Sopenharmony_ci std::vector<glw::GLchar> log_array(1); 120e5c31af7Sopenharmony_ci glw::GLint log_length = 0; 121e5c31af7Sopenharmony_ci std::string log_string("Failed to retrieve log"); 122e5c31af7Sopenharmony_ci 123e5c31af7Sopenharmony_ci /* Retrive compilation log length */ 124e5c31af7Sopenharmony_ci gl.getShaderiv(so_id, GL_INFO_LOG_LENGTH, &log_length); 125e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_ci log_array.resize(log_length + 1, 0); 128e5c31af7Sopenharmony_ci 129e5c31af7Sopenharmony_ci gl.getShaderInfoLog(so_id, log_length, DE_NULL, &log_array[0]); 130e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog() call failed."); 131e5c31af7Sopenharmony_ci 132e5c31af7Sopenharmony_ci log_string = std::string(&log_array[0]); 133e5c31af7Sopenharmony_ci 134e5c31af7Sopenharmony_ci testCtx.getLog() << tcu::TestLog::Message << "Shader compilation has failed.\n" 135e5c31af7Sopenharmony_ci << "Shader type: " << shaders_configuration[n_shader_index].type << "\n" 136e5c31af7Sopenharmony_ci << "Shader compilation error log:\n" 137e5c31af7Sopenharmony_ci << log_string << "\n" 138e5c31af7Sopenharmony_ci << "Shader source code:\n" 139e5c31af7Sopenharmony_ci << shaders_configuration[n_shader_index].body << "\n" 140e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 141e5c31af7Sopenharmony_ci 142e5c31af7Sopenharmony_ci TCU_FAIL("Shader compilation has failed."); 143e5c31af7Sopenharmony_ci } 144e5c31af7Sopenharmony_ci 145e5c31af7Sopenharmony_ci /* Also attach the shader to the corresponding program object */ 146e5c31af7Sopenharmony_ci gl.attachShader(po_id, so_id); 147e5c31af7Sopenharmony_ci 148e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed"); 149e5c31af7Sopenharmony_ci } /* if (shaders_configuration[n_shader_index].body != DE_NULL) */ 150e5c31af7Sopenharmony_ci } /* for (all shader object IDs) */ 151e5c31af7Sopenharmony_ci 152e5c31af7Sopenharmony_ci /* Set transform feedback if requested */ 153e5c31af7Sopenharmony_ci if (n_tf_varyings > 0) 154e5c31af7Sopenharmony_ci { 155e5c31af7Sopenharmony_ci gl.transformFeedbackVaryings(po_id, n_tf_varyings, tf_varyings, GL_INTERLEAVED_ATTRIBS); 156e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed"); 157e5c31af7Sopenharmony_ci } 158e5c31af7Sopenharmony_ci 159e5c31af7Sopenharmony_ci /* Try to link the program objects */ 160e5c31af7Sopenharmony_ci if (po_id != 0) 161e5c31af7Sopenharmony_ci { 162e5c31af7Sopenharmony_ci glw::GLint link_status = GL_FALSE; 163e5c31af7Sopenharmony_ci 164e5c31af7Sopenharmony_ci gl.linkProgram(po_id); 165e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed"); 166e5c31af7Sopenharmony_ci 167e5c31af7Sopenharmony_ci gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status); 168e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed"); 169e5c31af7Sopenharmony_ci 170e5c31af7Sopenharmony_ci if (link_status == GL_FALSE) 171e5c31af7Sopenharmony_ci { 172e5c31af7Sopenharmony_ci std::vector<glw::GLchar> log_array(1); 173e5c31af7Sopenharmony_ci glw::GLsizei log_length = 0; 174e5c31af7Sopenharmony_ci std::string log_string; 175e5c31af7Sopenharmony_ci 176e5c31af7Sopenharmony_ci /* Retreive compilation log length */ 177e5c31af7Sopenharmony_ci gl.getProgramiv(po_id, GL_INFO_LOG_LENGTH, &log_length); 178e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 179e5c31af7Sopenharmony_ci 180e5c31af7Sopenharmony_ci log_array.resize(log_length + 1, 0); 181e5c31af7Sopenharmony_ci 182e5c31af7Sopenharmony_ci /* Retreive compilation log */ 183e5c31af7Sopenharmony_ci gl.getProgramInfoLog(po_id, log_length, DE_NULL, &log_array[0]); 184e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog() call failed."); 185e5c31af7Sopenharmony_ci 186e5c31af7Sopenharmony_ci log_string = std::string(&log_array[0]); 187e5c31af7Sopenharmony_ci 188e5c31af7Sopenharmony_ci /* Log linking error message */ 189e5c31af7Sopenharmony_ci testCtx.getLog() << tcu::TestLog::Message << "Program linking has failed.\n" 190e5c31af7Sopenharmony_ci << "Linking error log:\n" 191e5c31af7Sopenharmony_ci << log_string << "\n" 192e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 193e5c31af7Sopenharmony_ci 194e5c31af7Sopenharmony_ci /* Log shader source code of shaders involved */ 195e5c31af7Sopenharmony_ci for (glw::GLuint n_shader_index = 0; n_shader_index < n_shaders_configuration; n_shader_index++) 196e5c31af7Sopenharmony_ci { 197e5c31af7Sopenharmony_ci if (shaders_configuration[n_shader_index].body != DE_NULL) 198e5c31af7Sopenharmony_ci { 199e5c31af7Sopenharmony_ci testCtx.getLog() << tcu::TestLog::Message << "Shader source code of type " 200e5c31af7Sopenharmony_ci << shaders_configuration[n_shader_index].type << " follows:\n" 201e5c31af7Sopenharmony_ci << shaders_configuration[n_shader_index].body << "\n" 202e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 203e5c31af7Sopenharmony_ci } 204e5c31af7Sopenharmony_ci } 205e5c31af7Sopenharmony_ci 206e5c31af7Sopenharmony_ci TCU_FAIL("Program linking failed"); 207e5c31af7Sopenharmony_ci } 208e5c31af7Sopenharmony_ci } /* if (po_id != 0) */ 209e5c31af7Sopenharmony_ci 210e5c31af7Sopenharmony_ci /* Delete all shaders we've created */ 211e5c31af7Sopenharmony_ci for (glw::GLuint n_shader_index = 0; n_shader_index < n_shaders_configuration; n_shader_index++) 212e5c31af7Sopenharmony_ci { 213e5c31af7Sopenharmony_ci const glw::GLuint so_id = shaders_configuration[n_shader_index].id; 214e5c31af7Sopenharmony_ci 215e5c31af7Sopenharmony_ci if (so_id != 0) 216e5c31af7Sopenharmony_ci { 217e5c31af7Sopenharmony_ci gl.deleteShader(so_id); 218e5c31af7Sopenharmony_ci 219e5c31af7Sopenharmony_ci shaders_configuration[n_shader_index].id = 0; 220e5c31af7Sopenharmony_ci 221e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed."); 222e5c31af7Sopenharmony_ci } 223e5c31af7Sopenharmony_ci } 224e5c31af7Sopenharmony_ci 225e5c31af7Sopenharmony_ci /* Store the result progrtam IDs */ 226e5c31af7Sopenharmony_ci *out_program = po_id; 227e5c31af7Sopenharmony_ci } 228e5c31af7Sopenharmony_ci catch (...) 229e5c31af7Sopenharmony_ci { 230e5c31af7Sopenharmony_ci /* Delete all shaders we've created */ 231e5c31af7Sopenharmony_ci for (glw::GLuint n_shader_index = 0; n_shader_index < n_shaders_configuration; n_shader_index++) 232e5c31af7Sopenharmony_ci { 233e5c31af7Sopenharmony_ci const glw::GLuint so_id = shaders_configuration[n_shader_index].id; 234e5c31af7Sopenharmony_ci 235e5c31af7Sopenharmony_ci if (so_id != 0) 236e5c31af7Sopenharmony_ci { 237e5c31af7Sopenharmony_ci gl.deleteShader(so_id); 238e5c31af7Sopenharmony_ci 239e5c31af7Sopenharmony_ci shaders_configuration[n_shader_index].id = 0; 240e5c31af7Sopenharmony_ci } 241e5c31af7Sopenharmony_ci } 242e5c31af7Sopenharmony_ci 243e5c31af7Sopenharmony_ci /* Delete the program object */ 244e5c31af7Sopenharmony_ci if (po_id != 0) 245e5c31af7Sopenharmony_ci { 246e5c31af7Sopenharmony_ci gl.deleteProgram(po_id); 247e5c31af7Sopenharmony_ci 248e5c31af7Sopenharmony_ci po_id = 0; 249e5c31af7Sopenharmony_ci } 250e5c31af7Sopenharmony_ci 251e5c31af7Sopenharmony_ci /* Rethrow */ 252e5c31af7Sopenharmony_ci throw; 253e5c31af7Sopenharmony_ci } 254e5c31af7Sopenharmony_ci} 255e5c31af7Sopenharmony_ci 256e5c31af7Sopenharmony_ci/** @brief Replace all occurences of a substring in a string by a substring 257e5c31af7Sopenharmony_ci * 258e5c31af7Sopenharmony_ci * @param [in,out] str string to be edited 259e5c31af7Sopenharmony_ci * @param [in] from substring to be replaced 260e5c31af7Sopenharmony_ci * @param [out] to new substring 261e5c31af7Sopenharmony_ci */ 262e5c31af7Sopenharmony_civoid CullDistance::Utilities::replaceAll(std::string& str, const std::string& from, const std::string& to) 263e5c31af7Sopenharmony_ci{ 264e5c31af7Sopenharmony_ci for (size_t start_pos = str.find(from, 0); start_pos != std::string::npos; start_pos = str.find(from, start_pos)) 265e5c31af7Sopenharmony_ci { 266e5c31af7Sopenharmony_ci str.replace(start_pos, from.length(), to); 267e5c31af7Sopenharmony_ci 268e5c31af7Sopenharmony_ci start_pos += to.length(); 269e5c31af7Sopenharmony_ci } 270e5c31af7Sopenharmony_ci 271e5c31af7Sopenharmony_ci return; 272e5c31af7Sopenharmony_ci} 273e5c31af7Sopenharmony_ci 274e5c31af7Sopenharmony_ci/** @brief Convert integer to string representation 275e5c31af7Sopenharmony_ci * 276e5c31af7Sopenharmony_ci * @param [in] integer input integer to be converted 277e5c31af7Sopenharmony_ci * 278e5c31af7Sopenharmony_ci * @return String representation of integer 279e5c31af7Sopenharmony_ci */ 280e5c31af7Sopenharmony_cistd::string CullDistance::Utilities::intToString(glw::GLint integer) 281e5c31af7Sopenharmony_ci{ 282e5c31af7Sopenharmony_ci std::stringstream temp_sstream; 283e5c31af7Sopenharmony_ci 284e5c31af7Sopenharmony_ci temp_sstream << integer; 285e5c31af7Sopenharmony_ci 286e5c31af7Sopenharmony_ci return temp_sstream.str(); 287e5c31af7Sopenharmony_ci} 288e5c31af7Sopenharmony_ci 289e5c31af7Sopenharmony_ci/** Constructor. 290e5c31af7Sopenharmony_ci * 291e5c31af7Sopenharmony_ci * @param context Rendering context handle. 292e5c31af7Sopenharmony_ci **/ 293e5c31af7Sopenharmony_ciCullDistance::APICoverageTest::APICoverageTest(deqp::Context& context) 294e5c31af7Sopenharmony_ci : TestCase(context, "coverage", "Cull Distance API Coverage Test") 295e5c31af7Sopenharmony_ci , m_bo_id(0) 296e5c31af7Sopenharmony_ci , m_cs_id(0) 297e5c31af7Sopenharmony_ci , m_cs_to_id(0) 298e5c31af7Sopenharmony_ci , m_fbo_draw_id(0) 299e5c31af7Sopenharmony_ci , m_fbo_draw_to_id(0) 300e5c31af7Sopenharmony_ci , m_fbo_read_id(0) 301e5c31af7Sopenharmony_ci , m_fs_id(0) 302e5c31af7Sopenharmony_ci , m_gs_id(0) 303e5c31af7Sopenharmony_ci , m_po_id(0) 304e5c31af7Sopenharmony_ci , m_tc_id(0) 305e5c31af7Sopenharmony_ci , m_te_id(0) 306e5c31af7Sopenharmony_ci , m_vao_id(0) 307e5c31af7Sopenharmony_ci , m_vs_id(0) 308e5c31af7Sopenharmony_ci{ 309e5c31af7Sopenharmony_ci /* Left blank on purpose */ 310e5c31af7Sopenharmony_ci} 311e5c31af7Sopenharmony_ci 312e5c31af7Sopenharmony_ci/** @brief Cull Distance API Coverage Test deinitialization */ 313e5c31af7Sopenharmony_civoid CullDistance::APICoverageTest::deinit() 314e5c31af7Sopenharmony_ci{ 315e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 316e5c31af7Sopenharmony_ci 317e5c31af7Sopenharmony_ci if (m_bo_id != 0) 318e5c31af7Sopenharmony_ci { 319e5c31af7Sopenharmony_ci gl.deleteBuffers(1, &m_bo_id); 320e5c31af7Sopenharmony_ci 321e5c31af7Sopenharmony_ci m_bo_id = 0; 322e5c31af7Sopenharmony_ci } 323e5c31af7Sopenharmony_ci 324e5c31af7Sopenharmony_ci if (m_cs_id != 0) 325e5c31af7Sopenharmony_ci { 326e5c31af7Sopenharmony_ci gl.deleteShader(m_cs_id); 327e5c31af7Sopenharmony_ci 328e5c31af7Sopenharmony_ci m_cs_id = 0; 329e5c31af7Sopenharmony_ci } 330e5c31af7Sopenharmony_ci 331e5c31af7Sopenharmony_ci if (m_cs_to_id != 0) 332e5c31af7Sopenharmony_ci { 333e5c31af7Sopenharmony_ci gl.deleteTextures(1, &m_cs_to_id); 334e5c31af7Sopenharmony_ci 335e5c31af7Sopenharmony_ci m_cs_to_id = 0; 336e5c31af7Sopenharmony_ci } 337e5c31af7Sopenharmony_ci 338e5c31af7Sopenharmony_ci if (m_fbo_draw_id != 0) 339e5c31af7Sopenharmony_ci { 340e5c31af7Sopenharmony_ci gl.deleteFramebuffers(1, &m_fbo_draw_id); 341e5c31af7Sopenharmony_ci 342e5c31af7Sopenharmony_ci m_fbo_draw_id = 0; 343e5c31af7Sopenharmony_ci } 344e5c31af7Sopenharmony_ci 345e5c31af7Sopenharmony_ci if (m_fbo_draw_to_id != 0) 346e5c31af7Sopenharmony_ci { 347e5c31af7Sopenharmony_ci gl.deleteTextures(1, &m_fbo_draw_to_id); 348e5c31af7Sopenharmony_ci 349e5c31af7Sopenharmony_ci m_fbo_draw_to_id = 0; 350e5c31af7Sopenharmony_ci } 351e5c31af7Sopenharmony_ci 352e5c31af7Sopenharmony_ci if (m_fbo_read_id != 0) 353e5c31af7Sopenharmony_ci { 354e5c31af7Sopenharmony_ci gl.deleteFramebuffers(1, &m_fbo_read_id); 355e5c31af7Sopenharmony_ci 356e5c31af7Sopenharmony_ci m_fbo_read_id = 0; 357e5c31af7Sopenharmony_ci } 358e5c31af7Sopenharmony_ci 359e5c31af7Sopenharmony_ci if (m_fs_id != 0) 360e5c31af7Sopenharmony_ci { 361e5c31af7Sopenharmony_ci gl.deleteShader(m_fs_id); 362e5c31af7Sopenharmony_ci 363e5c31af7Sopenharmony_ci m_fs_id = 0; 364e5c31af7Sopenharmony_ci } 365e5c31af7Sopenharmony_ci 366e5c31af7Sopenharmony_ci if (m_gs_id != 0) 367e5c31af7Sopenharmony_ci { 368e5c31af7Sopenharmony_ci gl.deleteShader(m_gs_id); 369e5c31af7Sopenharmony_ci 370e5c31af7Sopenharmony_ci m_gs_id = 0; 371e5c31af7Sopenharmony_ci } 372e5c31af7Sopenharmony_ci 373e5c31af7Sopenharmony_ci if (m_po_id != 0) 374e5c31af7Sopenharmony_ci { 375e5c31af7Sopenharmony_ci gl.deleteProgram(m_po_id); 376e5c31af7Sopenharmony_ci 377e5c31af7Sopenharmony_ci m_po_id = 0; 378e5c31af7Sopenharmony_ci } 379e5c31af7Sopenharmony_ci 380e5c31af7Sopenharmony_ci if (m_tc_id != 0) 381e5c31af7Sopenharmony_ci { 382e5c31af7Sopenharmony_ci gl.deleteShader(m_tc_id); 383e5c31af7Sopenharmony_ci 384e5c31af7Sopenharmony_ci m_tc_id = 0; 385e5c31af7Sopenharmony_ci } 386e5c31af7Sopenharmony_ci 387e5c31af7Sopenharmony_ci if (m_te_id != 0) 388e5c31af7Sopenharmony_ci { 389e5c31af7Sopenharmony_ci gl.deleteShader(m_te_id); 390e5c31af7Sopenharmony_ci 391e5c31af7Sopenharmony_ci m_te_id = 0; 392e5c31af7Sopenharmony_ci } 393e5c31af7Sopenharmony_ci 394e5c31af7Sopenharmony_ci if (m_vao_id != 0) 395e5c31af7Sopenharmony_ci { 396e5c31af7Sopenharmony_ci gl.deleteVertexArrays(1, &m_vao_id); 397e5c31af7Sopenharmony_ci 398e5c31af7Sopenharmony_ci m_vao_id = 0; 399e5c31af7Sopenharmony_ci } 400e5c31af7Sopenharmony_ci 401e5c31af7Sopenharmony_ci if (m_vs_id != 0) 402e5c31af7Sopenharmony_ci { 403e5c31af7Sopenharmony_ci gl.deleteShader(m_vs_id); 404e5c31af7Sopenharmony_ci 405e5c31af7Sopenharmony_ci m_vs_id = 0; 406e5c31af7Sopenharmony_ci } 407e5c31af7Sopenharmony_ci 408e5c31af7Sopenharmony_ci /* Restore default pack alignment value */ 409e5c31af7Sopenharmony_ci gl.pixelStorei(GL_PACK_ALIGNMENT, 4); 410e5c31af7Sopenharmony_ci} 411e5c31af7Sopenharmony_ci 412e5c31af7Sopenharmony_ci/** Executes test iteration. 413e5c31af7Sopenharmony_ci * 414e5c31af7Sopenharmony_ci * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 415e5c31af7Sopenharmony_ci */ 416e5c31af7Sopenharmony_citcu::TestNode::IterateResult CullDistance::APICoverageTest::iterate() 417e5c31af7Sopenharmony_ci{ 418e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 419e5c31af7Sopenharmony_ci 420e5c31af7Sopenharmony_ci /* This test should only be executed if ARB_cull_distance is supported, or if 421e5c31af7Sopenharmony_ci * we're running a GL4.5 context 422e5c31af7Sopenharmony_ci */ 423e5c31af7Sopenharmony_ci if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_cull_distance") && 424e5c31af7Sopenharmony_ci !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))) 425e5c31af7Sopenharmony_ci { 426e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("GL_ARB_cull_distance is not supported"); 427e5c31af7Sopenharmony_ci } 428e5c31af7Sopenharmony_ci 429e5c31af7Sopenharmony_ci /* Check that calling GetIntegerv with MAX_CULL_DISTANCES doesn't generate 430e5c31af7Sopenharmony_ci * any errors and returns a value at least 8. 431e5c31af7Sopenharmony_ci * 432e5c31af7Sopenharmony_ci * Check that calling GetIntegerv with MAX_COMBINED_CLIP_AND_CULL_DISTANCES 433e5c31af7Sopenharmony_ci * doesn't generate any errors and returns a value at least 8. 434e5c31af7Sopenharmony_ci * 435e5c31af7Sopenharmony_ci */ 436e5c31af7Sopenharmony_ci glw::GLint error_code = GL_NO_ERROR; 437e5c31af7Sopenharmony_ci glw::GLint gl_max_cull_distances_value = 0; 438e5c31af7Sopenharmony_ci glw::GLint gl_max_combined_clip_and_cull_distances_value = 0; 439e5c31af7Sopenharmony_ci 440e5c31af7Sopenharmony_ci gl.getIntegerv(GL_MAX_CULL_DISTANCES, &gl_max_cull_distances_value); 441e5c31af7Sopenharmony_ci 442e5c31af7Sopenharmony_ci error_code = gl.getError(); 443e5c31af7Sopenharmony_ci if (error_code != GL_NO_ERROR) 444e5c31af7Sopenharmony_ci { 445e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "glGetIntegerv() returned error code " 446e5c31af7Sopenharmony_ci << "[" << glu::getErrorStr(error_code) << "] for GL_MAX_CULL_DISTANCES" 447e5c31af7Sopenharmony_ci " query instead of GL_NO_ERROR" 448e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 449e5c31af7Sopenharmony_ci 450e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 451e5c31af7Sopenharmony_ci 452e5c31af7Sopenharmony_ci return STOP; 453e5c31af7Sopenharmony_ci } 454e5c31af7Sopenharmony_ci 455e5c31af7Sopenharmony_ci gl.getIntegerv(GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES, &gl_max_combined_clip_and_cull_distances_value); 456e5c31af7Sopenharmony_ci 457e5c31af7Sopenharmony_ci error_code = gl.getError(); 458e5c31af7Sopenharmony_ci if (error_code != GL_NO_ERROR) 459e5c31af7Sopenharmony_ci { 460e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "glGetIntegerv() returned error code " 461e5c31af7Sopenharmony_ci << "[" << glu::getErrorStr(error_code) << "] for " 462e5c31af7Sopenharmony_ci "GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES query " 463e5c31af7Sopenharmony_ci "instead of GL_NO_ERROR" 464e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 465e5c31af7Sopenharmony_ci 466e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 467e5c31af7Sopenharmony_ci 468e5c31af7Sopenharmony_ci return STOP; 469e5c31af7Sopenharmony_ci } 470e5c31af7Sopenharmony_ci 471e5c31af7Sopenharmony_ci /* Before we proceed with the two other tests, initialize a buffer & a texture 472e5c31af7Sopenharmony_ci * object we will need to capture data from the programs */ 473e5c31af7Sopenharmony_ci static const glw::GLuint bo_size = sizeof(int) * 4 /* components */ * 4 /* result points */; 474e5c31af7Sopenharmony_ci 475e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_bo_id); 476e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 477e5c31af7Sopenharmony_ci 478e5c31af7Sopenharmony_ci gl.genFramebuffers(1, &m_fbo_draw_id); 479e5c31af7Sopenharmony_ci gl.genFramebuffers(1, &m_fbo_read_id); 480e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call(s) failed."); 481e5c31af7Sopenharmony_ci 482e5c31af7Sopenharmony_ci gl.genTextures(1, &m_cs_to_id); 483e5c31af7Sopenharmony_ci gl.genTextures(1, &m_fbo_draw_to_id); 484e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed."); 485e5c31af7Sopenharmony_ci 486e5c31af7Sopenharmony_ci gl.genVertexArrays(1, &m_vao_id); 487e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 488e5c31af7Sopenharmony_ci 489e5c31af7Sopenharmony_ci gl.bindVertexArray(m_vao_id); 490e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 491e5c31af7Sopenharmony_ci 492e5c31af7Sopenharmony_ci gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id); 493e5c31af7Sopenharmony_ci gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */ 494e5c31af7Sopenharmony_ci m_bo_id); 495e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() or glBindBufferBase() call(s) failed."); 496e5c31af7Sopenharmony_ci 497e5c31af7Sopenharmony_ci gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL, GL_STATIC_DRAW); 498e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 499e5c31af7Sopenharmony_ci 500e5c31af7Sopenharmony_ci for (glw::GLuint n_to_id = 0; n_to_id < 2; /* CS, FBO */ ++n_to_id) 501e5c31af7Sopenharmony_ci { 502e5c31af7Sopenharmony_ci gl.bindTexture(GL_TEXTURE_2D, (n_to_id == 0) ? m_cs_to_id : m_fbo_draw_to_id); 503e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 504e5c31af7Sopenharmony_ci 505e5c31af7Sopenharmony_ci gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */ 506e5c31af7Sopenharmony_ci GL_R32I, 1, /* width */ 507e5c31af7Sopenharmony_ci 1); /* height */ 508e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed."); 509e5c31af7Sopenharmony_ci } 510e5c31af7Sopenharmony_ci 511e5c31af7Sopenharmony_ci if (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 3)) || 512e5c31af7Sopenharmony_ci m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) { 513e5c31af7Sopenharmony_ci gl.bindImageTexture(0, /* unit */ 514e5c31af7Sopenharmony_ci m_cs_to_id, 0, /* level */ 515e5c31af7Sopenharmony_ci GL_FALSE, /* layered */ 516e5c31af7Sopenharmony_ci 0, /* layer */ 517e5c31af7Sopenharmony_ci GL_WRITE_ONLY, GL_R32I); 518e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() call failed."); 519e5c31af7Sopenharmony_ci } 520e5c31af7Sopenharmony_ci 521e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_draw_id); 522e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 523e5c31af7Sopenharmony_ci 524e5c31af7Sopenharmony_ci gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_fbo_draw_to_id, 0); /* level */ 525e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed."); 526e5c31af7Sopenharmony_ci 527e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read_id); 528e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 529e5c31af7Sopenharmony_ci 530e5c31af7Sopenharmony_ci gl.viewport(0, /* x */ 531e5c31af7Sopenharmony_ci 0, /* y */ 532e5c31af7Sopenharmony_ci 1, /* width */ 533e5c31af7Sopenharmony_ci 1); /* height */ 534e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed."); 535e5c31af7Sopenharmony_ci 536e5c31af7Sopenharmony_ci gl.pixelStorei(GL_PACK_ALIGNMENT, 1); 537e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed."); 538e5c31af7Sopenharmony_ci 539e5c31af7Sopenharmony_ci /* There are two new GL constants, where value we need to verify */ 540e5c31af7Sopenharmony_ci struct _run 541e5c31af7Sopenharmony_ci { 542e5c31af7Sopenharmony_ci const glw::GLchar* essl_token_value; 543e5c31af7Sopenharmony_ci glw::GLenum gl_enum; 544e5c31af7Sopenharmony_ci glw::GLint gl_value; 545e5c31af7Sopenharmony_ci glw::GLint min_value; 546e5c31af7Sopenharmony_ci const glw::GLchar* name; 547e5c31af7Sopenharmony_ci } runs[] = { { "gl_MaxCullDistances", GL_MAX_CULL_DISTANCES, gl_max_cull_distances_value, 8 /*minimum required */, 548e5c31af7Sopenharmony_ci "GL_MAX_CULL_DISTANCES" }, 549e5c31af7Sopenharmony_ci { "gl_MaxCombinedClipAndCullDistances", GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES, 550e5c31af7Sopenharmony_ci gl_max_combined_clip_and_cull_distances_value, 8 /*minimum required */, 551e5c31af7Sopenharmony_ci "GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES" } }; 552e5c31af7Sopenharmony_ci 553e5c31af7Sopenharmony_ci static const glw::GLuint n_runs = sizeof(runs) / sizeof(runs[0]); 554e5c31af7Sopenharmony_ci 555e5c31af7Sopenharmony_ci for (glw::GLuint n_run = 0; n_run < n_runs; ++n_run) 556e5c31af7Sopenharmony_ci { 557e5c31af7Sopenharmony_ci _run& current_run = runs[n_run]; 558e5c31af7Sopenharmony_ci 559e5c31af7Sopenharmony_ci static const struct _stage 560e5c31af7Sopenharmony_ci { 561e5c31af7Sopenharmony_ci bool use_cs; 562e5c31af7Sopenharmony_ci bool use_fs; 563e5c31af7Sopenharmony_ci bool use_gs; 564e5c31af7Sopenharmony_ci bool use_tc; 565e5c31af7Sopenharmony_ci bool use_te; 566e5c31af7Sopenharmony_ci bool use_vs; 567e5c31af7Sopenharmony_ci 568e5c31af7Sopenharmony_ci const glw::GLchar* fs_input; 569e5c31af7Sopenharmony_ci const glw::GLchar* gs_input; 570e5c31af7Sopenharmony_ci const glw::GLchar* tc_input; 571e5c31af7Sopenharmony_ci const glw::GLchar* te_input; 572e5c31af7Sopenharmony_ci 573e5c31af7Sopenharmony_ci const glw::GLchar* tf_output_name; 574e5c31af7Sopenharmony_ci const glw::GLenum tf_mode; 575e5c31af7Sopenharmony_ci 576e5c31af7Sopenharmony_ci glw::GLenum draw_call_mode; 577e5c31af7Sopenharmony_ci glw::GLuint n_draw_call_vertices; 578e5c31af7Sopenharmony_ci } stages[] = { /* CS only test */ 579e5c31af7Sopenharmony_ci { 580e5c31af7Sopenharmony_ci /* use_cs|use_fs|use_gs|use_tc|use_te|use_vs */ 581e5c31af7Sopenharmony_ci true, false, false, false, false, false, 582e5c31af7Sopenharmony_ci 583e5c31af7Sopenharmony_ci NULL, /* fs_input */ 584e5c31af7Sopenharmony_ci NULL, /* gs_input */ 585e5c31af7Sopenharmony_ci NULL, /* tc_input */ 586e5c31af7Sopenharmony_ci NULL, /* te_input */ 587e5c31af7Sopenharmony_ci NULL, /* tf_output_name */ 588e5c31af7Sopenharmony_ci GL_NONE, /* tf_mode */ 589e5c31af7Sopenharmony_ci GL_NONE, /* draw_call_mode */ 590e5c31af7Sopenharmony_ci 0, /* n_draw_call_vertices */ 591e5c31af7Sopenharmony_ci }, 592e5c31af7Sopenharmony_ci /* VS+GS+TC+TE+FS test */ 593e5c31af7Sopenharmony_ci { 594e5c31af7Sopenharmony_ci /* use_cs|use_fs|use_gs|use_tc|use_te|use_vs */ 595e5c31af7Sopenharmony_ci false, true, true, true, true, true, 596e5c31af7Sopenharmony_ci 597e5c31af7Sopenharmony_ci "out_gs", /* fs_input */ 598e5c31af7Sopenharmony_ci "out_te", /* gs_input */ 599e5c31af7Sopenharmony_ci "out_vs", /* tc_input */ 600e5c31af7Sopenharmony_ci "out_tc", /* te_input */ 601e5c31af7Sopenharmony_ci "out_gs", /* tf_output_name */ 602e5c31af7Sopenharmony_ci GL_TRIANGLES, /* tf_mode */ 603e5c31af7Sopenharmony_ci GL_PATCHES, /* draw_call_mode */ 604e5c31af7Sopenharmony_ci 3, /* n_draw_call_vertices */ 605e5c31af7Sopenharmony_ci }, 606e5c31af7Sopenharmony_ci /* VS+GS+FS test */ 607e5c31af7Sopenharmony_ci { 608e5c31af7Sopenharmony_ci /* use_cs|use_fs|use_gs|use_tc|use_te|use_vs */ 609e5c31af7Sopenharmony_ci false, true, true, false, false, true, 610e5c31af7Sopenharmony_ci 611e5c31af7Sopenharmony_ci "out_gs", /* fs_input */ 612e5c31af7Sopenharmony_ci "out_vs", /* gs_input */ 613e5c31af7Sopenharmony_ci NULL, /* tc_input */ 614e5c31af7Sopenharmony_ci NULL, /* te_input */ 615e5c31af7Sopenharmony_ci "out_gs", /* tf_output_name */ 616e5c31af7Sopenharmony_ci GL_TRIANGLES, /* tf_mode */ 617e5c31af7Sopenharmony_ci GL_POINTS, /* draw_call_mode */ 618e5c31af7Sopenharmony_ci 1, /* n_draw_call_vertices */ 619e5c31af7Sopenharmony_ci }, 620e5c31af7Sopenharmony_ci /* VS+TC+TE+FS test */ 621e5c31af7Sopenharmony_ci { 622e5c31af7Sopenharmony_ci /* use_cs|use_fs|use_gs|use_tc|use_te|use_vs */ 623e5c31af7Sopenharmony_ci false, true, false, true, true, true, 624e5c31af7Sopenharmony_ci 625e5c31af7Sopenharmony_ci "out_te", /* fs_input */ 626e5c31af7Sopenharmony_ci NULL, /* gs_input */ 627e5c31af7Sopenharmony_ci "out_vs", /* tc_input */ 628e5c31af7Sopenharmony_ci "out_tc", /* te_input */ 629e5c31af7Sopenharmony_ci "out_te", /* tf_output_name */ 630e5c31af7Sopenharmony_ci GL_POINTS, /* tf_mode */ 631e5c31af7Sopenharmony_ci GL_PATCHES, /* draw_call_mode */ 632e5c31af7Sopenharmony_ci 3 /* n_draw_call_vertices */ 633e5c31af7Sopenharmony_ci }, 634e5c31af7Sopenharmony_ci /* VS test */ 635e5c31af7Sopenharmony_ci { 636e5c31af7Sopenharmony_ci /* use_cs|use_fs|use_gs|use_tc|use_te|use_vs */ 637e5c31af7Sopenharmony_ci false, false, false, false, false, true, 638e5c31af7Sopenharmony_ci 639e5c31af7Sopenharmony_ci "out_vs", /* fs_input */ 640e5c31af7Sopenharmony_ci NULL, /* gs_input */ 641e5c31af7Sopenharmony_ci NULL, /* tc_input */ 642e5c31af7Sopenharmony_ci NULL, /* te_input */ 643e5c31af7Sopenharmony_ci "out_vs", /* tf_output_name */ 644e5c31af7Sopenharmony_ci GL_POINTS, /* tf_mode */ 645e5c31af7Sopenharmony_ci GL_POINTS, /* draw_call_mode */ 646e5c31af7Sopenharmony_ci 1 /* n_draw_call_vertices */ 647e5c31af7Sopenharmony_ci } 648e5c31af7Sopenharmony_ci }; 649e5c31af7Sopenharmony_ci const glw::GLuint n_stages = sizeof(stages) / sizeof(stages[0]); 650e5c31af7Sopenharmony_ci 651e5c31af7Sopenharmony_ci /* Run through all test stages */ 652e5c31af7Sopenharmony_ci for (glw::GLuint n_stage = 0; n_stage < n_stages; ++n_stage) 653e5c31af7Sopenharmony_ci { 654e5c31af7Sopenharmony_ci /* Check for OpenGL feature support */ 655e5c31af7Sopenharmony_ci if (stages[n_stage].use_cs) 656e5c31af7Sopenharmony_ci { 657e5c31af7Sopenharmony_ci if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 3)) && 658e5c31af7Sopenharmony_ci !m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) 659e5c31af7Sopenharmony_ci { 660e5c31af7Sopenharmony_ci continue; // no compute shader support 661e5c31af7Sopenharmony_ci } 662e5c31af7Sopenharmony_ci } 663e5c31af7Sopenharmony_ci if (stages[n_stage].use_tc || stages[n_stage].use_te) 664e5c31af7Sopenharmony_ci { 665e5c31af7Sopenharmony_ci if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)) && 666e5c31af7Sopenharmony_ci !m_context.getContextInfo().isExtensionSupported("GL_ARB_tessellation_shader")) 667e5c31af7Sopenharmony_ci { 668e5c31af7Sopenharmony_ci continue; // no tessellation shader support 669e5c31af7Sopenharmony_ci } 670e5c31af7Sopenharmony_ci } 671e5c31af7Sopenharmony_ci 672e5c31af7Sopenharmony_ci /* Check that use of the GLSL built-in constant gl_MaxCullDistance in any 673e5c31af7Sopenharmony_ci * shader stage (including compute shader) does not affect the shader 674e5c31af7Sopenharmony_ci * compilation & program linking process. 675e5c31af7Sopenharmony_ci */ 676e5c31af7Sopenharmony_ci static const glw::GLchar* cs_body_template = 677e5c31af7Sopenharmony_ci "#version 420 core\n" 678e5c31af7Sopenharmony_ci "\n" 679e5c31af7Sopenharmony_ci "#extension GL_ARB_compute_shader : require\n" 680e5c31af7Sopenharmony_ci "#extension GL_ARB_cull_distance : require\n" 681e5c31af7Sopenharmony_ci "#extension GL_ARB_shader_image_load_store : require\n" 682e5c31af7Sopenharmony_ci "\n" 683e5c31af7Sopenharmony_ci "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 684e5c31af7Sopenharmony_ci "\n" 685e5c31af7Sopenharmony_ci "layout(r32i) uniform writeonly iimage2D result;\n" 686e5c31af7Sopenharmony_ci "\n" 687e5c31af7Sopenharmony_ci "void main()\n" 688e5c31af7Sopenharmony_ci "{\n" 689e5c31af7Sopenharmony_ci " imageStore(result, ivec2(0),ivec4(TOKEN) );\n" 690e5c31af7Sopenharmony_ci "}\n"; 691e5c31af7Sopenharmony_ci std::string cs_body = cs_body_template; 692e5c31af7Sopenharmony_ci 693e5c31af7Sopenharmony_ci static const glw::GLchar* fs_body_template = "#version 150\n" 694e5c31af7Sopenharmony_ci "\n" 695e5c31af7Sopenharmony_ci "#extension GL_ARB_cull_distance : require\n" 696e5c31af7Sopenharmony_ci "\n" 697e5c31af7Sopenharmony_ci "flat in int INPUT_FS_NAME;\n" 698e5c31af7Sopenharmony_ci "out int out_fs;\n" 699e5c31af7Sopenharmony_ci "\n" 700e5c31af7Sopenharmony_ci "void main()\n" 701e5c31af7Sopenharmony_ci "{\n" 702e5c31af7Sopenharmony_ci " if (INPUT_FS_NAME == TOKEN)\n" 703e5c31af7Sopenharmony_ci " {\n" 704e5c31af7Sopenharmony_ci " out_fs = TOKEN;\n" 705e5c31af7Sopenharmony_ci " }\n" 706e5c31af7Sopenharmony_ci " else\n" 707e5c31af7Sopenharmony_ci " {\n" 708e5c31af7Sopenharmony_ci " out_fs = -1;\n" 709e5c31af7Sopenharmony_ci " }\n" 710e5c31af7Sopenharmony_ci "}\n"; 711e5c31af7Sopenharmony_ci std::string fs_body = fs_body_template; 712e5c31af7Sopenharmony_ci 713e5c31af7Sopenharmony_ci static const glw::GLchar* gs_body_template = 714e5c31af7Sopenharmony_ci "#version 150\n" 715e5c31af7Sopenharmony_ci "\n" 716e5c31af7Sopenharmony_ci "#extension GL_ARB_cull_distance : require\n" 717e5c31af7Sopenharmony_ci "\n" 718e5c31af7Sopenharmony_ci "flat in int INPUT_GS_NAME[];\n" 719e5c31af7Sopenharmony_ci "flat out int out_gs;\n" 720e5c31af7Sopenharmony_ci "\n" 721e5c31af7Sopenharmony_ci "layout(points) in;\n" 722e5c31af7Sopenharmony_ci "layout(triangle_strip, max_vertices = 4) out;\n" 723e5c31af7Sopenharmony_ci "\n" 724e5c31af7Sopenharmony_ci "void main()\n" 725e5c31af7Sopenharmony_ci "{\n" 726e5c31af7Sopenharmony_ci " int result_value = (INPUT_GS_NAME[0] == TOKEN) ? TOKEN : -1;\n" 727e5c31af7Sopenharmony_ci "\n" 728e5c31af7Sopenharmony_ci /* Draw a full-screen quad */ 729e5c31af7Sopenharmony_ci " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 730e5c31af7Sopenharmony_ci " out_gs = result_value;\n" 731e5c31af7Sopenharmony_ci " EmitVertex();\n" 732e5c31af7Sopenharmony_ci "\n" 733e5c31af7Sopenharmony_ci " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 734e5c31af7Sopenharmony_ci " out_gs = result_value;\n" 735e5c31af7Sopenharmony_ci " EmitVertex();\n" 736e5c31af7Sopenharmony_ci "\n" 737e5c31af7Sopenharmony_ci " gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n" 738e5c31af7Sopenharmony_ci " out_gs = result_value;\n" 739e5c31af7Sopenharmony_ci " EmitVertex();\n" 740e5c31af7Sopenharmony_ci "\n" 741e5c31af7Sopenharmony_ci " gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n" 742e5c31af7Sopenharmony_ci " out_gs = result_value;\n" 743e5c31af7Sopenharmony_ci " EmitVertex();\n" 744e5c31af7Sopenharmony_ci " EndPrimitive();\n" 745e5c31af7Sopenharmony_ci "}\n"; 746e5c31af7Sopenharmony_ci std::string gs_body = gs_body_template; 747e5c31af7Sopenharmony_ci 748e5c31af7Sopenharmony_ci static const glw::GLchar* tc_body_template = 749e5c31af7Sopenharmony_ci "#version 150\n" 750e5c31af7Sopenharmony_ci "\n" 751e5c31af7Sopenharmony_ci "#extension GL_ARB_cull_distance : require\n" 752e5c31af7Sopenharmony_ci "#extension GL_ARB_tessellation_shader : require\n" 753e5c31af7Sopenharmony_ci "\n" 754e5c31af7Sopenharmony_ci "layout(vertices = 1) out;\n" 755e5c31af7Sopenharmony_ci "\n" 756e5c31af7Sopenharmony_ci "flat in int INPUT_TC_NAME[];\n" 757e5c31af7Sopenharmony_ci "flat out int out_tc [];\n" 758e5c31af7Sopenharmony_ci "\n" 759e5c31af7Sopenharmony_ci "void main()\n" 760e5c31af7Sopenharmony_ci "{\n" 761e5c31af7Sopenharmony_ci " int result_value = (INPUT_TC_NAME[0] == TOKEN) ? TOKEN : -1;\n" 762e5c31af7Sopenharmony_ci "\n" 763e5c31af7Sopenharmony_ci " out_tc[gl_InvocationID] = result_value;\n" 764e5c31af7Sopenharmony_ci " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 765e5c31af7Sopenharmony_ci " gl_TessLevelInner[0] = 1.0;\n" 766e5c31af7Sopenharmony_ci " gl_TessLevelInner[1] = 1.0;\n" 767e5c31af7Sopenharmony_ci " gl_TessLevelOuter[0] = 1.0;\n" 768e5c31af7Sopenharmony_ci " gl_TessLevelOuter[1] = 1.0;\n" 769e5c31af7Sopenharmony_ci " gl_TessLevelOuter[2] = 1.0;\n" 770e5c31af7Sopenharmony_ci " gl_TessLevelOuter[3] = 1.0;\n" 771e5c31af7Sopenharmony_ci "}\n"; 772e5c31af7Sopenharmony_ci std::string tc_body = tc_body_template; 773e5c31af7Sopenharmony_ci 774e5c31af7Sopenharmony_ci static const glw::GLchar* te_body_template = 775e5c31af7Sopenharmony_ci "#version 150\n" 776e5c31af7Sopenharmony_ci "\n" 777e5c31af7Sopenharmony_ci "#extension GL_ARB_cull_distance : require\n" 778e5c31af7Sopenharmony_ci "#extension GL_ARB_tessellation_shader : require\n" 779e5c31af7Sopenharmony_ci "\n" 780e5c31af7Sopenharmony_ci "flat in int INPUT_TE_NAME[];\n" 781e5c31af7Sopenharmony_ci "flat out int out_te;\n" 782e5c31af7Sopenharmony_ci "\n" 783e5c31af7Sopenharmony_ci "layout(isolines, point_mode) in;\n" 784e5c31af7Sopenharmony_ci "\n" 785e5c31af7Sopenharmony_ci "void main()\n" 786e5c31af7Sopenharmony_ci "{\n" 787e5c31af7Sopenharmony_ci " int result_value = (INPUT_TE_NAME[0] == TOKEN) ? TOKEN : 0;\n" 788e5c31af7Sopenharmony_ci "\n" 789e5c31af7Sopenharmony_ci " out_te = result_value;\n" 790e5c31af7Sopenharmony_ci "\n" 791e5c31af7Sopenharmony_ci " gl_Position = vec4(0.0, 0.0, 0.0, 1.);\n" 792e5c31af7Sopenharmony_ci "}\n"; 793e5c31af7Sopenharmony_ci std::string te_body = te_body_template; 794e5c31af7Sopenharmony_ci 795e5c31af7Sopenharmony_ci static const glw::GLchar* vs_body_template = "#version 150\n" 796e5c31af7Sopenharmony_ci "\n" 797e5c31af7Sopenharmony_ci "#extension GL_ARB_cull_distance : require\n" 798e5c31af7Sopenharmony_ci "\n" 799e5c31af7Sopenharmony_ci "flat out int out_vs;\n" 800e5c31af7Sopenharmony_ci "\n" 801e5c31af7Sopenharmony_ci "void main()\n" 802e5c31af7Sopenharmony_ci "{\n" 803e5c31af7Sopenharmony_ci " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" 804e5c31af7Sopenharmony_ci " out_vs = TOKEN;\n" 805e5c31af7Sopenharmony_ci "}\n"; 806e5c31af7Sopenharmony_ci std::string vs_body = vs_body_template; 807e5c31af7Sopenharmony_ci 808e5c31af7Sopenharmony_ci const _stage& current_stage = stages[n_stage]; 809e5c31af7Sopenharmony_ci 810e5c31af7Sopenharmony_ci /* Build shader bodies */ 811e5c31af7Sopenharmony_ci struct _shader_body 812e5c31af7Sopenharmony_ci { 813e5c31af7Sopenharmony_ci std::string* body_ptr; 814e5c31af7Sopenharmony_ci glw::GLenum gl_type; 815e5c31af7Sopenharmony_ci } shader_bodies[] = { { &cs_body, GL_COMPUTE_SHADER }, { &fs_body, GL_FRAGMENT_SHADER }, 816e5c31af7Sopenharmony_ci { &gs_body, GL_GEOMETRY_SHADER }, { &tc_body, GL_TESS_CONTROL_SHADER }, 817e5c31af7Sopenharmony_ci { &te_body, GL_TESS_EVALUATION_SHADER }, { &vs_body, GL_VERTEX_SHADER } }; 818e5c31af7Sopenharmony_ci static const glw::GLchar* input_fs_token_string = "INPUT_FS_NAME"; 819e5c31af7Sopenharmony_ci static const glw::GLchar* input_gs_token_string = "INPUT_GS_NAME"; 820e5c31af7Sopenharmony_ci static const glw::GLchar* input_te_token_string = "INPUT_TE_NAME"; 821e5c31af7Sopenharmony_ci static const glw::GLchar* input_tc_token_string = "INPUT_TC_NAME"; 822e5c31af7Sopenharmony_ci static const glw::GLuint n_shader_bodies = sizeof(shader_bodies) / sizeof(shader_bodies[0]); 823e5c31af7Sopenharmony_ci 824e5c31af7Sopenharmony_ci std::size_t token_position = std::string::npos; 825e5c31af7Sopenharmony_ci static const glw::GLchar* token_string = "TOKEN"; 826e5c31af7Sopenharmony_ci 827e5c31af7Sopenharmony_ci for (glw::GLuint n_shader_body = 0; n_shader_body < n_shader_bodies; ++n_shader_body) 828e5c31af7Sopenharmony_ci { 829e5c31af7Sopenharmony_ci _shader_body& current_body = shader_bodies[n_shader_body]; 830e5c31af7Sopenharmony_ci 831e5c31af7Sopenharmony_ci /* Is this stage actually used? */ 832e5c31af7Sopenharmony_ci if (((current_body.gl_type == GL_COMPUTE_SHADER) && (!current_stage.use_cs)) || 833e5c31af7Sopenharmony_ci ((current_body.gl_type == GL_FRAGMENT_SHADER) && (!current_stage.use_fs)) || 834e5c31af7Sopenharmony_ci ((current_body.gl_type == GL_TESS_CONTROL_SHADER) && (!current_stage.use_tc)) || 835e5c31af7Sopenharmony_ci ((current_body.gl_type == GL_TESS_EVALUATION_SHADER) && (!current_stage.use_te)) || 836e5c31af7Sopenharmony_ci ((current_body.gl_type == GL_VERTEX_SHADER) && (!current_stage.use_vs))) 837e5c31af7Sopenharmony_ci { 838e5c31af7Sopenharmony_ci /* Skip the iteration. */ 839e5c31af7Sopenharmony_ci continue; 840e5c31af7Sopenharmony_ci } 841e5c31af7Sopenharmony_ci 842e5c31af7Sopenharmony_ci /* Iterate over all token and replace them with stage-specific values */ 843e5c31af7Sopenharmony_ci struct _token_value_pair 844e5c31af7Sopenharmony_ci { 845e5c31af7Sopenharmony_ci const glw::GLchar* token; 846e5c31af7Sopenharmony_ci const glw::GLchar* value; 847e5c31af7Sopenharmony_ci } token_value_pairs[] = { 848e5c31af7Sopenharmony_ci /* NOTE: The last entry is filled by the switch() block below */ 849e5c31af7Sopenharmony_ci { token_string, current_run.essl_token_value }, 850e5c31af7Sopenharmony_ci { NULL, NULL }, 851e5c31af7Sopenharmony_ci }; 852e5c31af7Sopenharmony_ci 853e5c31af7Sopenharmony_ci const size_t n_token_value_pairs = sizeof(token_value_pairs) / sizeof(token_value_pairs[0]); 854e5c31af7Sopenharmony_ci 855e5c31af7Sopenharmony_ci switch (current_body.gl_type) 856e5c31af7Sopenharmony_ci { 857e5c31af7Sopenharmony_ci case GL_COMPUTE_SHADER: 858e5c31af7Sopenharmony_ci case GL_VERTEX_SHADER: 859e5c31af7Sopenharmony_ci break; 860e5c31af7Sopenharmony_ci 861e5c31af7Sopenharmony_ci case GL_FRAGMENT_SHADER: 862e5c31af7Sopenharmony_ci { 863e5c31af7Sopenharmony_ci token_value_pairs[1].token = input_fs_token_string; 864e5c31af7Sopenharmony_ci token_value_pairs[1].value = current_stage.fs_input; 865e5c31af7Sopenharmony_ci 866e5c31af7Sopenharmony_ci break; 867e5c31af7Sopenharmony_ci } 868e5c31af7Sopenharmony_ci 869e5c31af7Sopenharmony_ci case GL_GEOMETRY_SHADER: 870e5c31af7Sopenharmony_ci { 871e5c31af7Sopenharmony_ci token_value_pairs[1].token = input_gs_token_string; 872e5c31af7Sopenharmony_ci token_value_pairs[1].value = current_stage.gs_input; 873e5c31af7Sopenharmony_ci 874e5c31af7Sopenharmony_ci break; 875e5c31af7Sopenharmony_ci } 876e5c31af7Sopenharmony_ci 877e5c31af7Sopenharmony_ci case GL_TESS_CONTROL_SHADER: 878e5c31af7Sopenharmony_ci { 879e5c31af7Sopenharmony_ci token_value_pairs[1].token = input_tc_token_string; 880e5c31af7Sopenharmony_ci token_value_pairs[1].value = current_stage.tc_input; 881e5c31af7Sopenharmony_ci 882e5c31af7Sopenharmony_ci break; 883e5c31af7Sopenharmony_ci } 884e5c31af7Sopenharmony_ci 885e5c31af7Sopenharmony_ci case GL_TESS_EVALUATION_SHADER: 886e5c31af7Sopenharmony_ci { 887e5c31af7Sopenharmony_ci token_value_pairs[1].token = input_te_token_string; 888e5c31af7Sopenharmony_ci token_value_pairs[1].value = current_stage.te_input; 889e5c31af7Sopenharmony_ci 890e5c31af7Sopenharmony_ci break; 891e5c31af7Sopenharmony_ci } 892e5c31af7Sopenharmony_ci 893e5c31af7Sopenharmony_ci default: 894e5c31af7Sopenharmony_ci TCU_FAIL("Unrecognized shader body type"); 895e5c31af7Sopenharmony_ci } 896e5c31af7Sopenharmony_ci 897e5c31af7Sopenharmony_ci for (glw::GLuint n_pair = 0; n_pair < n_token_value_pairs; ++n_pair) 898e5c31af7Sopenharmony_ci { 899e5c31af7Sopenharmony_ci const _token_value_pair& current_pair = token_value_pairs[n_pair]; 900e5c31af7Sopenharmony_ci 901e5c31af7Sopenharmony_ci if (current_pair.token == NULL || current_pair.value == NULL) 902e5c31af7Sopenharmony_ci { 903e5c31af7Sopenharmony_ci continue; 904e5c31af7Sopenharmony_ci } 905e5c31af7Sopenharmony_ci 906e5c31af7Sopenharmony_ci while ((token_position = current_body.body_ptr->find(current_pair.token)) != std::string::npos) 907e5c31af7Sopenharmony_ci { 908e5c31af7Sopenharmony_ci current_body.body_ptr->replace(token_position, strlen(current_pair.token), current_pair.value); 909e5c31af7Sopenharmony_ci } 910e5c31af7Sopenharmony_ci } /* for (all token+value pairs) */ 911e5c31af7Sopenharmony_ci } /* for (all sader bodies) */ 912e5c31af7Sopenharmony_ci 913e5c31af7Sopenharmony_ci /* Build the test program */ 914e5c31af7Sopenharmony_ci CullDistance::Utilities::buildProgram( 915e5c31af7Sopenharmony_ci gl, m_testCtx, current_stage.use_cs ? cs_body.c_str() : DE_NULL, 916e5c31af7Sopenharmony_ci current_stage.use_fs ? fs_body.c_str() : DE_NULL, current_stage.use_gs ? gs_body.c_str() : DE_NULL, 917e5c31af7Sopenharmony_ci current_stage.use_tc ? tc_body.c_str() : DE_NULL, current_stage.use_te ? te_body.c_str() : DE_NULL, 918e5c31af7Sopenharmony_ci current_stage.use_vs ? vs_body.c_str() : DE_NULL, (current_stage.tf_output_name != NULL) ? 1 : 0, 919e5c31af7Sopenharmony_ci (const glw::GLchar**)¤t_stage.tf_output_name, &m_po_id); 920e5c31af7Sopenharmony_ci 921e5c31af7Sopenharmony_ci /* Bind the test program */ 922e5c31af7Sopenharmony_ci DE_ASSERT(m_po_id != 0); 923e5c31af7Sopenharmony_ci 924e5c31af7Sopenharmony_ci gl.useProgram(m_po_id); 925e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 926e5c31af7Sopenharmony_ci 927e5c31af7Sopenharmony_ci /* Execute the draw call. Transform Feed-back should be enabled for all iterations 928e5c31af7Sopenharmony_ci * par the CS one, since we use a different tool to capture the result data in the 929e5c31af7Sopenharmony_ci * latter case. 930e5c31af7Sopenharmony_ci */ 931e5c31af7Sopenharmony_ci if (!current_stage.use_cs) 932e5c31af7Sopenharmony_ci { 933e5c31af7Sopenharmony_ci gl.beginTransformFeedback(current_stage.tf_mode); 934e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed."); 935e5c31af7Sopenharmony_ci 936e5c31af7Sopenharmony_ci gl.drawArrays(current_stage.draw_call_mode, 0, /* first */ 937e5c31af7Sopenharmony_ci current_stage.n_draw_call_vertices); /* count */ 938e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed."); 939e5c31af7Sopenharmony_ci 940e5c31af7Sopenharmony_ci gl.endTransformFeedback(); 941e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed."); 942e5c31af7Sopenharmony_ci } /* if (uses_tf) */ 943e5c31af7Sopenharmony_ci else 944e5c31af7Sopenharmony_ci { 945e5c31af7Sopenharmony_ci gl.dispatchCompute(1, /* num_groups_x */ 946e5c31af7Sopenharmony_ci 1, /* num_groups_y */ 947e5c31af7Sopenharmony_ci 1); /* num_groups_z */ 948e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute() call failed."); 949e5c31af7Sopenharmony_ci } 950e5c31af7Sopenharmony_ci 951e5c31af7Sopenharmony_ci /* Verify the result values */ 952e5c31af7Sopenharmony_ci if (!current_stage.use_cs) 953e5c31af7Sopenharmony_ci { 954e5c31af7Sopenharmony_ci glw::GLint* result_data_ptr = DE_NULL; 955e5c31af7Sopenharmony_ci 956e5c31af7Sopenharmony_ci /* Retrieve the data captured by Transform Feedback */ 957e5c31af7Sopenharmony_ci result_data_ptr = (glw::GLint*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 958e5c31af7Sopenharmony_ci sizeof(unsigned int) * 1, GL_MAP_READ_BIT); 959e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed."); 960e5c31af7Sopenharmony_ci 961e5c31af7Sopenharmony_ci if (*result_data_ptr != current_run.gl_value) 962e5c31af7Sopenharmony_ci { 963e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << current_run.name << " value " 964e5c31af7Sopenharmony_ci "[" 965e5c31af7Sopenharmony_ci << *result_data_ptr << "]" 966e5c31af7Sopenharmony_ci " does not match the one reported by glGetIntegerv() " 967e5c31af7Sopenharmony_ci "[" 968e5c31af7Sopenharmony_ci << current_run.gl_value << "]" << tcu::TestLog::EndMessage; 969e5c31af7Sopenharmony_ci 970e5c31af7Sopenharmony_ci TCU_FAIL("GL constant value does not match the ES SL equivalent"); 971e5c31af7Sopenharmony_ci } 972e5c31af7Sopenharmony_ci 973e5c31af7Sopenharmony_ci if (*result_data_ptr < current_run.min_value) 974e5c31af7Sopenharmony_ci { 975e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << current_run.name << " value " 976e5c31af7Sopenharmony_ci "[" 977e5c31af7Sopenharmony_ci << *result_data_ptr << "]" 978e5c31af7Sopenharmony_ci " does not meet the minimum specification requirements " 979e5c31af7Sopenharmony_ci "[" 980e5c31af7Sopenharmony_ci << current_run.min_value << "]" << tcu::TestLog::EndMessage; 981e5c31af7Sopenharmony_ci 982e5c31af7Sopenharmony_ci TCU_FAIL("GL constant value does not meet minimum specification requirements"); 983e5c31af7Sopenharmony_ci } 984e5c31af7Sopenharmony_ci 985e5c31af7Sopenharmony_ci gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 986e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); 987e5c31af7Sopenharmony_ci } 988e5c31af7Sopenharmony_ci 989e5c31af7Sopenharmony_ci for (glw::GLuint n_stage_internal = 0; n_stage_internal < 2; /* CS, FS write to separate textures */ 990e5c31af7Sopenharmony_ci ++n_stage_internal) 991e5c31af7Sopenharmony_ci { 992e5c31af7Sopenharmony_ci glw::GLuint to_id = (n_stage_internal == 0) ? m_cs_to_id : m_fbo_draw_to_id; 993e5c31af7Sopenharmony_ci 994e5c31af7Sopenharmony_ci if (((n_stage_internal == 0) && (!current_stage.use_cs)) || 995e5c31af7Sopenharmony_ci ((n_stage_internal == 1) && (!current_stage.use_fs))) 996e5c31af7Sopenharmony_ci { 997e5c31af7Sopenharmony_ci /* Skip the iteration */ 998e5c31af7Sopenharmony_ci continue; 999e5c31af7Sopenharmony_ci } 1000e5c31af7Sopenharmony_ci 1001e5c31af7Sopenharmony_ci /* Check the image data the test CS / FS should have written */ 1002e5c31af7Sopenharmony_ci glw::GLint result_value = 0; 1003e5c31af7Sopenharmony_ci 1004e5c31af7Sopenharmony_ci gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, to_id, 0); /* level */ 1005e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed."); 1006e5c31af7Sopenharmony_ci 1007e5c31af7Sopenharmony_ci /* NOTE: We're using our custom read framebuffer here, so we'll be reading 1008e5c31af7Sopenharmony_ci * from the texture, that the writes have been issued to earlier. */ 1009e5c31af7Sopenharmony_ci gl.finish(); 1010e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier() call failed."); 1011e5c31af7Sopenharmony_ci 1012e5c31af7Sopenharmony_ci gl.readPixels(0, /* x */ 1013e5c31af7Sopenharmony_ci 0, /* y */ 1014e5c31af7Sopenharmony_ci 1, /* width */ 1015e5c31af7Sopenharmony_ci 1, /* height */ 1016e5c31af7Sopenharmony_ci GL_RED_INTEGER, GL_INT, &result_value); 1017e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed."); 1018e5c31af7Sopenharmony_ci 1019e5c31af7Sopenharmony_ci if (result_value != current_run.gl_value) 1020e5c31af7Sopenharmony_ci { 1021e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << current_run.name 1022e5c31af7Sopenharmony_ci << " value accessible to the compute / fragment shader " 1023e5c31af7Sopenharmony_ci "[" 1024e5c31af7Sopenharmony_ci << result_value << "]" 1025e5c31af7Sopenharmony_ci " does not match the one reported by glGetIntegerv() " 1026e5c31af7Sopenharmony_ci "[" 1027e5c31af7Sopenharmony_ci << current_run.gl_value << "]" << tcu::TestLog::EndMessage; 1028e5c31af7Sopenharmony_ci 1029e5c31af7Sopenharmony_ci TCU_FAIL("GL constant value does not match the ES SL equivalent"); 1030e5c31af7Sopenharmony_ci } 1031e5c31af7Sopenharmony_ci 1032e5c31af7Sopenharmony_ci if (result_value < current_run.min_value) 1033e5c31af7Sopenharmony_ci { 1034e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << current_run.name 1035e5c31af7Sopenharmony_ci << " value accessible to the compute / fragment shader " 1036e5c31af7Sopenharmony_ci "[" 1037e5c31af7Sopenharmony_ci << result_value << "]" 1038e5c31af7Sopenharmony_ci " does not meet the minimum specification requirements " 1039e5c31af7Sopenharmony_ci "[" 1040e5c31af7Sopenharmony_ci << current_run.min_value << "]" << tcu::TestLog::EndMessage; 1041e5c31af7Sopenharmony_ci 1042e5c31af7Sopenharmony_ci TCU_FAIL("GL constant value does not meet minimum specification requirements"); 1043e5c31af7Sopenharmony_ci } 1044e5c31af7Sopenharmony_ci } 1045e5c31af7Sopenharmony_ci 1046e5c31af7Sopenharmony_ci /* Clear the data buffer before we continue */ 1047e5c31af7Sopenharmony_ci static const glw::GLubyte bo_clear_data[bo_size] = { 0 }; 1048e5c31af7Sopenharmony_ci 1049e5c31af7Sopenharmony_ci gl.bufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 1050e5c31af7Sopenharmony_ci bo_size, bo_clear_data); 1051e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed."); 1052e5c31af7Sopenharmony_ci 1053e5c31af7Sopenharmony_ci /* Clear the texture mip-map before we continue */ 1054e5c31af7Sopenharmony_ci glw::GLint clear_values[4] = { 0, 0, 0, 0 }; 1055e5c31af7Sopenharmony_ci 1056e5c31af7Sopenharmony_ci gl.clearBufferiv(GL_COLOR, 0, /* drawbuffer */ 1057e5c31af7Sopenharmony_ci clear_values); 1058e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferiv() call failed."); 1059e5c31af7Sopenharmony_ci 1060e5c31af7Sopenharmony_ci /* Release program before we move on to the next iteration */ 1061e5c31af7Sopenharmony_ci if (m_po_id != 0) 1062e5c31af7Sopenharmony_ci { 1063e5c31af7Sopenharmony_ci gl.deleteProgram(m_po_id); 1064e5c31af7Sopenharmony_ci 1065e5c31af7Sopenharmony_ci m_po_id = 0; 1066e5c31af7Sopenharmony_ci } 1067e5c31af7Sopenharmony_ci } /* for (all stages) */ 1068e5c31af7Sopenharmony_ci } /* for (both runs) */ 1069e5c31af7Sopenharmony_ci 1070e5c31af7Sopenharmony_ci /* All done */ 1071e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1072e5c31af7Sopenharmony_ci 1073e5c31af7Sopenharmony_ci return STOP; 1074e5c31af7Sopenharmony_ci} 1075e5c31af7Sopenharmony_ci 1076e5c31af7Sopenharmony_ci/** Constructor. 1077e5c31af7Sopenharmony_ci * 1078e5c31af7Sopenharmony_ci * @param context Rendering context handle. 1079e5c31af7Sopenharmony_ci **/ 1080e5c31af7Sopenharmony_ciCullDistance::FunctionalTest::FunctionalTest(deqp::Context& context) 1081e5c31af7Sopenharmony_ci : TestCase(context, "functional", "Cull Distance Functional Test") 1082e5c31af7Sopenharmony_ci , m_bo_data() 1083e5c31af7Sopenharmony_ci , m_bo_id(0) 1084e5c31af7Sopenharmony_ci , m_fbo_id(0) 1085e5c31af7Sopenharmony_ci , m_po_id(0) 1086e5c31af7Sopenharmony_ci , m_render_primitives(0) 1087e5c31af7Sopenharmony_ci , m_render_vertices(0) 1088e5c31af7Sopenharmony_ci , m_sub_grid_cell_size(0) 1089e5c31af7Sopenharmony_ci , m_to_id(0) 1090e5c31af7Sopenharmony_ci , m_vao_id(0) 1091e5c31af7Sopenharmony_ci , m_to_height(512) 1092e5c31af7Sopenharmony_ci , m_to_width(512) 1093e5c31af7Sopenharmony_ci , m_to_pixel_data_cache() 1094e5c31af7Sopenharmony_ci{ 1095e5c31af7Sopenharmony_ci /* Left blank on purpose */ 1096e5c31af7Sopenharmony_ci} 1097e5c31af7Sopenharmony_ci 1098e5c31af7Sopenharmony_ci/** @brief Build OpenGL program for functional tests 1099e5c31af7Sopenharmony_ci * 1100e5c31af7Sopenharmony_ci * @param [in] clipdistances_array_size use size of gl_ClipDistance array 1101e5c31af7Sopenharmony_ci * @param [in] culldistances_array_size use size of gl_CullDistance array 1102e5c31af7Sopenharmony_ci * @param [in] dynamic_index_writes use dunamic indexing for setting the gl_ClipDistance and gl_CullDistance arrays 1103e5c31af7Sopenharmony_ci * @param [in] primitive_mode primitive_mode will be used for rendering 1104e5c31af7Sopenharmony_ci * @param [in] redeclare_clipdistances redeclare gl_ClipDistance 1105e5c31af7Sopenharmony_ci * @param [in] redeclare_culldistances redeclare gl_CullDistance 1106e5c31af7Sopenharmony_ci * @param [in] use_core_functionality use core OpenGL functionality 1107e5c31af7Sopenharmony_ci * @param [in] use_gs use geometry shader 1108e5c31af7Sopenharmony_ci * @param [in] use_ts use tessellation shader 1109e5c31af7Sopenharmony_ci * @param [in] fetch_culldistance_from_fs fetch check sum of gl_ClipDistance and gl_CullDistance from fragment shader 1110e5c31af7Sopenharmony_ci */ 1111e5c31af7Sopenharmony_civoid CullDistance::FunctionalTest::buildPO(glw::GLuint clipdistances_array_size, glw::GLuint culldistances_array_size, 1112e5c31af7Sopenharmony_ci bool dynamic_index_writes, _primitive_mode primitive_mode, 1113e5c31af7Sopenharmony_ci bool redeclare_clipdistances, bool redeclare_culldistances, 1114e5c31af7Sopenharmony_ci bool use_core_functionality, bool use_gs, bool use_ts, 1115e5c31af7Sopenharmony_ci bool fetch_culldistance_from_fs) 1116e5c31af7Sopenharmony_ci{ 1117e5c31af7Sopenharmony_ci deinitPO(); 1118e5c31af7Sopenharmony_ci 1119e5c31af7Sopenharmony_ci /* Form the vertex shader */ 1120e5c31af7Sopenharmony_ci glw::GLuint clipdistances_input_size = 1121e5c31af7Sopenharmony_ci clipdistances_array_size > 0 ? clipdistances_array_size : 1; /* Avoid zero-sized array compilation error */ 1122e5c31af7Sopenharmony_ci glw::GLuint culldistances_input_size = 1123e5c31af7Sopenharmony_ci culldistances_array_size > 0 ? culldistances_array_size : 1; /* Avoid zero-sized array compilation error */ 1124e5c31af7Sopenharmony_ci static const glw::GLchar* dynamic_array_setters = 1125e5c31af7Sopenharmony_ci "\n" 1126e5c31af7Sopenharmony_ci "#if TEMPLATE_N_GL_CLIPDISTANCE_ENTRIES\n" 1127e5c31af7Sopenharmony_ci " for (int n_clipdistance_entry = 0;\n" 1128e5c31af7Sopenharmony_ci " n_clipdistance_entry < TEMPLATE_N_GL_CLIPDISTANCE_ENTRIES;\n" 1129e5c31af7Sopenharmony_ci " ++n_clipdistance_entry)\n" 1130e5c31af7Sopenharmony_ci " {\n" 1131e5c31af7Sopenharmony_ci " ASSIGN_CLIP_DISTANCE(n_clipdistance_entry);\n" 1132e5c31af7Sopenharmony_ci " }\n" 1133e5c31af7Sopenharmony_ci "#endif" 1134e5c31af7Sopenharmony_ci "\n" 1135e5c31af7Sopenharmony_ci "#if TEMPLATE_N_GL_CULLDISTANCE_ENTRIES \n" 1136e5c31af7Sopenharmony_ci " for (int n_culldistance_entry = 0;\n" 1137e5c31af7Sopenharmony_ci " n_culldistance_entry < TEMPLATE_N_GL_CULLDISTANCE_ENTRIES;\n" 1138e5c31af7Sopenharmony_ci " ++n_culldistance_entry)\n" 1139e5c31af7Sopenharmony_ci " {\n" 1140e5c31af7Sopenharmony_ci " ASSIGN_CULL_DISTANCE(n_culldistance_entry);\n" 1141e5c31af7Sopenharmony_ci " }\n" 1142e5c31af7Sopenharmony_ci "#endif\n"; 1143e5c31af7Sopenharmony_ci 1144e5c31af7Sopenharmony_ci static const glw::GLchar* core_functionality = "#version 450\n"; 1145e5c31af7Sopenharmony_ci 1146e5c31af7Sopenharmony_ci static const glw::GLchar* extention_functionality = "#version 150\n" 1147e5c31af7Sopenharmony_ci "\n" 1148e5c31af7Sopenharmony_ci "#extension GL_ARB_cull_distance : require\n" 1149e5c31af7Sopenharmony_ci "TEMPLATE_EXTENSIONS\n" 1150e5c31af7Sopenharmony_ci "\n" 1151e5c31af7Sopenharmony_ci "#ifndef GL_ARB_cull_distance\n" 1152e5c31af7Sopenharmony_ci " #error GL_ARB_cull_distance is undefined\n" 1153e5c31af7Sopenharmony_ci "#endif\n"; 1154e5c31af7Sopenharmony_ci 1155e5c31af7Sopenharmony_ci static const glw::GLchar* fetch_function = "highp float fetch()\n" 1156e5c31af7Sopenharmony_ci "{\n" 1157e5c31af7Sopenharmony_ci " highp float sum = 0.0;\n" 1158e5c31af7Sopenharmony_ci "\n" 1159e5c31af7Sopenharmony_ci "TEMPLATE_SUM_SETTER" 1160e5c31af7Sopenharmony_ci "\n" 1161e5c31af7Sopenharmony_ci " return sum / TEMPLATE_SUM_DIVIDER;\n" 1162e5c31af7Sopenharmony_ci "}\n" 1163e5c31af7Sopenharmony_ci "\n" 1164e5c31af7Sopenharmony_ci "#define ASSIGN_RETURN_VALUE fetch()"; 1165e5c31af7Sopenharmony_ci 1166e5c31af7Sopenharmony_ci static const glw::GLchar* fs_template = "TEMPLATE_HEADER_DECLARATION\n" 1167e5c31af7Sopenharmony_ci "\n" 1168e5c31af7Sopenharmony_ci "TEMPLATE_REDECLARE_CLIPDISTANCE\n" 1169e5c31af7Sopenharmony_ci "TEMPLATE_REDECLARE_CULLDISTANCE\n" 1170e5c31af7Sopenharmony_ci "\n" 1171e5c31af7Sopenharmony_ci "TEMPLATE_ASSIGN_RETURN_VALUE\n" 1172e5c31af7Sopenharmony_ci "\n" 1173e5c31af7Sopenharmony_ci "out vec4 out_fs;\n" 1174e5c31af7Sopenharmony_ci "\n" 1175e5c31af7Sopenharmony_ci "/* Fragment shader main function */\n" 1176e5c31af7Sopenharmony_ci "void main()\n" 1177e5c31af7Sopenharmony_ci "{\n" 1178e5c31af7Sopenharmony_ci " out_fs = vec4(ASSIGN_RETURN_VALUE, 1.0, 1.0, 1.0);\n" 1179e5c31af7Sopenharmony_ci "}\n"; 1180e5c31af7Sopenharmony_ci 1181e5c31af7Sopenharmony_ci static const glw::GLchar* gs_template = "TEMPLATE_HEADER_DECLARATION\n" 1182e5c31af7Sopenharmony_ci "\n" 1183e5c31af7Sopenharmony_ci "TEMPLATE_LAYOUT_IN\n" 1184e5c31af7Sopenharmony_ci "TEMPLATE_LAYOUT_OUT\n" 1185e5c31af7Sopenharmony_ci "\n" 1186e5c31af7Sopenharmony_ci "TEMPLATE_REDECLARE_CLIPDISTANCE\n" 1187e5c31af7Sopenharmony_ci "TEMPLATE_REDECLARE_CULLDISTANCE\n" 1188e5c31af7Sopenharmony_ci "\n" 1189e5c31af7Sopenharmony_ci "#define ASSIGN_CLIP_DISTANCE(IDX) TEMPLATE_ASSIGN_CLIP_DISTANCE\n" 1190e5c31af7Sopenharmony_ci "#define ASSIGN_CULL_DISTANCE(IDX) TEMPLATE_ASSIGN_CULL_DISTANCE\n" 1191e5c31af7Sopenharmony_ci "\n" 1192e5c31af7Sopenharmony_ci "/* Geometry shader (passthrough) main function */\n" 1193e5c31af7Sopenharmony_ci "void main()\n" 1194e5c31af7Sopenharmony_ci "{\n" 1195e5c31af7Sopenharmony_ci " for (int n_vertex_index = 0;\n" 1196e5c31af7Sopenharmony_ci " n_vertex_index < gl_in.length();\n" 1197e5c31af7Sopenharmony_ci " n_vertex_index ++)\n" 1198e5c31af7Sopenharmony_ci " {\n" 1199e5c31af7Sopenharmony_ci " gl_Position = gl_in[n_vertex_index].gl_Position;\n" 1200e5c31af7Sopenharmony_ci "\n" 1201e5c31af7Sopenharmony_ci " TEMPLATE_ARRAY_SETTERS\n" 1202e5c31af7Sopenharmony_ci "\n" 1203e5c31af7Sopenharmony_ci " EmitVertex();\n" 1204e5c31af7Sopenharmony_ci " }\n" 1205e5c31af7Sopenharmony_ci "\n" 1206e5c31af7Sopenharmony_ci " EndPrimitive();\n" 1207e5c31af7Sopenharmony_ci "}\n"; 1208e5c31af7Sopenharmony_ci 1209e5c31af7Sopenharmony_ci static const glw::GLchar* tc_template = 1210e5c31af7Sopenharmony_ci "TEMPLATE_HEADER_DECLARATION\n" 1211e5c31af7Sopenharmony_ci "\n" 1212e5c31af7Sopenharmony_ci "TEMPLATE_LAYOUT_OUT\n" 1213e5c31af7Sopenharmony_ci "\n" 1214e5c31af7Sopenharmony_ci "out gl_PerVertex {\n" 1215e5c31af7Sopenharmony_ci "TEMPLATE_REDECLARE_CLIPDISTANCE\n" 1216e5c31af7Sopenharmony_ci "TEMPLATE_REDECLARE_CULLDISTANCE\n" 1217e5c31af7Sopenharmony_ci "vec4 gl_Position;\n" 1218e5c31af7Sopenharmony_ci "} gl_out[];\n" 1219e5c31af7Sopenharmony_ci "\n" 1220e5c31af7Sopenharmony_ci "#define ASSIGN_CLIP_DISTANCE(IDX) TEMPLATE_ASSIGN_CLIP_DISTANCE\n" 1221e5c31af7Sopenharmony_ci "#define ASSIGN_CULL_DISTANCE(IDX) TEMPLATE_ASSIGN_CULL_DISTANCE\n" 1222e5c31af7Sopenharmony_ci "\n" 1223e5c31af7Sopenharmony_ci "/* Tesselation control shader main function */\n" 1224e5c31af7Sopenharmony_ci "void main()\n" 1225e5c31af7Sopenharmony_ci "{\n" 1226e5c31af7Sopenharmony_ci " gl_TessLevelInner[0] = 1.0;\n" 1227e5c31af7Sopenharmony_ci " gl_TessLevelInner[1] = 1.0;\n" 1228e5c31af7Sopenharmony_ci " gl_TessLevelOuter[0] = 1.0;\n" 1229e5c31af7Sopenharmony_ci " gl_TessLevelOuter[1] = 1.0;\n" 1230e5c31af7Sopenharmony_ci " gl_TessLevelOuter[2] = 1.0;\n" 1231e5c31af7Sopenharmony_ci " gl_TessLevelOuter[3] = 1.0;\n" 1232e5c31af7Sopenharmony_ci " /* Clipdistance and culldistance array setters */\n" 1233e5c31af7Sopenharmony_ci " {\n" 1234e5c31af7Sopenharmony_ci " TEMPLATE_ARRAY_SETTERS\n" 1235e5c31af7Sopenharmony_ci " }\n" 1236e5c31af7Sopenharmony_ci " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 1237e5c31af7Sopenharmony_ci "}\n"; 1238e5c31af7Sopenharmony_ci 1239e5c31af7Sopenharmony_ci static const glw::GLchar* te_template = "TEMPLATE_HEADER_DECLARATION\n" 1240e5c31af7Sopenharmony_ci "\n" 1241e5c31af7Sopenharmony_ci "TEMPLATE_LAYOUT_IN\n" 1242e5c31af7Sopenharmony_ci "\n" 1243e5c31af7Sopenharmony_ci "in gl_PerVertex {\n" 1244e5c31af7Sopenharmony_ci "TEMPLATE_REDECLARE_IN_CLIPDISTANCE\n" 1245e5c31af7Sopenharmony_ci "TEMPLATE_REDECLARE_IN_CULLDISTANCE\n" 1246e5c31af7Sopenharmony_ci "vec4 gl_Position;\n" 1247e5c31af7Sopenharmony_ci "} gl_in[];\n" 1248e5c31af7Sopenharmony_ci "\n" 1249e5c31af7Sopenharmony_ci "TEMPLATE_REDECLARE_CLIPDISTANCE\n" 1250e5c31af7Sopenharmony_ci "TEMPLATE_REDECLARE_CULLDISTANCE\n" 1251e5c31af7Sopenharmony_ci "\n" 1252e5c31af7Sopenharmony_ci "#define ASSIGN_CLIP_DISTANCE(IDX) TEMPLATE_ASSIGN_CLIP_DISTANCE\n" 1253e5c31af7Sopenharmony_ci "#define ASSIGN_CULL_DISTANCE(IDX) TEMPLATE_ASSIGN_CULL_DISTANCE\n" 1254e5c31af7Sopenharmony_ci "\n" 1255e5c31af7Sopenharmony_ci "/* Tesselation evaluation shader main function */\n" 1256e5c31af7Sopenharmony_ci "void main()\n" 1257e5c31af7Sopenharmony_ci "{\n" 1258e5c31af7Sopenharmony_ci " /* Clipdistance and culldistance array setters */\n" 1259e5c31af7Sopenharmony_ci " {\n" 1260e5c31af7Sopenharmony_ci " TEMPLATE_ARRAY_SETTERS\n" 1261e5c31af7Sopenharmony_ci " }\n" 1262e5c31af7Sopenharmony_ci " gl_Position = TEMPLATE_OUT_FORMULA;\n" 1263e5c31af7Sopenharmony_ci "}\n"; 1264e5c31af7Sopenharmony_ci 1265e5c31af7Sopenharmony_ci static const glw::GLchar* vs_template = 1266e5c31af7Sopenharmony_ci "TEMPLATE_HEADER_DECLARATION\n" 1267e5c31af7Sopenharmony_ci "\n" 1268e5c31af7Sopenharmony_ci "in float clipdistance_data[TEMPLATE_CLIPDISTANCE_INPUT_SIZE];\n" 1269e5c31af7Sopenharmony_ci "in float culldistance_data[TEMPLATE_CULLDISTANCE_INPUT_SIZE];\n" 1270e5c31af7Sopenharmony_ci "in vec2 position;\n" 1271e5c31af7Sopenharmony_ci "\n" 1272e5c31af7Sopenharmony_ci "TEMPLATE_REDECLARE_CLIPDISTANCE\n" 1273e5c31af7Sopenharmony_ci "TEMPLATE_REDECLARE_CULLDISTANCE\n" 1274e5c31af7Sopenharmony_ci "\n" 1275e5c31af7Sopenharmony_ci "#define ASSIGN_CLIP_DISTANCE(IDX) TEMPLATE_ASSIGN_CLIP_DISTANCE\n" 1276e5c31af7Sopenharmony_ci "#define ASSIGN_CULL_DISTANCE(IDX) TEMPLATE_ASSIGN_CULL_DISTANCE\n" 1277e5c31af7Sopenharmony_ci "\n" 1278e5c31af7Sopenharmony_ci "/* Vertex shader main function */\n" 1279e5c31af7Sopenharmony_ci "void main()\n" 1280e5c31af7Sopenharmony_ci "{\n" 1281e5c31af7Sopenharmony_ci " /* Clipdistance and culldistance array setters */\n" 1282e5c31af7Sopenharmony_ci " {\n" 1283e5c31af7Sopenharmony_ci " TEMPLATE_ARRAY_SETTERS\n" 1284e5c31af7Sopenharmony_ci " }\n" 1285e5c31af7Sopenharmony_ci " gl_Position = vec4(2.0 * position.x - 1.0, 2.0 * position.y - 1.0, 0.0, 1.0);\n" 1286e5c31af7Sopenharmony_ci "}\n"; 1287e5c31af7Sopenharmony_ci 1288e5c31af7Sopenharmony_ci std::string* shader_body_string_fs = DE_NULL; 1289e5c31af7Sopenharmony_ci std::string* shader_body_string_gs = DE_NULL; 1290e5c31af7Sopenharmony_ci std::string* shader_body_string_tc = DE_NULL; 1291e5c31af7Sopenharmony_ci std::string* shader_body_string_te = DE_NULL; 1292e5c31af7Sopenharmony_ci std::string* shader_body_string_vs = DE_NULL; 1293e5c31af7Sopenharmony_ci std::string shader_header_declaration = use_core_functionality ? core_functionality : extention_functionality; 1294e5c31af7Sopenharmony_ci 1295e5c31af7Sopenharmony_ci struct _shaders_configuration 1296e5c31af7Sopenharmony_ci { 1297e5c31af7Sopenharmony_ci glw::GLenum type; 1298e5c31af7Sopenharmony_ci const glw::GLchar* shader_template; 1299e5c31af7Sopenharmony_ci std::string body; 1300e5c31af7Sopenharmony_ci const bool use; 1301e5c31af7Sopenharmony_ci } shaders_configuration[] = { { 1302e5c31af7Sopenharmony_ci GL_FRAGMENT_SHADER, fs_template, std::string(), true, 1303e5c31af7Sopenharmony_ci }, 1304e5c31af7Sopenharmony_ci { 1305e5c31af7Sopenharmony_ci GL_GEOMETRY_SHADER, gs_template, std::string(), use_gs, 1306e5c31af7Sopenharmony_ci }, 1307e5c31af7Sopenharmony_ci { 1308e5c31af7Sopenharmony_ci GL_TESS_CONTROL_SHADER, tc_template, std::string(), use_ts, 1309e5c31af7Sopenharmony_ci }, 1310e5c31af7Sopenharmony_ci { 1311e5c31af7Sopenharmony_ci GL_TESS_EVALUATION_SHADER, te_template, std::string(), use_ts, 1312e5c31af7Sopenharmony_ci }, 1313e5c31af7Sopenharmony_ci { 1314e5c31af7Sopenharmony_ci GL_VERTEX_SHADER, vs_template, std::string(), true, 1315e5c31af7Sopenharmony_ci } }; 1316e5c31af7Sopenharmony_ci 1317e5c31af7Sopenharmony_ci const glw::GLuint n_shaders_configuration = sizeof(shaders_configuration) / sizeof(shaders_configuration[0]); 1318e5c31af7Sopenharmony_ci 1319e5c31af7Sopenharmony_ci /* Construct shader bodies out of templates */ 1320e5c31af7Sopenharmony_ci for (glw::GLuint n_shader_index = 0; n_shader_index < n_shaders_configuration; n_shader_index++) 1321e5c31af7Sopenharmony_ci { 1322e5c31af7Sopenharmony_ci if (shaders_configuration[n_shader_index].use) 1323e5c31af7Sopenharmony_ci { 1324e5c31af7Sopenharmony_ci std::string array_setters; 1325e5c31af7Sopenharmony_ci std::string clipdistance_array_declaration; 1326e5c31af7Sopenharmony_ci std::string culldistance_array_declaration; 1327e5c31af7Sopenharmony_ci std::string clipdistance_in_array_declaration; 1328e5c31af7Sopenharmony_ci std::string culldistance_in_array_declaration; 1329e5c31af7Sopenharmony_ci std::string& shader_source = shaders_configuration[n_shader_index].body; 1330e5c31af7Sopenharmony_ci 1331e5c31af7Sopenharmony_ci /* Copy template into shader body source */ 1332e5c31af7Sopenharmony_ci shader_source = shaders_configuration[n_shader_index].shader_template; 1333e5c31af7Sopenharmony_ci 1334e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_HEADER_DECLARATION"), 1335e5c31af7Sopenharmony_ci shader_header_declaration); 1336e5c31af7Sopenharmony_ci 1337e5c31af7Sopenharmony_ci /* Shader-specific actions */ 1338e5c31af7Sopenharmony_ci switch (shaders_configuration[n_shader_index].type) 1339e5c31af7Sopenharmony_ci { 1340e5c31af7Sopenharmony_ci case GL_FRAGMENT_SHADER: 1341e5c31af7Sopenharmony_ci { 1342e5c31af7Sopenharmony_ci shader_body_string_fs = &shaders_configuration[n_shader_index].body; 1343e5c31af7Sopenharmony_ci 1344e5c31af7Sopenharmony_ci if (fetch_culldistance_from_fs) 1345e5c31af7Sopenharmony_ci { 1346e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_ASSIGN_RETURN_VALUE"), 1347e5c31af7Sopenharmony_ci std::string(fetch_function)); 1348e5c31af7Sopenharmony_ci 1349e5c31af7Sopenharmony_ci std::string fetch_sum_setters = ""; 1350e5c31af7Sopenharmony_ci for (glw::GLuint i = 0; i < clipdistances_array_size; ++i) 1351e5c31af7Sopenharmony_ci { 1352e5c31af7Sopenharmony_ci fetch_sum_setters.append(" sum += abs(gl_ClipDistance["); 1353e5c31af7Sopenharmony_ci fetch_sum_setters.append(CullDistance::Utilities::intToString(i)); 1354e5c31af7Sopenharmony_ci fetch_sum_setters.append("]) * "); 1355e5c31af7Sopenharmony_ci fetch_sum_setters.append(CullDistance::Utilities::intToString(i + 1)); 1356e5c31af7Sopenharmony_ci fetch_sum_setters.append(".0;\n"); 1357e5c31af7Sopenharmony_ci } 1358e5c31af7Sopenharmony_ci 1359e5c31af7Sopenharmony_ci fetch_sum_setters.append("\n"); 1360e5c31af7Sopenharmony_ci 1361e5c31af7Sopenharmony_ci for (glw::GLuint i = 0; i < culldistances_array_size; ++i) 1362e5c31af7Sopenharmony_ci { 1363e5c31af7Sopenharmony_ci fetch_sum_setters.append(" sum += abs(gl_CullDistance["); 1364e5c31af7Sopenharmony_ci fetch_sum_setters.append(CullDistance::Utilities::intToString(i)); 1365e5c31af7Sopenharmony_ci fetch_sum_setters.append("]) * "); 1366e5c31af7Sopenharmony_ci fetch_sum_setters.append( 1367e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(i + 1 + clipdistances_array_size)); 1368e5c31af7Sopenharmony_ci fetch_sum_setters.append(".0;\n"); 1369e5c31af7Sopenharmony_ci } 1370e5c31af7Sopenharmony_ci 1371e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_SUM_SETTER"), 1372e5c31af7Sopenharmony_ci std::string(fetch_sum_setters)); 1373e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1374e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_SUM_DIVIDER"), 1375e5c31af7Sopenharmony_ci std::string(CullDistance::Utilities::intToString( 1376e5c31af7Sopenharmony_ci (clipdistances_array_size + culldistances_array_size) * 1377e5c31af7Sopenharmony_ci ((clipdistances_array_size + culldistances_array_size + 1)))) 1378e5c31af7Sopenharmony_ci .append(".0")); 1379e5c31af7Sopenharmony_ci } 1380e5c31af7Sopenharmony_ci else 1381e5c31af7Sopenharmony_ci { 1382e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_ASSIGN_RETURN_VALUE"), 1383e5c31af7Sopenharmony_ci std::string("#define ASSIGN_RETURN_VALUE 1.0")); 1384e5c31af7Sopenharmony_ci } 1385e5c31af7Sopenharmony_ci 1386e5c31af7Sopenharmony_ci break; 1387e5c31af7Sopenharmony_ci } 1388e5c31af7Sopenharmony_ci 1389e5c31af7Sopenharmony_ci case GL_GEOMETRY_SHADER: 1390e5c31af7Sopenharmony_ci { 1391e5c31af7Sopenharmony_ci shader_body_string_gs = &shaders_configuration[n_shader_index].body; 1392e5c31af7Sopenharmony_ci 1393e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1394e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_ASSIGN_CLIP_DISTANCE"), 1395e5c31af7Sopenharmony_ci std::string("gl_ClipDistance[IDX] = gl_in[n_vertex_index].gl_ClipDistance[IDX]")); 1396e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1397e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_ASSIGN_CULL_DISTANCE"), 1398e5c31af7Sopenharmony_ci std::string("gl_CullDistance[IDX] = gl_in[n_vertex_index].gl_CullDistance[IDX]")); 1399e5c31af7Sopenharmony_ci 1400e5c31af7Sopenharmony_ci switch (primitive_mode) 1401e5c31af7Sopenharmony_ci { 1402e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_LINES: 1403e5c31af7Sopenharmony_ci { 1404e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_LAYOUT_IN"), 1405e5c31af7Sopenharmony_ci std::string("layout(lines) in;")); 1406e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_LAYOUT_OUT"), 1407e5c31af7Sopenharmony_ci std::string("layout(line_strip, max_vertices = 2) out;")); 1408e5c31af7Sopenharmony_ci 1409e5c31af7Sopenharmony_ci break; 1410e5c31af7Sopenharmony_ci } 1411e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_POINTS: 1412e5c31af7Sopenharmony_ci { 1413e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_LAYOUT_IN"), 1414e5c31af7Sopenharmony_ci std::string("layout(points) in;")); 1415e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_LAYOUT_OUT"), 1416e5c31af7Sopenharmony_ci std::string("layout(points, max_vertices = 1) out;")); 1417e5c31af7Sopenharmony_ci 1418e5c31af7Sopenharmony_ci break; 1419e5c31af7Sopenharmony_ci } 1420e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_TRIANGLES: 1421e5c31af7Sopenharmony_ci { 1422e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_LAYOUT_IN"), 1423e5c31af7Sopenharmony_ci std::string("layout(triangles) in;")); 1424e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_LAYOUT_OUT"), 1425e5c31af7Sopenharmony_ci std::string("layout(triangle_strip, max_vertices = 3) out;")); 1426e5c31af7Sopenharmony_ci 1427e5c31af7Sopenharmony_ci break; 1428e5c31af7Sopenharmony_ci } 1429e5c31af7Sopenharmony_ci default: 1430e5c31af7Sopenharmony_ci TCU_FAIL("Unknown primitive mode"); 1431e5c31af7Sopenharmony_ci } 1432e5c31af7Sopenharmony_ci 1433e5c31af7Sopenharmony_ci break; 1434e5c31af7Sopenharmony_ci } 1435e5c31af7Sopenharmony_ci 1436e5c31af7Sopenharmony_ci case GL_TESS_CONTROL_SHADER: 1437e5c31af7Sopenharmony_ci { 1438e5c31af7Sopenharmony_ci shader_body_string_tc = &shaders_configuration[n_shader_index].body; 1439e5c31af7Sopenharmony_ci 1440e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1441e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_ASSIGN_CLIP_DISTANCE"), 1442e5c31af7Sopenharmony_ci std::string( 1443e5c31af7Sopenharmony_ci "gl_out[gl_InvocationID].gl_ClipDistance[IDX] = gl_in[gl_InvocationID].gl_ClipDistance[IDX]")); 1444e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1445e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_ASSIGN_CULL_DISTANCE"), 1446e5c31af7Sopenharmony_ci std::string( 1447e5c31af7Sopenharmony_ci "gl_out[gl_InvocationID].gl_CullDistance[IDX] = gl_in[gl_InvocationID].gl_CullDistance[IDX]")); 1448e5c31af7Sopenharmony_ci 1449e5c31af7Sopenharmony_ci switch (primitive_mode) 1450e5c31af7Sopenharmony_ci { 1451e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_LINES: 1452e5c31af7Sopenharmony_ci { 1453e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_LAYOUT_OUT"), 1454e5c31af7Sopenharmony_ci std::string("layout(vertices = 2) out;")); 1455e5c31af7Sopenharmony_ci 1456e5c31af7Sopenharmony_ci break; 1457e5c31af7Sopenharmony_ci } 1458e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_POINTS: 1459e5c31af7Sopenharmony_ci { 1460e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_LAYOUT_OUT"), 1461e5c31af7Sopenharmony_ci std::string("layout(vertices = 1) out;")); 1462e5c31af7Sopenharmony_ci 1463e5c31af7Sopenharmony_ci break; 1464e5c31af7Sopenharmony_ci } 1465e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_TRIANGLES: 1466e5c31af7Sopenharmony_ci { 1467e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_LAYOUT_OUT"), 1468e5c31af7Sopenharmony_ci std::string("layout(vertices = 3) out;")); 1469e5c31af7Sopenharmony_ci 1470e5c31af7Sopenharmony_ci break; 1471e5c31af7Sopenharmony_ci } 1472e5c31af7Sopenharmony_ci default: 1473e5c31af7Sopenharmony_ci TCU_FAIL("Unknown primitive mode"); 1474e5c31af7Sopenharmony_ci } 1475e5c31af7Sopenharmony_ci 1476e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1477e5c31af7Sopenharmony_ci shader_source, 1478e5c31af7Sopenharmony_ci std::string("TEMPLATE_EXTENSIONS"), 1479e5c31af7Sopenharmony_ci std::string("#extension GL_ARB_tessellation_shader: require")); 1480e5c31af7Sopenharmony_ci break; 1481e5c31af7Sopenharmony_ci } 1482e5c31af7Sopenharmony_ci 1483e5c31af7Sopenharmony_ci case GL_TESS_EVALUATION_SHADER: 1484e5c31af7Sopenharmony_ci { 1485e5c31af7Sopenharmony_ci shader_body_string_te = &shaders_configuration[n_shader_index].body; 1486e5c31af7Sopenharmony_ci 1487e5c31af7Sopenharmony_ci switch (primitive_mode) 1488e5c31af7Sopenharmony_ci { 1489e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_LINES: 1490e5c31af7Sopenharmony_ci { 1491e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_LAYOUT_IN"), 1492e5c31af7Sopenharmony_ci std::string("layout(isolines) in;")); 1493e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1494e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_OUT_FORMULA"), 1495e5c31af7Sopenharmony_ci std::string("mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x)")); 1496e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1497e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_ASSIGN_CLIP_DISTANCE"), 1498e5c31af7Sopenharmony_ci std::string("gl_ClipDistance[IDX] = mix(gl_in[0].gl_ClipDistance[IDX], " 1499e5c31af7Sopenharmony_ci "gl_in[1].gl_ClipDistance[IDX], gl_TessCoord.x)")); 1500e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1501e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_ASSIGN_CULL_DISTANCE"), 1502e5c31af7Sopenharmony_ci std::string("gl_CullDistance[IDX] = mix(gl_in[0].gl_CullDistance[IDX], " 1503e5c31af7Sopenharmony_ci "gl_in[1].gl_CullDistance[IDX], gl_TessCoord.x)")); 1504e5c31af7Sopenharmony_ci 1505e5c31af7Sopenharmony_ci break; 1506e5c31af7Sopenharmony_ci } 1507e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_POINTS: 1508e5c31af7Sopenharmony_ci { 1509e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_LAYOUT_IN"), 1510e5c31af7Sopenharmony_ci std::string("layout(isolines, point_mode) in;")); 1511e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_OUT_FORMULA"), 1512e5c31af7Sopenharmony_ci std::string("gl_in[0].gl_Position")); 1513e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1514e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_ASSIGN_CLIP_DISTANCE"), 1515e5c31af7Sopenharmony_ci std::string("gl_ClipDistance[IDX] = gl_in[0].gl_ClipDistance[IDX]")); 1516e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1517e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_ASSIGN_CULL_DISTANCE"), 1518e5c31af7Sopenharmony_ci std::string("gl_CullDistance[IDX] = gl_in[0].gl_CullDistance[IDX]")); 1519e5c31af7Sopenharmony_ci 1520e5c31af7Sopenharmony_ci break; 1521e5c31af7Sopenharmony_ci } 1522e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_TRIANGLES: 1523e5c31af7Sopenharmony_ci { 1524e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_LAYOUT_IN"), 1525e5c31af7Sopenharmony_ci std::string("layout(triangles) in;")); 1526e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1527e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_OUT_FORMULA"), 1528e5c31af7Sopenharmony_ci std::string("vec4(mat3(gl_in[0].gl_Position.xyz, gl_in[1].gl_Position.xyz, " 1529e5c31af7Sopenharmony_ci "gl_in[2].gl_Position.xyz) * gl_TessCoord, 1.0)")); 1530e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1531e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_ASSIGN_CLIP_DISTANCE"), 1532e5c31af7Sopenharmony_ci std::string("gl_ClipDistance[IDX] = dot(vec3(gl_in[0].gl_ClipDistance[IDX], " 1533e5c31af7Sopenharmony_ci "gl_in[1].gl_ClipDistance[IDX], gl_in[2].gl_ClipDistance[IDX]), gl_TessCoord)")); 1534e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1535e5c31af7Sopenharmony_ci shader_source, std::string("TEMPLATE_ASSIGN_CULL_DISTANCE"), 1536e5c31af7Sopenharmony_ci std::string("gl_CullDistance[IDX] = dot(vec3(gl_in[0].gl_CullDistance[IDX], " 1537e5c31af7Sopenharmony_ci "gl_in[1].gl_CullDistance[IDX], gl_in[2].gl_CullDistance[IDX]), gl_TessCoord)")); 1538e5c31af7Sopenharmony_ci 1539e5c31af7Sopenharmony_ci break; 1540e5c31af7Sopenharmony_ci } 1541e5c31af7Sopenharmony_ci default: 1542e5c31af7Sopenharmony_ci TCU_FAIL("Unknown primitive mode"); 1543e5c31af7Sopenharmony_ci } 1544e5c31af7Sopenharmony_ci 1545e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1546e5c31af7Sopenharmony_ci shader_source, 1547e5c31af7Sopenharmony_ci std::string("TEMPLATE_EXTENSIONS"), 1548e5c31af7Sopenharmony_ci std::string("#extension GL_ARB_tessellation_shader: require")); 1549e5c31af7Sopenharmony_ci break; 1550e5c31af7Sopenharmony_ci } 1551e5c31af7Sopenharmony_ci 1552e5c31af7Sopenharmony_ci case GL_VERTEX_SHADER: 1553e5c31af7Sopenharmony_ci { 1554e5c31af7Sopenharmony_ci shader_body_string_vs = &shaders_configuration[n_shader_index].body; 1555e5c31af7Sopenharmony_ci 1556e5c31af7Sopenharmony_ci /* Specify input data size for clipdistances data */ 1557e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_CLIPDISTANCE_INPUT_SIZE"), 1558e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(clipdistances_input_size)); 1559e5c31af7Sopenharmony_ci 1560e5c31af7Sopenharmony_ci /* Specify input data size for culldistances data */ 1561e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_CULLDISTANCE_INPUT_SIZE"), 1562e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(culldistances_input_size)); 1563e5c31af7Sopenharmony_ci 1564e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_ASSIGN_CLIP_DISTANCE"), 1565e5c31af7Sopenharmony_ci std::string("gl_ClipDistance[IDX] = clipdistance_data[IDX]")); 1566e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_ASSIGN_CULL_DISTANCE"), 1567e5c31af7Sopenharmony_ci std::string("gl_CullDistance[IDX] = culldistance_data[IDX]")); 1568e5c31af7Sopenharmony_ci 1569e5c31af7Sopenharmony_ci break; 1570e5c31af7Sopenharmony_ci } 1571e5c31af7Sopenharmony_ci 1572e5c31af7Sopenharmony_ci default: 1573e5c31af7Sopenharmony_ci TCU_FAIL("Unknown shader type"); 1574e5c31af7Sopenharmony_ci } 1575e5c31af7Sopenharmony_ci 1576e5c31af7Sopenharmony_ci /* Clear out in case no specific exts were needed */ 1577e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll( 1578e5c31af7Sopenharmony_ci shader_source, 1579e5c31af7Sopenharmony_ci std::string("TEMPLATE_EXTENSIONS"), 1580e5c31af7Sopenharmony_ci std::string("")); 1581e5c31af7Sopenharmony_ci 1582e5c31af7Sopenharmony_ci /* Adjust clipdistances declaration */ 1583e5c31af7Sopenharmony_ci if (redeclare_clipdistances && clipdistances_array_size > 0) 1584e5c31af7Sopenharmony_ci { 1585e5c31af7Sopenharmony_ci if (shaders_configuration[n_shader_index].type == GL_FRAGMENT_SHADER) 1586e5c31af7Sopenharmony_ci { 1587e5c31af7Sopenharmony_ci if (fetch_culldistance_from_fs) 1588e5c31af7Sopenharmony_ci { 1589e5c31af7Sopenharmony_ci clipdistance_array_declaration = 1590e5c31af7Sopenharmony_ci std::string("in float gl_ClipDistance[") + 1591e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(clipdistances_array_size) + std::string("];"); 1592e5c31af7Sopenharmony_ci } 1593e5c31af7Sopenharmony_ci } 1594e5c31af7Sopenharmony_ci else if (shaders_configuration[n_shader_index].type == GL_TESS_CONTROL_SHADER) 1595e5c31af7Sopenharmony_ci { 1596e5c31af7Sopenharmony_ci clipdistance_array_declaration = std::string("float gl_ClipDistance[") + 1597e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(clipdistances_array_size) + 1598e5c31af7Sopenharmony_ci std::string("];"); 1599e5c31af7Sopenharmony_ci } 1600e5c31af7Sopenharmony_ci else 1601e5c31af7Sopenharmony_ci { 1602e5c31af7Sopenharmony_ci clipdistance_array_declaration = std::string("out float gl_ClipDistance[") + 1603e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(clipdistances_array_size) + 1604e5c31af7Sopenharmony_ci std::string("];"); 1605e5c31af7Sopenharmony_ci clipdistance_in_array_declaration = std::string("in float gl_ClipDistance[") + 1606e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(clipdistances_array_size) + 1607e5c31af7Sopenharmony_ci std::string("];"); 1608e5c31af7Sopenharmony_ci } 1609e5c31af7Sopenharmony_ci } 1610e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_REDECLARE_CLIPDISTANCE"), 1611e5c31af7Sopenharmony_ci clipdistance_array_declaration); 1612e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_REDECLARE_IN_CLIPDISTANCE"), 1613e5c31af7Sopenharmony_ci clipdistance_in_array_declaration); 1614e5c31af7Sopenharmony_ci 1615e5c31af7Sopenharmony_ci /* Adjust culldistances declaration */ 1616e5c31af7Sopenharmony_ci if (redeclare_culldistances && culldistances_array_size > 0) 1617e5c31af7Sopenharmony_ci { 1618e5c31af7Sopenharmony_ci if (shaders_configuration[n_shader_index].type == GL_FRAGMENT_SHADER) 1619e5c31af7Sopenharmony_ci { 1620e5c31af7Sopenharmony_ci if (fetch_culldistance_from_fs) 1621e5c31af7Sopenharmony_ci { 1622e5c31af7Sopenharmony_ci culldistance_array_declaration = 1623e5c31af7Sopenharmony_ci std::string("in float gl_CullDistance[") + 1624e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(culldistances_array_size) + std::string("];"); 1625e5c31af7Sopenharmony_ci } 1626e5c31af7Sopenharmony_ci } 1627e5c31af7Sopenharmony_ci else if (shaders_configuration[n_shader_index].type == GL_TESS_CONTROL_SHADER) 1628e5c31af7Sopenharmony_ci { 1629e5c31af7Sopenharmony_ci culldistance_array_declaration = std::string("float gl_CullDistance[") + 1630e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(culldistances_array_size) + 1631e5c31af7Sopenharmony_ci std::string("];"); 1632e5c31af7Sopenharmony_ci } 1633e5c31af7Sopenharmony_ci else 1634e5c31af7Sopenharmony_ci { 1635e5c31af7Sopenharmony_ci culldistance_array_declaration = std::string("out float gl_CullDistance[") + 1636e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(culldistances_array_size) + 1637e5c31af7Sopenharmony_ci std::string("];"); 1638e5c31af7Sopenharmony_ci culldistance_in_array_declaration = std::string("in float gl_CullDistance[") + 1639e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(culldistances_array_size) + 1640e5c31af7Sopenharmony_ci std::string("];"); 1641e5c31af7Sopenharmony_ci } 1642e5c31af7Sopenharmony_ci } 1643e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_REDECLARE_CULLDISTANCE"), 1644e5c31af7Sopenharmony_ci culldistance_array_declaration); 1645e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_REDECLARE_IN_CULLDISTANCE"), 1646e5c31af7Sopenharmony_ci culldistance_in_array_declaration); 1647e5c31af7Sopenharmony_ci 1648e5c31af7Sopenharmony_ci /* Adjust clip/cull distances setters */ 1649e5c31af7Sopenharmony_ci if (dynamic_index_writes) 1650e5c31af7Sopenharmony_ci { 1651e5c31af7Sopenharmony_ci array_setters = dynamic_array_setters; 1652e5c31af7Sopenharmony_ci 1653e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(array_setters, std::string("TEMPLATE_N_GL_CLIPDISTANCE_ENTRIES"), 1654e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(clipdistances_array_size)); 1655e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(array_setters, std::string("TEMPLATE_N_GL_CULLDISTANCE_ENTRIES"), 1656e5c31af7Sopenharmony_ci CullDistance::Utilities::intToString(culldistances_array_size)); 1657e5c31af7Sopenharmony_ci } 1658e5c31af7Sopenharmony_ci else 1659e5c31af7Sopenharmony_ci { 1660e5c31af7Sopenharmony_ci std::stringstream static_array_setters_sstream; 1661e5c31af7Sopenharmony_ci 1662e5c31af7Sopenharmony_ci static_array_setters_sstream << "\n"; 1663e5c31af7Sopenharmony_ci 1664e5c31af7Sopenharmony_ci for (glw::GLuint clipdistances_array_entry = 0; clipdistances_array_entry < clipdistances_array_size; 1665e5c31af7Sopenharmony_ci ++clipdistances_array_entry) 1666e5c31af7Sopenharmony_ci { 1667e5c31af7Sopenharmony_ci static_array_setters_sstream << " ASSIGN_CLIP_DISTANCE(" << clipdistances_array_entry 1668e5c31af7Sopenharmony_ci << ");\n"; 1669e5c31af7Sopenharmony_ci } 1670e5c31af7Sopenharmony_ci 1671e5c31af7Sopenharmony_ci static_array_setters_sstream << "\n"; 1672e5c31af7Sopenharmony_ci 1673e5c31af7Sopenharmony_ci for (glw::GLuint culldistances_array_entry = 0; culldistances_array_entry < culldistances_array_size; 1674e5c31af7Sopenharmony_ci ++culldistances_array_entry) 1675e5c31af7Sopenharmony_ci { 1676e5c31af7Sopenharmony_ci static_array_setters_sstream << " ASSIGN_CULL_DISTANCE(" << culldistances_array_entry 1677e5c31af7Sopenharmony_ci << ");\n"; 1678e5c31af7Sopenharmony_ci } 1679e5c31af7Sopenharmony_ci 1680e5c31af7Sopenharmony_ci array_setters = static_array_setters_sstream.str(); 1681e5c31af7Sopenharmony_ci } 1682e5c31af7Sopenharmony_ci 1683e5c31af7Sopenharmony_ci CullDistance::Utilities::replaceAll(shader_source, std::string("TEMPLATE_ARRAY_SETTERS"), array_setters); 1684e5c31af7Sopenharmony_ci } 1685e5c31af7Sopenharmony_ci } 1686e5c31af7Sopenharmony_ci 1687e5c31af7Sopenharmony_ci /* Build the geometry shader */ 1688e5c31af7Sopenharmony_ci CullDistance::Utilities::buildProgram( 1689e5c31af7Sopenharmony_ci m_context.getRenderContext().getFunctions(), m_testCtx, DE_NULL, /* Compute shader */ 1690e5c31af7Sopenharmony_ci shader_body_string_fs != DE_NULL ? shader_body_string_fs->c_str() : 1691e5c31af7Sopenharmony_ci DE_NULL, /* Fragment shader */ 1692e5c31af7Sopenharmony_ci shader_body_string_gs != DE_NULL ? shader_body_string_gs->c_str() : 1693e5c31af7Sopenharmony_ci DE_NULL, /* Geometry shader */ 1694e5c31af7Sopenharmony_ci shader_body_string_tc != DE_NULL ? shader_body_string_tc->c_str() : 1695e5c31af7Sopenharmony_ci DE_NULL, /* Tesselation control shader */ 1696e5c31af7Sopenharmony_ci shader_body_string_te != DE_NULL ? shader_body_string_te->c_str() : 1697e5c31af7Sopenharmony_ci DE_NULL, /* Tesselation evaluation shader */ 1698e5c31af7Sopenharmony_ci shader_body_string_vs != DE_NULL ? shader_body_string_vs->c_str() : 1699e5c31af7Sopenharmony_ci DE_NULL, /* Vertex shader */ 1700e5c31af7Sopenharmony_ci 0, /* Transform feedback varyings count */ 1701e5c31af7Sopenharmony_ci DE_NULL, /* Transform feedback varyings */ 1702e5c31af7Sopenharmony_ci &m_po_id /* Program object id */ 1703e5c31af7Sopenharmony_ci ); 1704e5c31af7Sopenharmony_ci} 1705e5c31af7Sopenharmony_ci 1706e5c31af7Sopenharmony_ci/** Generates primitive data required to test a case with specified 1707e5c31af7Sopenharmony_ci * gl_ClipDistance and glCullDistance array sizes for specified 1708e5c31af7Sopenharmony_ci * primitive mode. Generated primitive data is stored in m_bo_data 1709e5c31af7Sopenharmony_ci * as well uploaded into buffer specified in m_bo_id buffer. 1710e5c31af7Sopenharmony_ci * Also the procedure binds vertex attribute locations to 1711e5c31af7Sopenharmony_ci * program object m_po_id. 1712e5c31af7Sopenharmony_ci * 1713e5c31af7Sopenharmony_ci * @param clipdistances_array_size gl_ClipDistance array size. Can be 0. 1714e5c31af7Sopenharmony_ci * @param culldistances_array_size gl_CullDistance array size. Can be 0. 1715e5c31af7Sopenharmony_ci * @param _primitive_mode Primitives to be generated. Can be: 1716e5c31af7Sopenharmony_ci * PRIMITIVE_MODE_POINTS, 1717e5c31af7Sopenharmony_ci * PRIMITIVE_MODE_LINES, 1718e5c31af7Sopenharmony_ci * PRIMITIVE_MODE_TRIANGLES. 1719e5c31af7Sopenharmony_ci */ 1720e5c31af7Sopenharmony_civoid CullDistance::FunctionalTest::configureVAO(glw::GLuint clipdistances_array_size, 1721e5c31af7Sopenharmony_ci glw::GLuint culldistances_array_size, _primitive_mode primitive_mode) 1722e5c31af7Sopenharmony_ci{ 1723e5c31af7Sopenharmony_ci /* Detailed test description. 1724e5c31af7Sopenharmony_ci * 1725e5c31af7Sopenharmony_ci * configureVAO() generates primitives layouted in grid. Primitve 1726e5c31af7Sopenharmony_ci * consists of up to 3 vertices and each vertex is accompanied by: 1727e5c31af7Sopenharmony_ci * - array of clipdistances (clipdistances_array_size floats); 1728e5c31af7Sopenharmony_ci * - array of culldistances (culldistances_array_size floats); 1729e5c31af7Sopenharmony_ci * - rendering position coordinates (x and y); 1730e5c31af7Sopenharmony_ci * - check position coordinates (x and y). 1731e5c31af7Sopenharmony_ci * 1732e5c31af7Sopenharmony_ci * The grid has following layout: 1733e5c31af7Sopenharmony_ci * 1734e5c31af7Sopenharmony_ci * Grid | gl_CullDistance[x] | 1735e5c31af7Sopenharmony_ci * | 0 .. culldistances_array_size - 1 | 1736e5c31af7Sopenharmony_ci * | 0th | 1st | 2nd | .......... | 1737e5c31af7Sopenharmony_ci * ---------------------------+-------+-------+-------+------------+ 1738e5c31af7Sopenharmony_ci * 0th gl_ClipDistance |Subgrid|Subgrid|Subgrid| .......... | 1739e5c31af7Sopenharmony_ci * 1st gl_ClipDistance |Subgrid|Subgrid|Subgrid| .......... | 1740e5c31af7Sopenharmony_ci * ... | ... | ... | ... | .......... | 1741e5c31af7Sopenharmony_ci * y-th gl_ClipDistance |Subgrid|Subgrid|Subgrid| .......... | 1742e5c31af7Sopenharmony_ci * ... | ... | ... | ... | .......... | 1743e5c31af7Sopenharmony_ci * clipdistances_array_size-1 |Subgrid|Subgrid|Subgrid| .......... | 1744e5c31af7Sopenharmony_ci * 1745e5c31af7Sopenharmony_ci * Each grid cell contains subgrid of 3*3 items in size with following 1746e5c31af7Sopenharmony_ci * structure: 1747e5c31af7Sopenharmony_ci * 1748e5c31af7Sopenharmony_ci * Subgrid | x-th gl_CullDistance test | 1749e5c31af7Sopenharmony_ci * | | 1750e5c31af7Sopenharmony_ci * y-th | all vertices | 0th vertex | all vertices | 1751e5c31af7Sopenharmony_ci * gl_ClipDistance| in primitive | in primitive | in primitive | 1752e5c31af7Sopenharmony_ci * tests | dist[x] > 0 | dist[x] < 0 | dist[x] < 0 | 1753e5c31af7Sopenharmony_ci * ---------------+--------------+--------------+--------------+ 1754e5c31af7Sopenharmony_ci * all vertices| primitive #0 | primitive #1 | primitive #2 | 1755e5c31af7Sopenharmony_ci * in primitive| | | | 1756e5c31af7Sopenharmony_ci * dist[y] > 0 | visible | visible | culled | 1757e5c31af7Sopenharmony_ci * ---------------+--------------+--------------+--------------+ 1758e5c31af7Sopenharmony_ci * 0th vertex | primitive #3 | primitive #4 | primitive #5 | 1759e5c31af7Sopenharmony_ci * in primitive| 0th vertex | 0th vertex | | 1760e5c31af7Sopenharmony_ci * dist[y] < 0 | clipped | clipped | culled | 1761e5c31af7Sopenharmony_ci * ---------------+--------------+--------------+--------------+ 1762e5c31af7Sopenharmony_ci * all vertices| primitive #6 | primitive #7 | primitive #8 | 1763e5c31af7Sopenharmony_ci * in primitive| | | | 1764e5c31af7Sopenharmony_ci * dist[y] < 0 | clipped | clipped | culled | 1765e5c31af7Sopenharmony_ci * ---------------+--------------+--------------+--------------+ 1766e5c31af7Sopenharmony_ci * 1767e5c31af7Sopenharmony_ci * Expected rendering result is specified in cell bottom. 1768e5c31af7Sopenharmony_ci * It can be one of the following: 1769e5c31af7Sopenharmony_ci * - "visible" means the primitive is not affected neither by gl_CullDistance 1770e5c31af7Sopenharmony_ci * nor by gl_ClipDistance and rendered as a whole; 1771e5c31af7Sopenharmony_ci * - "clipped" for the vertex means the vertex is not rendered, while other 1772e5c31af7Sopenharmony_ci * primitive vertices and some filling fragments are rendered; 1773e5c31af7Sopenharmony_ci * - "clipped" for primitive means none of primitive vertices and fragments 1774e5c31af7Sopenharmony_ci * are rendered and thus primitive is not rendered and is invisible; 1775e5c31af7Sopenharmony_ci * - "culled" means, that neither primitive vertices, nor primitive filling 1776e5c31af7Sopenharmony_ci * fragments are rendered (primitive is invisible). 1777e5c31af7Sopenharmony_ci * 1778e5c31af7Sopenharmony_ci * All subgrid items contain same primitive rendered. Depending on 1779e5c31af7Sopenharmony_ci * test case running it would be either triangle, or line, or point: 1780e5c31af7Sopenharmony_ci * 1781e5c31af7Sopenharmony_ci * triangle line point 1782e5c31af7Sopenharmony_ci * 8x8 box 8x8 box 3x3 box 1783e5c31af7Sopenharmony_ci * ........ ........ ... 1784e5c31af7Sopenharmony_ci * .0----2. .0...... .0. 1785e5c31af7Sopenharmony_ci * ..\@@@|. ..\..... ... 1786e5c31af7Sopenharmony_ci * ...\@@|. ...\.... 1787e5c31af7Sopenharmony_ci * ....\@|. ....\... 1788e5c31af7Sopenharmony_ci * .....\|. .....\.. 1789e5c31af7Sopenharmony_ci * ......1. ......1. 1790e5c31af7Sopenharmony_ci * ........ ........ 1791e5c31af7Sopenharmony_ci * 1792e5c31af7Sopenharmony_ci * where 0 - is a 0th vertex primitive 1793e5c31af7Sopenharmony_ci * 1 - is a 1st vertex primitive 1794e5c31af7Sopenharmony_ci * 2 - is a 2nd vertex primitive 1795e5c31af7Sopenharmony_ci * 1796e5c31af7Sopenharmony_ci * The culldistances_array_size can be 0. In that case, grid height 1797e5c31af7Sopenharmony_ci * is assumed equal to 1, but 0 glCullDistances is specified. 1798e5c31af7Sopenharmony_ci * Similar handled clipdistances_array_size. 1799e5c31af7Sopenharmony_ci * 1800e5c31af7Sopenharmony_ci * The data generated is used and checked in executeRenderTest(). 1801e5c31af7Sopenharmony_ci * After rendering each primitive vertex is tested: 1802e5c31af7Sopenharmony_ci * - if it is rendered, if it have to be rendered (according distance); 1803e5c31af7Sopenharmony_ci * - if it is not rendered, if it have to be not rendered (according distance). 1804e5c31af7Sopenharmony_ci * Due to "top-left" rasterization rule check position is 1805e5c31af7Sopenharmony_ci * different from rendering vertex position. 1806e5c31af7Sopenharmony_ci * 1807e5c31af7Sopenharmony_ci * Also one pixel width guarding box is checked to be clear. 1808e5c31af7Sopenharmony_ci */ 1809e5c31af7Sopenharmony_ci 1810e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1811e5c31af7Sopenharmony_ci const glw::GLuint n_sub_grid_cells = 3; /* Tested distance is positive for all vertices in the primitive; 1812e5c31af7Sopenharmony_ci * Tested distance is negative for 0th vertex in the primitive; 1813e5c31af7Sopenharmony_ci * Tested distance is negative for all vertices in the primitive; 1814e5c31af7Sopenharmony_ci */ 1815e5c31af7Sopenharmony_ci const glw::GLuint sub_grid_cell_size = 1816e5c31af7Sopenharmony_ci ((primitive_mode == PRIMITIVE_MODE_LINES) ? 8 : (primitive_mode == PRIMITIVE_MODE_POINTS) ? 3 : 8); 1817e5c31af7Sopenharmony_ci 1818e5c31af7Sopenharmony_ci const glw::GLuint grid_cell_size = n_sub_grid_cells * sub_grid_cell_size; 1819e5c31af7Sopenharmony_ci const glw::GLuint n_primitive_vertices = 1820e5c31af7Sopenharmony_ci ((primitive_mode == PRIMITIVE_MODE_LINES) ? 2 : (primitive_mode == PRIMITIVE_MODE_POINTS) ? 1 : 3); 1821e5c31af7Sopenharmony_ci 1822e5c31af7Sopenharmony_ci const glw::GLuint n_grid_cells_x = culldistances_array_size != 0 ? culldistances_array_size : 1; 1823e5c31af7Sopenharmony_ci const glw::GLuint n_grid_cells_y = clipdistances_array_size != 0 ? clipdistances_array_size : 1; 1824e5c31af7Sopenharmony_ci const glw::GLuint n_pervertex_float_attributes = clipdistances_array_size + culldistances_array_size + 1825e5c31af7Sopenharmony_ci 2 /* vertex' draw x, y */ + 2 /* vertex' checkpoint x, y */; 1826e5c31af7Sopenharmony_ci const glw::GLuint n_primitives_total = n_grid_cells_x * n_sub_grid_cells * n_grid_cells_y * n_sub_grid_cells; 1827e5c31af7Sopenharmony_ci const glw::GLuint n_vertices_total = n_primitives_total * n_primitive_vertices; 1828e5c31af7Sopenharmony_ci const glw::GLuint offsets_line_draw_x[2] = { 1829e5c31af7Sopenharmony_ci 1, sub_grid_cell_size - 1 1830e5c31af7Sopenharmony_ci }; /* vertex x offsets to subgrid cell origin for line primitive */ 1831e5c31af7Sopenharmony_ci const glw::GLuint offsets_line_draw_y[2] = { 1832e5c31af7Sopenharmony_ci 1, sub_grid_cell_size - 1 1833e5c31af7Sopenharmony_ci }; /* vertex y offsets to subgrid cell origin for line primitive */ 1834e5c31af7Sopenharmony_ci const glw::GLuint offsets_line_checkpoint_x[2] = { 1835e5c31af7Sopenharmony_ci 1, sub_grid_cell_size - 2 1836e5c31af7Sopenharmony_ci }; /* pixel x offsets to subgrid cell origin for line primitive */ 1837e5c31af7Sopenharmony_ci const glw::GLuint offsets_line_checkpoint_y[2] = { 1838e5c31af7Sopenharmony_ci 1, sub_grid_cell_size - 2 1839e5c31af7Sopenharmony_ci }; /* pixel y offsets to subgrid cell origin for line primitive */ 1840e5c31af7Sopenharmony_ci const glw::GLuint offsets_point_draw_x[1] = { 1841e5c31af7Sopenharmony_ci 1 1842e5c31af7Sopenharmony_ci }; /* vertex x offsets to subgrid cell origin for point primitive */ 1843e5c31af7Sopenharmony_ci const glw::GLuint offsets_point_draw_y[1] = { 1844e5c31af7Sopenharmony_ci 1 1845e5c31af7Sopenharmony_ci }; /* vertex y offsets to subgrid cell origin for point primitive */ 1846e5c31af7Sopenharmony_ci const glw::GLuint offsets_point_checkpoint_x[1] = { 1847e5c31af7Sopenharmony_ci 1 1848e5c31af7Sopenharmony_ci }; /* pixel x offsets to subgrid cell origin for point primitive */ 1849e5c31af7Sopenharmony_ci const glw::GLuint offsets_point_checkpoint_y[1] = { 1850e5c31af7Sopenharmony_ci 1 1851e5c31af7Sopenharmony_ci }; /* pixel y offsets to subgrid cell origin for point primitive */ 1852e5c31af7Sopenharmony_ci const glw::GLuint offsets_triangle_draw_x[3] = { 1853e5c31af7Sopenharmony_ci 1, sub_grid_cell_size - 1, sub_grid_cell_size - 1 1854e5c31af7Sopenharmony_ci }; /* vertex x offsets to subgrid cell origin for triangle primitive */ 1855e5c31af7Sopenharmony_ci const glw::GLuint offsets_triangle_draw_y[3] = { 1856e5c31af7Sopenharmony_ci 1, sub_grid_cell_size - 1, 1 1857e5c31af7Sopenharmony_ci }; /* vertex y offsets to subgrid cell origin for triangle primitive */ 1858e5c31af7Sopenharmony_ci const glw::GLuint offsets_triangle_checkpoint_x[3] = { 1859e5c31af7Sopenharmony_ci 1, sub_grid_cell_size - 2, sub_grid_cell_size - 2 1860e5c31af7Sopenharmony_ci }; /* pixel x offsets to subgrid cell origin for triangle primitive */ 1861e5c31af7Sopenharmony_ci const glw::GLuint offsets_triangle_checkpoint_y[3] = { 1862e5c31af7Sopenharmony_ci 1, sub_grid_cell_size - 2, 1 1863e5c31af7Sopenharmony_ci }; /* pixel y offsets to subgrid cell origin for triangle primitive */ 1864e5c31af7Sopenharmony_ci const glw::GLfloat offsets_pixel_center_x = (primitive_mode == PRIMITIVE_MODE_POINTS) ? 0.5f : 0; 1865e5c31af7Sopenharmony_ci const glw::GLfloat offsets_pixel_center_y = (primitive_mode == PRIMITIVE_MODE_POINTS) ? 0.5f : 0; 1866e5c31af7Sopenharmony_ci /* Clear data left from previous tests. */ 1867e5c31af7Sopenharmony_ci m_bo_data.clear(); 1868e5c31af7Sopenharmony_ci 1869e5c31af7Sopenharmony_ci /* No data to render */ 1870e5c31af7Sopenharmony_ci m_render_primitives = 0; 1871e5c31af7Sopenharmony_ci m_render_vertices = 0; 1872e5c31af7Sopenharmony_ci 1873e5c31af7Sopenharmony_ci /* Preallocate space for bo_points_count */ 1874e5c31af7Sopenharmony_ci m_bo_data.reserve(n_vertices_total * n_pervertex_float_attributes); 1875e5c31af7Sopenharmony_ci 1876e5c31af7Sopenharmony_ci /* Generate test data for cell_y-th clip distance */ 1877e5c31af7Sopenharmony_ci for (glw::GLuint cell_y = 0; cell_y < n_grid_cells_y; cell_y++) 1878e5c31af7Sopenharmony_ci { 1879e5c31af7Sopenharmony_ci /* Generate test data for cell_x-th cull distance */ 1880e5c31af7Sopenharmony_ci for (glw::GLuint cell_x = 0; cell_x < n_grid_cells_x; cell_x++) 1881e5c31af7Sopenharmony_ci { 1882e5c31af7Sopenharmony_ci /* Check clip distance sub cases: 1883e5c31af7Sopenharmony_ci * 0. Tested distance is positive for all vertices in the primitive; 1884e5c31af7Sopenharmony_ci * 1. Tested distance is negative for 0th vertex in the primitive; 1885e5c31af7Sopenharmony_ci * 2. Tested distance is negative for all vertices in the primitive; 1886e5c31af7Sopenharmony_ci */ 1887e5c31af7Sopenharmony_ci for (glw::GLuint n_sub_cell_y = 0; n_sub_cell_y < n_sub_grid_cells; n_sub_cell_y++) 1888e5c31af7Sopenharmony_ci { 1889e5c31af7Sopenharmony_ci /* Check cull distance sub cases: 1890e5c31af7Sopenharmony_ci * 0. Tested distance is positive for all vertices in the primitive; 1891e5c31af7Sopenharmony_ci * 1. Tested distance is negative for 0th vertex in the primitive; 1892e5c31af7Sopenharmony_ci * 2. Tested distance is negative for all vertices in the primitive; 1893e5c31af7Sopenharmony_ci */ 1894e5c31af7Sopenharmony_ci for (glw::GLuint n_sub_cell_x = 0; n_sub_cell_x < n_sub_grid_cells; n_sub_cell_x++) 1895e5c31af7Sopenharmony_ci { 1896e5c31af7Sopenharmony_ci /* Generate vertices in primitive */ 1897e5c31af7Sopenharmony_ci for (glw::GLuint n_primitive_vertex = 0; n_primitive_vertex < n_primitive_vertices; 1898e5c31af7Sopenharmony_ci n_primitive_vertex++) 1899e5c31af7Sopenharmony_ci { 1900e5c31af7Sopenharmony_ci /* Fill in clipdistance array for the n_primitive_vertex vertex in primitive */ 1901e5c31af7Sopenharmony_ci for (glw::GLuint n_clipdistance_entry = 0; n_clipdistance_entry < clipdistances_array_size; 1902e5c31af7Sopenharmony_ci n_clipdistance_entry++) 1903e5c31af7Sopenharmony_ci { 1904e5c31af7Sopenharmony_ci glw::GLfloat distance_value = 0.0f; 1905e5c31af7Sopenharmony_ci bool negative = true; 1906e5c31af7Sopenharmony_ci 1907e5c31af7Sopenharmony_ci /* Special approach to tested clipdistance entry. */ 1908e5c31af7Sopenharmony_ci if (n_clipdistance_entry == cell_y) 1909e5c31af7Sopenharmony_ci { 1910e5c31af7Sopenharmony_ci /* The primitive vertex should be affected by the clip distance */ 1911e5c31af7Sopenharmony_ci switch (n_sub_cell_y) 1912e5c31af7Sopenharmony_ci { 1913e5c31af7Sopenharmony_ci case 0: 1914e5c31af7Sopenharmony_ci { 1915e5c31af7Sopenharmony_ci /* subgrid row 0: all primitive vertices have tested distance value positive */ 1916e5c31af7Sopenharmony_ci negative = false; 1917e5c31af7Sopenharmony_ci 1918e5c31af7Sopenharmony_ci break; 1919e5c31af7Sopenharmony_ci } 1920e5c31af7Sopenharmony_ci case 1: 1921e5c31af7Sopenharmony_ci { 1922e5c31af7Sopenharmony_ci /* subgrid row 1: tested distance value for 0th primitive vertex is negative, 1923e5c31af7Sopenharmony_ci all other primitive vertices have tested distance value positive */ 1924e5c31af7Sopenharmony_ci negative = (n_primitive_vertex == 0) ? true : false; 1925e5c31af7Sopenharmony_ci 1926e5c31af7Sopenharmony_ci break; 1927e5c31af7Sopenharmony_ci } 1928e5c31af7Sopenharmony_ci case 2: 1929e5c31af7Sopenharmony_ci { 1930e5c31af7Sopenharmony_ci /* subgrid row 2: tested distance value is negative for all primitive vertices */ 1931e5c31af7Sopenharmony_ci negative = true; 1932e5c31af7Sopenharmony_ci 1933e5c31af7Sopenharmony_ci break; 1934e5c31af7Sopenharmony_ci } 1935e5c31af7Sopenharmony_ci default: 1936e5c31af7Sopenharmony_ci TCU_FAIL("Invalid subgrid cell index"); 1937e5c31af7Sopenharmony_ci } 1938e5c31af7Sopenharmony_ci 1939e5c31af7Sopenharmony_ci distance_value = (negative ? -1.0f : 1.0f) * glw::GLfloat(n_clipdistance_entry + 1); 1940e5c31af7Sopenharmony_ci } 1941e5c31af7Sopenharmony_ci else 1942e5c31af7Sopenharmony_ci { 1943e5c31af7Sopenharmony_ci /* For clip distances other than tested: assign positive value to avoid its influence. */ 1944e5c31af7Sopenharmony_ci distance_value = glw::GLfloat(clipdistances_array_size + n_clipdistance_entry + 1); 1945e5c31af7Sopenharmony_ci } 1946e5c31af7Sopenharmony_ci 1947e5c31af7Sopenharmony_ci m_bo_data.push_back(distance_value / glw::GLfloat(clipdistances_array_size)); 1948e5c31af7Sopenharmony_ci } /* for (all gl_ClipDistance[] array values) */ 1949e5c31af7Sopenharmony_ci 1950e5c31af7Sopenharmony_ci /* Fill in culldistance array for the n_primitive_vertex vertex in primitive */ 1951e5c31af7Sopenharmony_ci for (glw::GLuint n_culldistance_entry = 0; n_culldistance_entry < culldistances_array_size; 1952e5c31af7Sopenharmony_ci n_culldistance_entry++) 1953e5c31af7Sopenharmony_ci { 1954e5c31af7Sopenharmony_ci glw::GLfloat distance_value = 0.0f; 1955e5c31af7Sopenharmony_ci bool negative = true; 1956e5c31af7Sopenharmony_ci 1957e5c31af7Sopenharmony_ci /* Special approach to tested culldistance entry. */ 1958e5c31af7Sopenharmony_ci if (n_culldistance_entry == cell_x) 1959e5c31af7Sopenharmony_ci { 1960e5c31af7Sopenharmony_ci /* The primitive vertex should be affected by the cull distance */ 1961e5c31af7Sopenharmony_ci switch (n_sub_cell_x) 1962e5c31af7Sopenharmony_ci { 1963e5c31af7Sopenharmony_ci case 0: 1964e5c31af7Sopenharmony_ci { 1965e5c31af7Sopenharmony_ci /* subgrid column 0: all primitive vertices have tested distance value positive */ 1966e5c31af7Sopenharmony_ci negative = false; 1967e5c31af7Sopenharmony_ci 1968e5c31af7Sopenharmony_ci break; 1969e5c31af7Sopenharmony_ci } 1970e5c31af7Sopenharmony_ci case 1: 1971e5c31af7Sopenharmony_ci { 1972e5c31af7Sopenharmony_ci /* subgrid column 1: tested distance value for 0th primitive vertex is negative, 1973e5c31af7Sopenharmony_ci all other primitive vertices have tested distance value positive */ 1974e5c31af7Sopenharmony_ci negative = (n_primitive_vertex == 0) ? true : false; 1975e5c31af7Sopenharmony_ci 1976e5c31af7Sopenharmony_ci break; 1977e5c31af7Sopenharmony_ci } 1978e5c31af7Sopenharmony_ci case 2: 1979e5c31af7Sopenharmony_ci { 1980e5c31af7Sopenharmony_ci /* subgrid column 2: tested distance value is negative for all primitive vertices */ 1981e5c31af7Sopenharmony_ci negative = true; 1982e5c31af7Sopenharmony_ci 1983e5c31af7Sopenharmony_ci break; 1984e5c31af7Sopenharmony_ci } 1985e5c31af7Sopenharmony_ci default: 1986e5c31af7Sopenharmony_ci TCU_FAIL("Invalid subgrid cell index"); 1987e5c31af7Sopenharmony_ci } 1988e5c31af7Sopenharmony_ci 1989e5c31af7Sopenharmony_ci distance_value = (negative ? -1.0f : 1.0f) * glw::GLfloat(n_culldistance_entry + 1); 1990e5c31af7Sopenharmony_ci } 1991e5c31af7Sopenharmony_ci else 1992e5c31af7Sopenharmony_ci { 1993e5c31af7Sopenharmony_ci /* For cull distances other than tested: assign 0th vertex negative value, 1994e5c31af7Sopenharmony_ci to check absence of between-distances influence. */ 1995e5c31af7Sopenharmony_ci if (n_primitive_vertices > 1 && n_primitive_vertex == 0) 1996e5c31af7Sopenharmony_ci { 1997e5c31af7Sopenharmony_ci distance_value = -glw::GLfloat(culldistances_array_size + n_culldistance_entry + 1); 1998e5c31af7Sopenharmony_ci } 1999e5c31af7Sopenharmony_ci else 2000e5c31af7Sopenharmony_ci { 2001e5c31af7Sopenharmony_ci /* This culldistance is out of interest: assign positive value. */ 2002e5c31af7Sopenharmony_ci distance_value = glw::GLfloat(culldistances_array_size + n_culldistance_entry + 1); 2003e5c31af7Sopenharmony_ci } 2004e5c31af7Sopenharmony_ci } 2005e5c31af7Sopenharmony_ci 2006e5c31af7Sopenharmony_ci m_bo_data.push_back(distance_value / glw::GLfloat(culldistances_array_size)); 2007e5c31af7Sopenharmony_ci } /* for (all gl_CullDistance[] array values) */ 2008e5c31af7Sopenharmony_ci 2009e5c31af7Sopenharmony_ci /* Generate primitve vertex draw and checkpoint coordinates */ 2010e5c31af7Sopenharmony_ci glw::GLint vertex_draw_pixel_offset_x = 0; 2011e5c31af7Sopenharmony_ci glw::GLint vertex_draw_pixel_offset_y = 0; 2012e5c31af7Sopenharmony_ci glw::GLint vertex_checkpoint_pixel_offset_x = 0; 2013e5c31af7Sopenharmony_ci glw::GLint vertex_checkpoint_pixel_offset_y = 0; 2014e5c31af7Sopenharmony_ci 2015e5c31af7Sopenharmony_ci switch (primitive_mode) 2016e5c31af7Sopenharmony_ci { 2017e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_LINES: 2018e5c31af7Sopenharmony_ci { 2019e5c31af7Sopenharmony_ci vertex_draw_pixel_offset_x = offsets_line_draw_x[n_primitive_vertex]; 2020e5c31af7Sopenharmony_ci vertex_draw_pixel_offset_y = offsets_line_draw_y[n_primitive_vertex]; 2021e5c31af7Sopenharmony_ci vertex_checkpoint_pixel_offset_x = offsets_line_checkpoint_x[n_primitive_vertex]; 2022e5c31af7Sopenharmony_ci vertex_checkpoint_pixel_offset_y = offsets_line_checkpoint_y[n_primitive_vertex]; 2023e5c31af7Sopenharmony_ci 2024e5c31af7Sopenharmony_ci break; 2025e5c31af7Sopenharmony_ci } 2026e5c31af7Sopenharmony_ci 2027e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_POINTS: 2028e5c31af7Sopenharmony_ci { 2029e5c31af7Sopenharmony_ci vertex_draw_pixel_offset_x = offsets_point_draw_x[n_primitive_vertex]; 2030e5c31af7Sopenharmony_ci vertex_draw_pixel_offset_y = offsets_point_draw_y[n_primitive_vertex]; 2031e5c31af7Sopenharmony_ci vertex_checkpoint_pixel_offset_x = offsets_point_checkpoint_x[n_primitive_vertex]; 2032e5c31af7Sopenharmony_ci vertex_checkpoint_pixel_offset_y = offsets_point_checkpoint_y[n_primitive_vertex]; 2033e5c31af7Sopenharmony_ci 2034e5c31af7Sopenharmony_ci break; 2035e5c31af7Sopenharmony_ci } 2036e5c31af7Sopenharmony_ci 2037e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_TRIANGLES: 2038e5c31af7Sopenharmony_ci { 2039e5c31af7Sopenharmony_ci vertex_draw_pixel_offset_x = offsets_triangle_draw_x[n_primitive_vertex]; 2040e5c31af7Sopenharmony_ci vertex_draw_pixel_offset_y = offsets_triangle_draw_y[n_primitive_vertex]; 2041e5c31af7Sopenharmony_ci vertex_checkpoint_pixel_offset_x = offsets_triangle_checkpoint_x[n_primitive_vertex]; 2042e5c31af7Sopenharmony_ci vertex_checkpoint_pixel_offset_y = offsets_triangle_checkpoint_y[n_primitive_vertex]; 2043e5c31af7Sopenharmony_ci 2044e5c31af7Sopenharmony_ci break; 2045e5c31af7Sopenharmony_ci } 2046e5c31af7Sopenharmony_ci 2047e5c31af7Sopenharmony_ci default: 2048e5c31af7Sopenharmony_ci TCU_FAIL("Unknown primitive mode"); 2049e5c31af7Sopenharmony_ci } 2050e5c31af7Sopenharmony_ci 2051e5c31af7Sopenharmony_ci /* Origin of sub_cell */ 2052e5c31af7Sopenharmony_ci glw::GLint sub_cell_origin_x = cell_x * grid_cell_size + n_sub_cell_x * sub_grid_cell_size; 2053e5c31af7Sopenharmony_ci glw::GLint sub_cell_origin_y = cell_y * grid_cell_size + n_sub_cell_y * sub_grid_cell_size; 2054e5c31af7Sopenharmony_ci /* Normalized texture coordinates of vertex draw position. */ 2055e5c31af7Sopenharmony_ci glw::GLfloat x = 2056e5c31af7Sopenharmony_ci (glw::GLfloat(sub_cell_origin_x + vertex_draw_pixel_offset_x) + offsets_pixel_center_x) / 2057e5c31af7Sopenharmony_ci glw::GLfloat(m_to_width); 2058e5c31af7Sopenharmony_ci glw::GLfloat y = 2059e5c31af7Sopenharmony_ci (glw::GLfloat(sub_cell_origin_y + vertex_draw_pixel_offset_y) + offsets_pixel_center_y) / 2060e5c31af7Sopenharmony_ci glw::GLfloat(m_to_height); 2061e5c31af7Sopenharmony_ci /* Normalized texture coordinates of vertex checkpoint position. */ 2062e5c31af7Sopenharmony_ci glw::GLfloat checkpoint_x = glw::GLfloat(sub_cell_origin_x + vertex_checkpoint_pixel_offset_x) / 2063e5c31af7Sopenharmony_ci glw::GLfloat(m_to_width); 2064e5c31af7Sopenharmony_ci glw::GLfloat checkpoint_y = glw::GLfloat(sub_cell_origin_y + vertex_checkpoint_pixel_offset_y) / 2065e5c31af7Sopenharmony_ci glw::GLfloat(m_to_height); 2066e5c31af7Sopenharmony_ci 2067e5c31af7Sopenharmony_ci /* Add vertex draw coordinates into buffer. */ 2068e5c31af7Sopenharmony_ci m_bo_data.push_back(x); 2069e5c31af7Sopenharmony_ci m_bo_data.push_back(y); 2070e5c31af7Sopenharmony_ci 2071e5c31af7Sopenharmony_ci /* Add vertex checkpoint coordinates into buffer. */ 2072e5c31af7Sopenharmony_ci m_bo_data.push_back(checkpoint_x); 2073e5c31af7Sopenharmony_ci m_bo_data.push_back(checkpoint_y); 2074e5c31af7Sopenharmony_ci } /* for (all vertices in primitive) */ 2075e5c31af7Sopenharmony_ci } /* for (all horizontal sub cells) */ 2076e5c31af7Sopenharmony_ci } /* for (all vertical sub cells) */ 2077e5c31af7Sopenharmony_ci } /* for (all horizontal cells) */ 2078e5c31af7Sopenharmony_ci } /* for (all vertical cells) */ 2079e5c31af7Sopenharmony_ci 2080e5c31af7Sopenharmony_ci /* Quick check: make sure we pushed required amount of data */ 2081e5c31af7Sopenharmony_ci DE_ASSERT(m_bo_data.size() == n_vertices_total * n_pervertex_float_attributes); 2082e5c31af7Sopenharmony_ci 2083e5c31af7Sopenharmony_ci /* Save number of primitives to render */ 2084e5c31af7Sopenharmony_ci m_render_primitives = n_primitives_total; 2085e5c31af7Sopenharmony_ci m_render_vertices = n_vertices_total; 2086e5c31af7Sopenharmony_ci m_sub_grid_cell_size = sub_grid_cell_size; 2087e5c31af7Sopenharmony_ci 2088e5c31af7Sopenharmony_ci /* Copy the data to the buffer object */ 2089e5c31af7Sopenharmony_ci gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id); 2090e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); 2091e5c31af7Sopenharmony_ci 2092e5c31af7Sopenharmony_ci gl.bufferData(GL_ARRAY_BUFFER, m_bo_data.size() * sizeof(glw::GLfloat), &m_bo_data[0], GL_STATIC_DRAW); 2093e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed."); 2094e5c31af7Sopenharmony_ci 2095e5c31af7Sopenharmony_ci DE_ASSERT(m_po_id != 0); 2096e5c31af7Sopenharmony_ci 2097e5c31af7Sopenharmony_ci /* Bind VAO data to program */ 2098e5c31af7Sopenharmony_ci glw::GLint po_clipdistance_array_location = -1; 2099e5c31af7Sopenharmony_ci glw::GLint po_culldistance_array_location = -1; 2100e5c31af7Sopenharmony_ci glw::GLint po_position_location = -1; 2101e5c31af7Sopenharmony_ci 2102e5c31af7Sopenharmony_ci /* Retrieve clipdistance and culldistance attribute locations */ 2103e5c31af7Sopenharmony_ci gl.bindVertexArray(m_vao_id); 2104e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 2105e5c31af7Sopenharmony_ci 2106e5c31af7Sopenharmony_ci po_clipdistance_array_location = gl.getAttribLocation(m_po_id, "clipdistance_data[0]"); 2107e5c31af7Sopenharmony_ci po_culldistance_array_location = gl.getAttribLocation(m_po_id, "culldistance_data[0]"); 2108e5c31af7Sopenharmony_ci po_position_location = gl.getAttribLocation(m_po_id, "position"); 2109e5c31af7Sopenharmony_ci 2110e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation() call(s) failed."); 2111e5c31af7Sopenharmony_ci 2112e5c31af7Sopenharmony_ci if (clipdistances_array_size > 0) 2113e5c31af7Sopenharmony_ci { 2114e5c31af7Sopenharmony_ci DE_ASSERT(po_clipdistance_array_location != -1); 2115e5c31af7Sopenharmony_ci } 2116e5c31af7Sopenharmony_ci 2117e5c31af7Sopenharmony_ci if (culldistances_array_size > 0) 2118e5c31af7Sopenharmony_ci { 2119e5c31af7Sopenharmony_ci DE_ASSERT(po_culldistance_array_location != -1); 2120e5c31af7Sopenharmony_ci } 2121e5c31af7Sopenharmony_ci 2122e5c31af7Sopenharmony_ci DE_ASSERT(po_position_location != -1); 2123e5c31af7Sopenharmony_ci 2124e5c31af7Sopenharmony_ci glw::GLintptr current_offset = 0; 2125e5c31af7Sopenharmony_ci const glw::GLint stride = static_cast<glw::GLint>(n_pervertex_float_attributes * sizeof(glw::GLfloat)); 2126e5c31af7Sopenharmony_ci 2127e5c31af7Sopenharmony_ci gl.bindVertexArray(m_vao_id); 2128e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed."); 2129e5c31af7Sopenharmony_ci 2130e5c31af7Sopenharmony_ci for (glw::GLuint n_clipdistance_entry = 0; n_clipdistance_entry < clipdistances_array_size; ++n_clipdistance_entry) 2131e5c31af7Sopenharmony_ci { 2132e5c31af7Sopenharmony_ci gl.vertexAttribPointer(po_clipdistance_array_location + n_clipdistance_entry, 1, /* size */ 2133e5c31af7Sopenharmony_ci GL_FLOAT, GL_FALSE, /* normalized */ 2134e5c31af7Sopenharmony_ci stride, (const glw::GLvoid*)current_offset); 2135e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed."); 2136e5c31af7Sopenharmony_ci 2137e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(po_clipdistance_array_location + n_clipdistance_entry); 2138e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed."); 2139e5c31af7Sopenharmony_ci 2140e5c31af7Sopenharmony_ci current_offset += sizeof(glw::GLfloat); 2141e5c31af7Sopenharmony_ci } /* for (all clip distance array value attributes) */ 2142e5c31af7Sopenharmony_ci 2143e5c31af7Sopenharmony_ci for (glw::GLuint n_culldistance_entry = 0; n_culldistance_entry < culldistances_array_size; ++n_culldistance_entry) 2144e5c31af7Sopenharmony_ci { 2145e5c31af7Sopenharmony_ci gl.vertexAttribPointer(po_culldistance_array_location + n_culldistance_entry, 1, /* size */ 2146e5c31af7Sopenharmony_ci GL_FLOAT, GL_FALSE, /* normalized */ 2147e5c31af7Sopenharmony_ci stride, (const glw::GLvoid*)current_offset); 2148e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed."); 2149e5c31af7Sopenharmony_ci 2150e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(po_culldistance_array_location + n_culldistance_entry); 2151e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed."); 2152e5c31af7Sopenharmony_ci 2153e5c31af7Sopenharmony_ci current_offset += sizeof(glw::GLfloat); 2154e5c31af7Sopenharmony_ci } /* for (all cull distance array value attributes) */ 2155e5c31af7Sopenharmony_ci 2156e5c31af7Sopenharmony_ci gl.vertexAttribPointer(po_position_location, 2, /* size */ 2157e5c31af7Sopenharmony_ci GL_FLOAT, GL_FALSE, /* normalized */ 2158e5c31af7Sopenharmony_ci stride, (const glw::GLvoid*)current_offset); 2159e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed"); 2160e5c31af7Sopenharmony_ci 2161e5c31af7Sopenharmony_ci gl.enableVertexAttribArray(po_position_location); 2162e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed"); 2163e5c31af7Sopenharmony_ci} 2164e5c31af7Sopenharmony_ci 2165e5c31af7Sopenharmony_ci/** @brief Cull Distance Functional Test deinitialization */ 2166e5c31af7Sopenharmony_civoid CullDistance::FunctionalTest::deinit() 2167e5c31af7Sopenharmony_ci{ 2168e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2169e5c31af7Sopenharmony_ci 2170e5c31af7Sopenharmony_ci if (m_fbo_id != 0) 2171e5c31af7Sopenharmony_ci { 2172e5c31af7Sopenharmony_ci gl.deleteFramebuffers(1, &m_fbo_id); 2173e5c31af7Sopenharmony_ci 2174e5c31af7Sopenharmony_ci m_fbo_id = 0; 2175e5c31af7Sopenharmony_ci } 2176e5c31af7Sopenharmony_ci 2177e5c31af7Sopenharmony_ci if (m_to_id != 0) 2178e5c31af7Sopenharmony_ci { 2179e5c31af7Sopenharmony_ci gl.deleteTextures(1, &m_to_id); 2180e5c31af7Sopenharmony_ci 2181e5c31af7Sopenharmony_ci m_to_id = 0; 2182e5c31af7Sopenharmony_ci } 2183e5c31af7Sopenharmony_ci 2184e5c31af7Sopenharmony_ci if (m_vao_id != 0) 2185e5c31af7Sopenharmony_ci { 2186e5c31af7Sopenharmony_ci gl.deleteVertexArrays(1, &m_vao_id); 2187e5c31af7Sopenharmony_ci 2188e5c31af7Sopenharmony_ci m_vao_id = 0; 2189e5c31af7Sopenharmony_ci } 2190e5c31af7Sopenharmony_ci 2191e5c31af7Sopenharmony_ci deinitPO(); 2192e5c31af7Sopenharmony_ci} 2193e5c31af7Sopenharmony_ci 2194e5c31af7Sopenharmony_ci/** @brief Cull Distance Functional Test deinitialization of OpenGL programs */ 2195e5c31af7Sopenharmony_civoid CullDistance::FunctionalTest::deinitPO() 2196e5c31af7Sopenharmony_ci{ 2197e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2198e5c31af7Sopenharmony_ci 2199e5c31af7Sopenharmony_ci if (m_po_id != 0) 2200e5c31af7Sopenharmony_ci { 2201e5c31af7Sopenharmony_ci gl.deleteProgram(m_po_id); 2202e5c31af7Sopenharmony_ci 2203e5c31af7Sopenharmony_ci m_po_id = 0; 2204e5c31af7Sopenharmony_ci } 2205e5c31af7Sopenharmony_ci} 2206e5c31af7Sopenharmony_ci 2207e5c31af7Sopenharmony_ci/** @brief Executes single render test case 2208e5c31af7Sopenharmony_ci * 2209e5c31af7Sopenharmony_ci * @param [in] clipdistances_array_size Size of gl_ClipDistance[] array 2210e5c31af7Sopenharmony_ci * @param [in] culldistances_array_size Size of gl_CullDistance[] array 2211e5c31af7Sopenharmony_ci * @param [in] primitive_mode Type of primitives to be rendered (see enum _primitive_mode) 2212e5c31af7Sopenharmony_ci * @param [in] use_tesselation Indicate whether to use tessellation shader 2213e5c31af7Sopenharmony_ci * @param [in] fetch_culldistance_from_fs Indicate whether to fetch gl_CullDistance and gl_ClipDistance values from the fragment shader 2214e5c31af7Sopenharmony_ci */ 2215e5c31af7Sopenharmony_civoid CullDistance::FunctionalTest::executeRenderTest(glw::GLuint clipdistances_array_size, 2216e5c31af7Sopenharmony_ci glw::GLuint culldistances_array_size, 2217e5c31af7Sopenharmony_ci _primitive_mode primitive_mode, bool use_tesselation, 2218e5c31af7Sopenharmony_ci bool fetch_culldistance_from_fs) 2219e5c31af7Sopenharmony_ci{ 2220e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2221e5c31af7Sopenharmony_ci glw::GLenum mode = GL_NONE; 2222e5c31af7Sopenharmony_ci glw::GLuint n_clipped_vertices_real = 0; 2223e5c31af7Sopenharmony_ci glw::GLuint n_culled_primitives_real = 0; 2224e5c31af7Sopenharmony_ci const glw::GLuint primitive_vertices_count = 2225e5c31af7Sopenharmony_ci ((primitive_mode == PRIMITIVE_MODE_LINES) ? 2 : (primitive_mode == PRIMITIVE_MODE_POINTS) ? 1 : 3); 2226e5c31af7Sopenharmony_ci const glw::GLuint stride_in_floats = 2227e5c31af7Sopenharmony_ci clipdistances_array_size + culldistances_array_size + 2 /* position's x, y*/ + 2 /* checkpoint x,y */; 2228e5c31af7Sopenharmony_ci 2229e5c31af7Sopenharmony_ci // Release build does not use them 2230e5c31af7Sopenharmony_ci DE_UNREF(n_clipped_vertices_real); 2231e5c31af7Sopenharmony_ci DE_UNREF(n_culled_primitives_real); 2232e5c31af7Sopenharmony_ci 2233e5c31af7Sopenharmony_ci switch (primitive_mode) 2234e5c31af7Sopenharmony_ci { 2235e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_LINES: 2236e5c31af7Sopenharmony_ci { 2237e5c31af7Sopenharmony_ci mode = GL_LINES; 2238e5c31af7Sopenharmony_ci 2239e5c31af7Sopenharmony_ci break; 2240e5c31af7Sopenharmony_ci } 2241e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_POINTS: 2242e5c31af7Sopenharmony_ci { 2243e5c31af7Sopenharmony_ci mode = GL_POINTS; 2244e5c31af7Sopenharmony_ci 2245e5c31af7Sopenharmony_ci break; 2246e5c31af7Sopenharmony_ci } 2247e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_TRIANGLES: 2248e5c31af7Sopenharmony_ci { 2249e5c31af7Sopenharmony_ci mode = GL_TRIANGLES; 2250e5c31af7Sopenharmony_ci 2251e5c31af7Sopenharmony_ci break; 2252e5c31af7Sopenharmony_ci } 2253e5c31af7Sopenharmony_ci default: 2254e5c31af7Sopenharmony_ci TCU_FAIL("Unknown primitive mode"); 2255e5c31af7Sopenharmony_ci } 2256e5c31af7Sopenharmony_ci 2257e5c31af7Sopenharmony_ci if (use_tesselation) 2258e5c31af7Sopenharmony_ci { 2259e5c31af7Sopenharmony_ci mode = GL_PATCHES; 2260e5c31af7Sopenharmony_ci 2261e5c31af7Sopenharmony_ci gl.patchParameteri(GL_PATCH_VERTICES, primitive_vertices_count); 2262e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed."); 2263e5c31af7Sopenharmony_ci } 2264e5c31af7Sopenharmony_ci 2265e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT); 2266e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed."); 2267e5c31af7Sopenharmony_ci 2268e5c31af7Sopenharmony_ci gl.useProgram(m_po_id); 2269e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 2270e5c31af7Sopenharmony_ci 2271e5c31af7Sopenharmony_ci for (glw::GLuint n_clipdistance_entry = 0; n_clipdistance_entry < clipdistances_array_size; n_clipdistance_entry++) 2272e5c31af7Sopenharmony_ci { 2273e5c31af7Sopenharmony_ci gl.enable(GL_CLIP_DISTANCE0 + n_clipdistance_entry); 2274e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "gl.enable(GL_CLIP_DISTANCE)() call failed."); 2275e5c31af7Sopenharmony_ci } /* for (all clip distance array value attributes) */ 2276e5c31af7Sopenharmony_ci 2277e5c31af7Sopenharmony_ci gl.drawArrays(mode, 0, m_render_vertices); 2278e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray() call(s) failed."); 2279e5c31af7Sopenharmony_ci 2280e5c31af7Sopenharmony_ci for (glw::GLuint n_clipdistance_entry = 0; n_clipdistance_entry < clipdistances_array_size; n_clipdistance_entry++) 2281e5c31af7Sopenharmony_ci { 2282e5c31af7Sopenharmony_ci gl.disable(GL_CLIP_DISTANCE0 + n_clipdistance_entry); 2283e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "gl.disable(GL_CLIP_DISTANCE)() call failed."); 2284e5c31af7Sopenharmony_ci } /* for (all clip distance array value attributes) */ 2285e5c31af7Sopenharmony_ci 2286e5c31af7Sopenharmony_ci gl.useProgram(0); 2287e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); 2288e5c31af7Sopenharmony_ci 2289e5c31af7Sopenharmony_ci /* Read generated texture into m_to_pixel_data_cache */ 2290e5c31af7Sopenharmony_ci readTexturePixels(); 2291e5c31af7Sopenharmony_ci 2292e5c31af7Sopenharmony_ci for (glw::GLint n_primitive_index = 0; n_primitive_index < m_render_primitives; n_primitive_index++) 2293e5c31af7Sopenharmony_ci { 2294e5c31af7Sopenharmony_ci glw::GLuint base_index_of_primitive = n_primitive_index * primitive_vertices_count * stride_in_floats; 2295e5c31af7Sopenharmony_ci bool primitive_culled = false; 2296e5c31af7Sopenharmony_ci glw::GLint primitive_culled_by_distance = -1; 2297e5c31af7Sopenharmony_ci 2298e5c31af7Sopenharmony_ci /* Check the bounding box is clear */ 2299e5c31af7Sopenharmony_ci glw::GLuint base_index_of_vertex = base_index_of_primitive; 2300e5c31af7Sopenharmony_ci glw::GLuint checkpoint_position_index = base_index_of_vertex + clipdistances_array_size + 2301e5c31af7Sopenharmony_ci culldistances_array_size + 2 /* ignore vertex coordinates */; 2302e5c31af7Sopenharmony_ci glw::GLint checkpoint_x = glw::GLint(glw::GLfloat(m_to_width) * m_bo_data[checkpoint_position_index]); 2303e5c31af7Sopenharmony_ci glw::GLint checkpoint_y = glw::GLint(glw::GLfloat(m_to_height) * m_bo_data[checkpoint_position_index + 1]); 2304e5c31af7Sopenharmony_ci glw::GLint origin_x = checkpoint_x - 1; 2305e5c31af7Sopenharmony_ci glw::GLint origin_y = checkpoint_y - 1; 2306e5c31af7Sopenharmony_ci for (glw::GLint pixel_offset = 0; pixel_offset < m_sub_grid_cell_size; pixel_offset++) 2307e5c31af7Sopenharmony_ci { 2308e5c31af7Sopenharmony_ci if (readRedPixelValue(origin_x + pixel_offset, origin_y) != 0) 2309e5c31af7Sopenharmony_ci { 2310e5c31af7Sopenharmony_ci TCU_FAIL("Top edge of bounding box is overwritten"); 2311e5c31af7Sopenharmony_ci } 2312e5c31af7Sopenharmony_ci 2313e5c31af7Sopenharmony_ci if (readRedPixelValue(origin_x + m_sub_grid_cell_size - 1, origin_y + pixel_offset) != 0) 2314e5c31af7Sopenharmony_ci { 2315e5c31af7Sopenharmony_ci TCU_FAIL("Right edge of bounding box is overwritten"); 2316e5c31af7Sopenharmony_ci } 2317e5c31af7Sopenharmony_ci 2318e5c31af7Sopenharmony_ci if (readRedPixelValue(origin_x + m_sub_grid_cell_size - 1 - pixel_offset, 2319e5c31af7Sopenharmony_ci origin_y + m_sub_grid_cell_size - 1) != 0) 2320e5c31af7Sopenharmony_ci { 2321e5c31af7Sopenharmony_ci TCU_FAIL("Bottom edge of bounding box is overwritten"); 2322e5c31af7Sopenharmony_ci } 2323e5c31af7Sopenharmony_ci 2324e5c31af7Sopenharmony_ci if (readRedPixelValue(origin_x, origin_y + m_sub_grid_cell_size - 1 - pixel_offset) != 0) 2325e5c31af7Sopenharmony_ci { 2326e5c31af7Sopenharmony_ci TCU_FAIL("Left edge of bounding box is overwritten"); 2327e5c31af7Sopenharmony_ci } 2328e5c31af7Sopenharmony_ci } 2329e5c31af7Sopenharmony_ci 2330e5c31af7Sopenharmony_ci /* Determine if primitive has been culled */ 2331e5c31af7Sopenharmony_ci for (glw::GLuint n_culldistance_entry = 0; n_culldistance_entry < culldistances_array_size; 2332e5c31af7Sopenharmony_ci n_culldistance_entry++) 2333e5c31af7Sopenharmony_ci { 2334e5c31af7Sopenharmony_ci bool distance_negative_in_all_primitive_vertices = true; 2335e5c31af7Sopenharmony_ci 2336e5c31af7Sopenharmony_ci for (glw::GLuint n_primitive_vertex = 0; n_primitive_vertex < primitive_vertices_count; 2337e5c31af7Sopenharmony_ci n_primitive_vertex++) 2338e5c31af7Sopenharmony_ci { 2339e5c31af7Sopenharmony_ci glw::GLint base_index_of_vertex_internal = 2340e5c31af7Sopenharmony_ci base_index_of_primitive + n_primitive_vertex * stride_in_floats; 2341e5c31af7Sopenharmony_ci glw::GLint culldistance_array_offset = base_index_of_vertex_internal + clipdistances_array_size; 2342e5c31af7Sopenharmony_ci glw::GLfloat* vertex_culldistance_array = &m_bo_data[culldistance_array_offset]; 2343e5c31af7Sopenharmony_ci 2344e5c31af7Sopenharmony_ci if (vertex_culldistance_array[n_culldistance_entry] >= 0) 2345e5c31af7Sopenharmony_ci { 2346e5c31af7Sopenharmony_ci /* Primitive is not culled, due to one of its distances is not negative */ 2347e5c31af7Sopenharmony_ci distance_negative_in_all_primitive_vertices = false; 2348e5c31af7Sopenharmony_ci 2349e5c31af7Sopenharmony_ci /* Skip left vertices for this distance */ 2350e5c31af7Sopenharmony_ci break; 2351e5c31af7Sopenharmony_ci } 2352e5c31af7Sopenharmony_ci } 2353e5c31af7Sopenharmony_ci 2354e5c31af7Sopenharmony_ci /* The distance is negative in all primitive vertices, so this distance culls the primitive */ 2355e5c31af7Sopenharmony_ci if (distance_negative_in_all_primitive_vertices) 2356e5c31af7Sopenharmony_ci { 2357e5c31af7Sopenharmony_ci primitive_culled = true; 2358e5c31af7Sopenharmony_ci primitive_culled_by_distance = n_culldistance_entry; 2359e5c31af7Sopenharmony_ci 2360e5c31af7Sopenharmony_ci n_culled_primitives_real++; 2361e5c31af7Sopenharmony_ci 2362e5c31af7Sopenharmony_ci /* Skip left distances from check */ 2363e5c31af7Sopenharmony_ci break; 2364e5c31af7Sopenharmony_ci } 2365e5c31af7Sopenharmony_ci } 2366e5c31af7Sopenharmony_ci 2367e5c31af7Sopenharmony_ci /* Validate culling */ 2368e5c31af7Sopenharmony_ci if (primitive_culled) 2369e5c31af7Sopenharmony_ci { 2370e5c31af7Sopenharmony_ci /* Check whether primitive was culled and all its vertices are invisible */ 2371e5c31af7Sopenharmony_ci for (glw::GLuint n_primitive_vertex = 0; n_primitive_vertex < primitive_vertices_count; 2372e5c31af7Sopenharmony_ci n_primitive_vertex++) 2373e5c31af7Sopenharmony_ci { 2374e5c31af7Sopenharmony_ci glw::GLint base_index_of_vertex_internal = 2375e5c31af7Sopenharmony_ci base_index_of_primitive + n_primitive_vertex * stride_in_floats; 2376e5c31af7Sopenharmony_ci glw::GLint checkpoint_position_index_internal = base_index_of_vertex_internal + 2377e5c31af7Sopenharmony_ci clipdistances_array_size + culldistances_array_size + 2378e5c31af7Sopenharmony_ci 2 /* ignore vertex coordinates */; 2379e5c31af7Sopenharmony_ci glw::GLint checkpoint_x_internal = 2380e5c31af7Sopenharmony_ci glw::GLint(glw::GLfloat(m_to_width) * m_bo_data[checkpoint_position_index_internal]); 2381e5c31af7Sopenharmony_ci glw::GLint checkpoint_y_internal = 2382e5c31af7Sopenharmony_ci glw::GLint(glw::GLfloat(m_to_height) * m_bo_data[checkpoint_position_index_internal + 1]); 2383e5c31af7Sopenharmony_ci glw::GLint vertex_color_red_value = readRedPixelValue(checkpoint_x_internal, checkpoint_y_internal); 2384e5c31af7Sopenharmony_ci 2385e5c31af7Sopenharmony_ci /* Make sure vertex is invisible */ 2386e5c31af7Sopenharmony_ci if (vertex_color_red_value != 0) 2387e5c31af7Sopenharmony_ci { 2388e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Primitive number [" << n_primitive_index << "] " 2389e5c31af7Sopenharmony_ci << "should be culled by distance [" << primitive_culled_by_distance << "]" 2390e5c31af7Sopenharmony_ci << "but primitive vertex at (" << checkpoint_x << "," << checkpoint_y 2391e5c31af7Sopenharmony_ci << ") is visible." << tcu::TestLog::EndMessage; 2392e5c31af7Sopenharmony_ci 2393e5c31af7Sopenharmony_ci TCU_FAIL("Primitive is expected to be culled, but one of its vertices is visible."); 2394e5c31af7Sopenharmony_ci } 2395e5c31af7Sopenharmony_ci } 2396e5c31af7Sopenharmony_ci 2397e5c31af7Sopenharmony_ci /* Primitive is culled, no reason to check clipping */ 2398e5c31af7Sopenharmony_ci continue; 2399e5c31af7Sopenharmony_ci } 2400e5c31af7Sopenharmony_ci 2401e5c31af7Sopenharmony_ci bool all_vertices_are_clipped = true; 2402e5c31af7Sopenharmony_ci 2403e5c31af7Sopenharmony_ci for (glw::GLuint n_primitive_vertex = 0; n_primitive_vertex < primitive_vertices_count; n_primitive_vertex++) 2404e5c31af7Sopenharmony_ci { 2405e5c31af7Sopenharmony_ci glw::GLuint base_index_of_vertex_internal = base_index_of_primitive + n_primitive_vertex * stride_in_floats; 2406e5c31af7Sopenharmony_ci glw::GLuint clipdistance_array_index = base_index_of_vertex_internal; 2407e5c31af7Sopenharmony_ci glw::GLuint checkpoint_position_index_internal = base_index_of_vertex_internal + clipdistances_array_size + 2408e5c31af7Sopenharmony_ci culldistances_array_size + 2409e5c31af7Sopenharmony_ci 2 /* ignore vertex coordinates */; 2410e5c31af7Sopenharmony_ci glw::GLint checkpoint_x_internal = 2411e5c31af7Sopenharmony_ci glw::GLint(glw::GLfloat(m_to_width) * m_bo_data[checkpoint_position_index_internal]); 2412e5c31af7Sopenharmony_ci glw::GLint checkpoint_y_internal = 2413e5c31af7Sopenharmony_ci glw::GLint(glw::GLfloat(m_to_height) * m_bo_data[checkpoint_position_index_internal + 1]); 2414e5c31af7Sopenharmony_ci glw::GLfloat* vertex_clipdistance_array = &m_bo_data[clipdistance_array_index]; 2415e5c31af7Sopenharmony_ci bool vertex_clipped = false; 2416e5c31af7Sopenharmony_ci glw::GLint vertex_clipped_by_distance = 0; 2417e5c31af7Sopenharmony_ci glw::GLint vertex_color_red_value = readRedPixelValue(checkpoint_x_internal, checkpoint_y_internal); 2418e5c31af7Sopenharmony_ci 2419e5c31af7Sopenharmony_ci /* Check whether pixel should be clipped */ 2420e5c31af7Sopenharmony_ci for (glw::GLuint n_clipdistance_entry = 0; n_clipdistance_entry < clipdistances_array_size; 2421e5c31af7Sopenharmony_ci n_clipdistance_entry++) 2422e5c31af7Sopenharmony_ci { 2423e5c31af7Sopenharmony_ci if (vertex_clipdistance_array[n_clipdistance_entry] < 0) 2424e5c31af7Sopenharmony_ci { 2425e5c31af7Sopenharmony_ci vertex_clipped = true; 2426e5c31af7Sopenharmony_ci vertex_clipped_by_distance = n_clipdistance_entry; 2427e5c31af7Sopenharmony_ci 2428e5c31af7Sopenharmony_ci break; 2429e5c31af7Sopenharmony_ci } 2430e5c31af7Sopenharmony_ci } 2431e5c31af7Sopenharmony_ci 2432e5c31af7Sopenharmony_ci all_vertices_are_clipped &= vertex_clipped; 2433e5c31af7Sopenharmony_ci 2434e5c31af7Sopenharmony_ci /* Validate whether real data same as expected */ 2435e5c31af7Sopenharmony_ci if (vertex_clipped) 2436e5c31af7Sopenharmony_ci { 2437e5c31af7Sopenharmony_ci if (vertex_color_red_value != 0) 2438e5c31af7Sopenharmony_ci { 2439e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "In primitive number [" << n_primitive_index << "] " 2440e5c31af7Sopenharmony_ci << "vertex at (" << checkpoint_x << "," << checkpoint_y << ") " 2441e5c31af7Sopenharmony_ci << "should be clipped by distance [" << vertex_clipped_by_distance << "] " 2442e5c31af7Sopenharmony_ci << "(distance value [" << vertex_clipdistance_array[vertex_clipped_by_distance] 2443e5c31af7Sopenharmony_ci << "])" << tcu::TestLog::EndMessage; 2444e5c31af7Sopenharmony_ci 2445e5c31af7Sopenharmony_ci TCU_FAIL("Vertex is expected to be clipped and invisible, while it is visible."); 2446e5c31af7Sopenharmony_ci } 2447e5c31af7Sopenharmony_ci else 2448e5c31af7Sopenharmony_ci { 2449e5c31af7Sopenharmony_ci n_clipped_vertices_real++; 2450e5c31af7Sopenharmony_ci } 2451e5c31af7Sopenharmony_ci } 2452e5c31af7Sopenharmony_ci else 2453e5c31af7Sopenharmony_ci { 2454e5c31af7Sopenharmony_ci if (vertex_color_red_value == 0) 2455e5c31af7Sopenharmony_ci { 2456e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "In primitive number [" << n_primitive_index << "] " 2457e5c31af7Sopenharmony_ci << "vertex at (" << checkpoint_x << "," << checkpoint_y << ") " 2458e5c31af7Sopenharmony_ci << "should not be clipped." << tcu::TestLog::EndMessage; 2459e5c31af7Sopenharmony_ci 2460e5c31af7Sopenharmony_ci TCU_FAIL("Vertex is unexpectedly clipped or invisible"); 2461e5c31af7Sopenharmony_ci } 2462e5c31af7Sopenharmony_ci } 2463e5c31af7Sopenharmony_ci } 2464e5c31af7Sopenharmony_ci 2465e5c31af7Sopenharmony_ci if (!all_vertices_are_clipped) 2466e5c31af7Sopenharmony_ci { 2467e5c31af7Sopenharmony_ci /* Check fetched values from the shader (Point 2 of Basic Outline : "Use program that...") */ 2468e5c31af7Sopenharmony_ci if (fetch_culldistance_from_fs) 2469e5c31af7Sopenharmony_ci { 2470e5c31af7Sopenharmony_ci for (glw::GLuint n_primitive_vertex = 0; n_primitive_vertex < primitive_vertices_count; 2471e5c31af7Sopenharmony_ci n_primitive_vertex++) 2472e5c31af7Sopenharmony_ci { 2473e5c31af7Sopenharmony_ci /* Get shader output value */ 2474e5c31af7Sopenharmony_ci glw::GLuint base_index_of_vertex_internal = 2475e5c31af7Sopenharmony_ci base_index_of_primitive + n_primitive_vertex * stride_in_floats; 2476e5c31af7Sopenharmony_ci glw::GLuint checkpoint_position_index_internal = 2477e5c31af7Sopenharmony_ci base_index_of_vertex_internal + clipdistances_array_size + culldistances_array_size + 2478e5c31af7Sopenharmony_ci 2 /* ignore vertex coordinates */; 2479e5c31af7Sopenharmony_ci glw::GLuint culldistances_index = base_index_of_vertex_internal + clipdistances_array_size; 2480e5c31af7Sopenharmony_ci glw::GLint checkpoint_x_internal = 2481e5c31af7Sopenharmony_ci glw::GLint(glw::GLfloat(m_to_width) * m_bo_data[checkpoint_position_index_internal]); 2482e5c31af7Sopenharmony_ci glw::GLint checkpoint_y_internal = 2483e5c31af7Sopenharmony_ci glw::GLint(glw::GLfloat(m_to_height) * m_bo_data[checkpoint_position_index_internal + 1]); 2484e5c31af7Sopenharmony_ci glw::GLint vertex_color_red_value = readRedPixelValue(checkpoint_x_internal, checkpoint_y_internal); 2485e5c31af7Sopenharmony_ci 2486e5c31af7Sopenharmony_ci /* Calculate culldistances check sum hash */ 2487e5c31af7Sopenharmony_ci float sum = 0.f; 2488e5c31af7Sopenharmony_ci 2489e5c31af7Sopenharmony_ci for (glw::GLuint n_clipdistance_entry = 0; n_clipdistance_entry < clipdistances_array_size; 2490e5c31af7Sopenharmony_ci ++n_clipdistance_entry) 2491e5c31af7Sopenharmony_ci { 2492e5c31af7Sopenharmony_ci sum += de::abs(m_bo_data[base_index_of_vertex_internal + n_clipdistance_entry]) * 2493e5c31af7Sopenharmony_ci float(n_clipdistance_entry + 1); 2494e5c31af7Sopenharmony_ci } 2495e5c31af7Sopenharmony_ci 2496e5c31af7Sopenharmony_ci for (glw::GLuint n_culldistance_entry = 0; n_culldistance_entry < culldistances_array_size; 2497e5c31af7Sopenharmony_ci ++n_culldistance_entry) 2498e5c31af7Sopenharmony_ci { 2499e5c31af7Sopenharmony_ci sum += de::abs(m_bo_data[culldistances_index + n_culldistance_entry]) * 2500e5c31af7Sopenharmony_ci float(n_culldistance_entry + 1 + clipdistances_array_size); 2501e5c31af7Sopenharmony_ci } 2502e5c31af7Sopenharmony_ci 2503e5c31af7Sopenharmony_ci /* limit sum and return */ 2504e5c31af7Sopenharmony_ci glw::GLint sum_hash = 2505e5c31af7Sopenharmony_ci glw::GLint(sum / glw::GLfloat((clipdistances_array_size + culldistances_array_size) * 2506e5c31af7Sopenharmony_ci (clipdistances_array_size + culldistances_array_size + 1)) * 2507e5c31af7Sopenharmony_ci 65535.f /* normalizing to short */); 2508e5c31af7Sopenharmony_ci sum_hash = (sum_hash < 65536) ? sum_hash : 65535; /* clamping to short */ 2509e5c31af7Sopenharmony_ci 2510e5c31af7Sopenharmony_ci /* Compare against setup value */ 2511e5c31af7Sopenharmony_ci if (std::abs(vertex_color_red_value - sum_hash) > 4 /* precision 4/65536 */) 2512e5c31af7Sopenharmony_ci { 2513e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Primitive number [" << n_primitive_index << "] " 2514e5c31af7Sopenharmony_ci << "should have culldistance hash sum " << sum_hash 2515e5c31af7Sopenharmony_ci << "but primitive vertex at (" << checkpoint_x << "," << checkpoint_y 2516e5c31af7Sopenharmony_ci << ") has sum hash equal to " << vertex_color_red_value 2517e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 2518e5c31af7Sopenharmony_ci 2519e5c31af7Sopenharmony_ci TCU_FAIL("Culled distances returned from fragment shader dose not match expected values."); 2520e5c31af7Sopenharmony_ci } 2521e5c31af7Sopenharmony_ci } 2522e5c31af7Sopenharmony_ci } 2523e5c31af7Sopenharmony_ci } 2524e5c31af7Sopenharmony_ci } 2525e5c31af7Sopenharmony_ci 2526e5c31af7Sopenharmony_ci /* sub_grid cell size is 3*3 */ 2527e5c31af7Sopenharmony_ci DE_ASSERT(m_render_primitives % 9 == 0); 2528e5c31af7Sopenharmony_ci 2529e5c31af7Sopenharmony_ci /* Quick check */ 2530e5c31af7Sopenharmony_ci switch (primitive_mode) 2531e5c31af7Sopenharmony_ci { 2532e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_LINES: 2533e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_TRIANGLES: 2534e5c31af7Sopenharmony_ci { 2535e5c31af7Sopenharmony_ci /* Validate culled primitives */ 2536e5c31af7Sopenharmony_ci if (culldistances_array_size == 0) 2537e5c31af7Sopenharmony_ci { 2538e5c31af7Sopenharmony_ci DE_ASSERT(n_culled_primitives_real == 0); 2539e5c31af7Sopenharmony_ci } 2540e5c31af7Sopenharmony_ci else 2541e5c31af7Sopenharmony_ci { 2542e5c31af7Sopenharmony_ci /* Each 3rd line or triangle should be culled by test design */ 2543e5c31af7Sopenharmony_ci DE_ASSERT(glw::GLsizei(n_culled_primitives_real) == m_render_primitives / 3); 2544e5c31af7Sopenharmony_ci } 2545e5c31af7Sopenharmony_ci 2546e5c31af7Sopenharmony_ci /* Validate clipped vertices */ 2547e5c31af7Sopenharmony_ci if (clipdistances_array_size == 0) 2548e5c31af7Sopenharmony_ci { 2549e5c31af7Sopenharmony_ci DE_ASSERT(n_clipped_vertices_real == 0); 2550e5c31af7Sopenharmony_ci } 2551e5c31af7Sopenharmony_ci else 2552e5c31af7Sopenharmony_ci { 2553e5c31af7Sopenharmony_ci#if defined(DE_DEBUG) && !defined(DE_COVERAGE_BUILD) 2554e5c31af7Sopenharmony_ci glw::GLint one_third_of_rendered_primitives = (m_render_primitives - n_culled_primitives_real) / 3; 2555e5c31af7Sopenharmony_ci glw::GLint n_clipped_vertices_expected = /* One third of primitives has 0th vertex clipped */ 2556e5c31af7Sopenharmony_ci one_third_of_rendered_primitives + 2557e5c31af7Sopenharmony_ci /* One third of primitives clipped completely */ 2558e5c31af7Sopenharmony_ci one_third_of_rendered_primitives * primitive_vertices_count; 2559e5c31af7Sopenharmony_ci 2560e5c31af7Sopenharmony_ci DE_ASSERT(glw::GLint(n_clipped_vertices_real) == n_clipped_vertices_expected); 2561e5c31af7Sopenharmony_ci#endif 2562e5c31af7Sopenharmony_ci } 2563e5c31af7Sopenharmony_ci break; 2564e5c31af7Sopenharmony_ci } 2565e5c31af7Sopenharmony_ci 2566e5c31af7Sopenharmony_ci case PRIMITIVE_MODE_POINTS: 2567e5c31af7Sopenharmony_ci { 2568e5c31af7Sopenharmony_ci /* Validate culled primitives */ 2569e5c31af7Sopenharmony_ci if (culldistances_array_size == 0) 2570e5c31af7Sopenharmony_ci { 2571e5c31af7Sopenharmony_ci DE_ASSERT(n_culled_primitives_real == 0); 2572e5c31af7Sopenharmony_ci } 2573e5c31af7Sopenharmony_ci else 2574e5c31af7Sopenharmony_ci { 2575e5c31af7Sopenharmony_ci /* 2/3 points should be culled by test design */ 2576e5c31af7Sopenharmony_ci DE_ASSERT(glw::GLsizei(n_culled_primitives_real) == m_render_primitives * 2 / 3); 2577e5c31af7Sopenharmony_ci } 2578e5c31af7Sopenharmony_ci 2579e5c31af7Sopenharmony_ci /* Validate clipped vertices */ 2580e5c31af7Sopenharmony_ci if (clipdistances_array_size == 0) 2581e5c31af7Sopenharmony_ci { 2582e5c31af7Sopenharmony_ci DE_ASSERT(n_clipped_vertices_real == 0); 2583e5c31af7Sopenharmony_ci } 2584e5c31af7Sopenharmony_ci else 2585e5c31af7Sopenharmony_ci { 2586e5c31af7Sopenharmony_ci#if defined(DE_DEBUG) && !defined(DE_COVERAGE_BUILD) 2587e5c31af7Sopenharmony_ci glw::GLint one_third_of_rendered_primitives = (m_render_primitives - n_culled_primitives_real) / 3; 2588e5c31af7Sopenharmony_ci 2589e5c31af7Sopenharmony_ci /* 2/3 of rendered points should be clipped by test design */ 2590e5c31af7Sopenharmony_ci DE_ASSERT(glw::GLint(n_clipped_vertices_real) == 2 * one_third_of_rendered_primitives); 2591e5c31af7Sopenharmony_ci#endif 2592e5c31af7Sopenharmony_ci } 2593e5c31af7Sopenharmony_ci 2594e5c31af7Sopenharmony_ci break; 2595e5c31af7Sopenharmony_ci } 2596e5c31af7Sopenharmony_ci default: 2597e5c31af7Sopenharmony_ci TCU_FAIL("Unknown primitive mode"); 2598e5c31af7Sopenharmony_ci } 2599e5c31af7Sopenharmony_ci} 2600e5c31af7Sopenharmony_ci 2601e5c31af7Sopenharmony_ci/** Executes test iteration. 2602e5c31af7Sopenharmony_ci * 2603e5c31af7Sopenharmony_ci * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 2604e5c31af7Sopenharmony_ci */ 2605e5c31af7Sopenharmony_citcu::TestNode::IterateResult CullDistance::FunctionalTest::iterate() 2606e5c31af7Sopenharmony_ci{ 2607e5c31af7Sopenharmony_ci /* This test should only be executed if ARB_cull_distance is supported, or if 2608e5c31af7Sopenharmony_ci * we're running a GL4.5 context 2609e5c31af7Sopenharmony_ci */ 2610e5c31af7Sopenharmony_ci if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_cull_distance") && 2611e5c31af7Sopenharmony_ci !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))) 2612e5c31af7Sopenharmony_ci { 2613e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("GL_ARB_cull_distance is not supported"); 2614e5c31af7Sopenharmony_ci } 2615e5c31af7Sopenharmony_ci 2616e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2617e5c31af7Sopenharmony_ci bool has_succeeded = true; 2618e5c31af7Sopenharmony_ci bool is_core = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)); 2619e5c31af7Sopenharmony_ci 2620e5c31af7Sopenharmony_ci /* Retrieve important GL constant values */ 2621e5c31af7Sopenharmony_ci glw::GLint gl_max_clip_distances_value = 0; 2622e5c31af7Sopenharmony_ci glw::GLint gl_max_combined_clip_and_cull_distances_value = 0; 2623e5c31af7Sopenharmony_ci glw::GLint gl_max_cull_distances_value = 0; 2624e5c31af7Sopenharmony_ci 2625e5c31af7Sopenharmony_ci gl.getIntegerv(GL_MAX_CLIP_DISTANCES, &gl_max_clip_distances_value); 2626e5c31af7Sopenharmony_ci gl.getIntegerv(GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES, &gl_max_combined_clip_and_cull_distances_value); 2627e5c31af7Sopenharmony_ci gl.getIntegerv(GL_MAX_CULL_DISTANCES, &gl_max_cull_distances_value); 2628e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call(s) failed."); 2629e5c31af7Sopenharmony_ci 2630e5c31af7Sopenharmony_ci gl.genTextures(1, &m_to_id); 2631e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed."); 2632e5c31af7Sopenharmony_ci 2633e5c31af7Sopenharmony_ci gl.bindTexture(GL_TEXTURE_2D, m_to_id); 2634e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); 2635e5c31af7Sopenharmony_ci 2636e5c31af7Sopenharmony_ci gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */ 2637e5c31af7Sopenharmony_ci GL_R32F, m_to_width, m_to_height); 2638e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed."); 2639e5c31af7Sopenharmony_ci 2640e5c31af7Sopenharmony_ci /* Set up the draw/read FBO */ 2641e5c31af7Sopenharmony_ci gl.genFramebuffers(1, &m_fbo_id); 2642e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed."); 2643e5c31af7Sopenharmony_ci 2644e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 2645e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed."); 2646e5c31af7Sopenharmony_ci 2647e5c31af7Sopenharmony_ci gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0); /* level */ 2648e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed."); 2649e5c31af7Sopenharmony_ci 2650e5c31af7Sopenharmony_ci /* Prepare a buffer object */ 2651e5c31af7Sopenharmony_ci gl.genBuffers(1, &m_bo_id); 2652e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); 2653e5c31af7Sopenharmony_ci 2654e5c31af7Sopenharmony_ci /* Prepare a VAO. We will configure separately for each iteration. */ 2655e5c31af7Sopenharmony_ci gl.genVertexArrays(1, &m_vao_id); 2656e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed."); 2657e5c31af7Sopenharmony_ci 2658e5c31af7Sopenharmony_ci /* Iterate over all functional tests */ 2659e5c31af7Sopenharmony_ci struct _test_item 2660e5c31af7Sopenharmony_ci { 2661e5c31af7Sopenharmony_ci bool redeclare_clipdistances_array; 2662e5c31af7Sopenharmony_ci bool redeclare_culldistances_array; 2663e5c31af7Sopenharmony_ci bool dynamic_index_writes; 2664e5c31af7Sopenharmony_ci bool use_passthrough_gs; 2665e5c31af7Sopenharmony_ci bool use_passthrough_ts; 2666e5c31af7Sopenharmony_ci bool use_core_functionality; 2667e5c31af7Sopenharmony_ci bool fetch_culldistances; 2668e5c31af7Sopenharmony_ci } test_items[] = { /* Use the basic outline to test the basic functionality of cull distances. */ 2669e5c31af7Sopenharmony_ci { 2670e5c31af7Sopenharmony_ci true, /* redeclare_clipdistances_array */ 2671e5c31af7Sopenharmony_ci true, /* redeclare_culldistances_array */ 2672e5c31af7Sopenharmony_ci false, /* dynamic_index_writes */ 2673e5c31af7Sopenharmony_ci false, /* use_passthrough_gs */ 2674e5c31af7Sopenharmony_ci false, /* use_passthrough_ts */ 2675e5c31af7Sopenharmony_ci is_core, /* use_core_functionality */ 2676e5c31af7Sopenharmony_ci false /* fetch_culldistances */ 2677e5c31af7Sopenharmony_ci }, 2678e5c31af7Sopenharmony_ci /* Use the basic outline but don't redeclare gl_ClipDistance with a size. */ 2679e5c31af7Sopenharmony_ci { 2680e5c31af7Sopenharmony_ci false, /* redeclare_clipdistances_array */ 2681e5c31af7Sopenharmony_ci true, /* redeclare_culldistances_array */ 2682e5c31af7Sopenharmony_ci false, /* dynamic_index_writes */ 2683e5c31af7Sopenharmony_ci false, /* use_passthrough_gs */ 2684e5c31af7Sopenharmony_ci false, /* use_passthrough_ts */ 2685e5c31af7Sopenharmony_ci is_core, /* use_core_functionality */ 2686e5c31af7Sopenharmony_ci false /* fetch_culldistances */ 2687e5c31af7Sopenharmony_ci }, 2688e5c31af7Sopenharmony_ci /* Use the basic outline but don't redeclare gl_CullDistance with a size. */ 2689e5c31af7Sopenharmony_ci { 2690e5c31af7Sopenharmony_ci true, /* redeclare_clipdistances_array */ 2691e5c31af7Sopenharmony_ci false, /* redeclare_culldistances_array */ 2692e5c31af7Sopenharmony_ci false, /* dynamic_index_writes */ 2693e5c31af7Sopenharmony_ci false, /* use_passthrough_gs */ 2694e5c31af7Sopenharmony_ci false, /* use_passthrough_ts */ 2695e5c31af7Sopenharmony_ci is_core, /* use_core_functionality */ 2696e5c31af7Sopenharmony_ci false /* fetch_culldistances */ 2697e5c31af7Sopenharmony_ci }, 2698e5c31af7Sopenharmony_ci /* Use the basic outline but don't redeclare either gl_ClipDistance or 2699e5c31af7Sopenharmony_ci * gl_CullDistance with a size. 2700e5c31af7Sopenharmony_ci */ 2701e5c31af7Sopenharmony_ci { 2702e5c31af7Sopenharmony_ci false, /* redeclare_clipdistances_array */ 2703e5c31af7Sopenharmony_ci false, /* redeclare_culldistances_array */ 2704e5c31af7Sopenharmony_ci false, /* dynamic_index_writes */ 2705e5c31af7Sopenharmony_ci false, /* use_passthrough_gs */ 2706e5c31af7Sopenharmony_ci false, /* use_passthrough_ts */ 2707e5c31af7Sopenharmony_ci is_core, /* use_core_functionality */ 2708e5c31af7Sopenharmony_ci false /* fetch_culldistances */ 2709e5c31af7Sopenharmony_ci }, 2710e5c31af7Sopenharmony_ci /* Use the basic outline but use dynamic indexing when writing the elements 2711e5c31af7Sopenharmony_ci * of the gl_ClipDistance and gl_CullDistance arrays. 2712e5c31af7Sopenharmony_ci */ 2713e5c31af7Sopenharmony_ci { 2714e5c31af7Sopenharmony_ci true, /* redeclare_clipdistances_array */ 2715e5c31af7Sopenharmony_ci true, /* redeclare_culldistances_array */ 2716e5c31af7Sopenharmony_ci true, /* dynamic_index_writes */ 2717e5c31af7Sopenharmony_ci false, /* use_passthrough_gs */ 2718e5c31af7Sopenharmony_ci false, /* use_passthrough_ts */ 2719e5c31af7Sopenharmony_ci is_core, /* use_core_functionality */ 2720e5c31af7Sopenharmony_ci false /* fetch_culldistances */ 2721e5c31af7Sopenharmony_ci }, 2722e5c31af7Sopenharmony_ci /* Use the basic outline but add a geometry shader to the program that 2723e5c31af7Sopenharmony_ci * simply passes through all written clip and cull distances. 2724e5c31af7Sopenharmony_ci */ 2725e5c31af7Sopenharmony_ci { 2726e5c31af7Sopenharmony_ci true, /* redeclare_clipdistances_array */ 2727e5c31af7Sopenharmony_ci true, /* redeclare_culldistances_array */ 2728e5c31af7Sopenharmony_ci false, /* dynamic_index_writes */ 2729e5c31af7Sopenharmony_ci true, /* use_passthrough_gs */ 2730e5c31af7Sopenharmony_ci false, /* use_passthrough_ts */ 2731e5c31af7Sopenharmony_ci is_core, /* use_core_functionality */ 2732e5c31af7Sopenharmony_ci false /* fetch_culldistances */ 2733e5c31af7Sopenharmony_ci }, 2734e5c31af7Sopenharmony_ci /* Use the basic outline but add a tessellation control and tessellation 2735e5c31af7Sopenharmony_ci * evaluation shader to the program which simply pass through all written 2736e5c31af7Sopenharmony_ci * clip and cull distances. 2737e5c31af7Sopenharmony_ci */ 2738e5c31af7Sopenharmony_ci { 2739e5c31af7Sopenharmony_ci true, /* redeclare_clipdistances_array */ 2740e5c31af7Sopenharmony_ci true, /* redeclare_culldistances_array */ 2741e5c31af7Sopenharmony_ci false, /* dynamic_index_writes */ 2742e5c31af7Sopenharmony_ci false, /* use_passthrough_gs */ 2743e5c31af7Sopenharmony_ci true, /* use_passthrough_ts */ 2744e5c31af7Sopenharmony_ci is_core, /* use_core_functionality */ 2745e5c31af7Sopenharmony_ci false /* fetch_culldistances */ 2746e5c31af7Sopenharmony_ci }, 2747e5c31af7Sopenharmony_ci /* Test that using #extension with GL_ARB_cull_distance allows using the 2748e5c31af7Sopenharmony_ci * feature even with an earlier version of GLSL. Also test that the 2749e5c31af7Sopenharmony_ci * extension name is available as preprocessor #define. 2750e5c31af7Sopenharmony_ci */ 2751e5c31af7Sopenharmony_ci { 2752e5c31af7Sopenharmony_ci true, /* redeclare_clipdistances_array */ 2753e5c31af7Sopenharmony_ci true, /* redeclare_culldistances_array */ 2754e5c31af7Sopenharmony_ci false, /* dynamic_index_writes */ 2755e5c31af7Sopenharmony_ci false, /* use_passthrough_gs */ 2756e5c31af7Sopenharmony_ci false, /* use_passthrough_ts */ 2757e5c31af7Sopenharmony_ci false, /* use_core_functionality */ 2758e5c31af7Sopenharmony_ci false /* fetch_culldistances */ 2759e5c31af7Sopenharmony_ci }, 2760e5c31af7Sopenharmony_ci /* Use a program that has only a vertex shader and a fragment shader. 2761e5c31af7Sopenharmony_ci * The vertex shader should redeclare gl_ClipDistance with a size that 2762e5c31af7Sopenharmony_ci * fits all enabled cull distances. Also redeclare gl_CullDistance with a 2763e5c31af7Sopenharmony_ci * size. The sum of the two sizes should not be more than MAX_COMBINED_- 2764e5c31af7Sopenharmony_ci * CLIP_AND_CULL_DISTANCES. The fragment shader should output the cull 2765e5c31af7Sopenharmony_ci * distances written by the vertex shader by reading them from the built-in 2766e5c31af7Sopenharmony_ci * array gl_CullDistance. 2767e5c31af7Sopenharmony_ci */ 2768e5c31af7Sopenharmony_ci { 2769e5c31af7Sopenharmony_ci true, /* redeclare_clipdistances_array */ 2770e5c31af7Sopenharmony_ci true, /* redeclare_culldistances_array */ 2771e5c31af7Sopenharmony_ci false, /* dynamic_index_writes */ 2772e5c31af7Sopenharmony_ci false, /* use_passthrough_gs */ 2773e5c31af7Sopenharmony_ci false, /* use_passthrough_ts */ 2774e5c31af7Sopenharmony_ci false, /* use_core_functionality */ 2775e5c31af7Sopenharmony_ci true /* fetch_culldistances */ 2776e5c31af7Sopenharmony_ci } 2777e5c31af7Sopenharmony_ci }; 2778e5c31af7Sopenharmony_ci const glw::GLuint n_test_items = sizeof(test_items) / sizeof(test_items[0]); 2779e5c31af7Sopenharmony_ci 2780e5c31af7Sopenharmony_ci gl.viewport(0, 0, m_to_width, m_to_height); 2781e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed."); 2782e5c31af7Sopenharmony_ci 2783e5c31af7Sopenharmony_ci gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 2784e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed."); 2785e5c31af7Sopenharmony_ci 2786e5c31af7Sopenharmony_ci for (glw::GLuint n_test_item = 0; n_test_item < n_test_items; ++n_test_item) 2787e5c31af7Sopenharmony_ci { 2788e5c31af7Sopenharmony_ci /* Check for OpenGL feature support */ 2789e5c31af7Sopenharmony_ci if (test_items[n_test_item].use_passthrough_ts) 2790e5c31af7Sopenharmony_ci { 2791e5c31af7Sopenharmony_ci if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)) && 2792e5c31af7Sopenharmony_ci !m_context.getContextInfo().isExtensionSupported("GL_ARB_tessellation_shader")) 2793e5c31af7Sopenharmony_ci { 2794e5c31af7Sopenharmony_ci continue; // no tessellation shader support 2795e5c31af7Sopenharmony_ci } 2796e5c31af7Sopenharmony_ci } 2797e5c31af7Sopenharmony_ci 2798e5c31af7Sopenharmony_ci const _test_item& current_test_item = test_items[n_test_item]; 2799e5c31af7Sopenharmony_ci const _primitive_mode primitive_modes[PRIMITIVE_MODE_COUNT] = { PRIMITIVE_MODE_LINES, PRIMITIVE_MODE_POINTS, 2800e5c31af7Sopenharmony_ci PRIMITIVE_MODE_TRIANGLES }; 2801e5c31af7Sopenharmony_ci 2802e5c31af7Sopenharmony_ci for (glw::GLuint primitive_mode_index = 0; primitive_mode_index < PRIMITIVE_MODE_COUNT; ++primitive_mode_index) 2803e5c31af7Sopenharmony_ci { 2804e5c31af7Sopenharmony_ci _primitive_mode primitive_mode = primitive_modes[primitive_mode_index]; 2805e5c31af7Sopenharmony_ci 2806e5c31af7Sopenharmony_ci /* Iterate over a set of gl_ClipDistances[] and gl_CullDistances[] array sizes */ 2807e5c31af7Sopenharmony_ci for (glw::GLint n_iteration = 0; n_iteration <= gl_max_combined_clip_and_cull_distances_value; 2808e5c31af7Sopenharmony_ci ++n_iteration) 2809e5c31af7Sopenharmony_ci { 2810e5c31af7Sopenharmony_ci glw::GLuint clipdistances_array_size = 0; 2811e5c31af7Sopenharmony_ci glw::GLuint culldistances_array_size = 0; 2812e5c31af7Sopenharmony_ci 2813e5c31af7Sopenharmony_ci if (n_iteration != 0 && n_iteration <= gl_max_clip_distances_value) 2814e5c31af7Sopenharmony_ci { 2815e5c31af7Sopenharmony_ci clipdistances_array_size = n_iteration; 2816e5c31af7Sopenharmony_ci } 2817e5c31af7Sopenharmony_ci 2818e5c31af7Sopenharmony_ci if ((gl_max_combined_clip_and_cull_distances_value - n_iteration) < gl_max_cull_distances_value) 2819e5c31af7Sopenharmony_ci { 2820e5c31af7Sopenharmony_ci culldistances_array_size = gl_max_combined_clip_and_cull_distances_value - n_iteration; 2821e5c31af7Sopenharmony_ci } 2822e5c31af7Sopenharmony_ci else 2823e5c31af7Sopenharmony_ci { 2824e5c31af7Sopenharmony_ci culldistances_array_size = gl_max_cull_distances_value; 2825e5c31af7Sopenharmony_ci } 2826e5c31af7Sopenharmony_ci 2827e5c31af7Sopenharmony_ci if (clipdistances_array_size == 0 && culldistances_array_size == 0) 2828e5c31af7Sopenharmony_ci { 2829e5c31af7Sopenharmony_ci /* Skip the empty iteration */ 2830e5c31af7Sopenharmony_ci continue; 2831e5c31af7Sopenharmony_ci } 2832e5c31af7Sopenharmony_ci 2833e5c31af7Sopenharmony_ci if (current_test_item.fetch_culldistances && (primitive_mode != PRIMITIVE_MODE_POINTS)) 2834e5c31af7Sopenharmony_ci { 2835e5c31af7Sopenharmony_ci continue; 2836e5c31af7Sopenharmony_ci } 2837e5c31af7Sopenharmony_ci 2838e5c31af7Sopenharmony_ci /* Create a program to run */ 2839e5c31af7Sopenharmony_ci buildPO(clipdistances_array_size, culldistances_array_size, current_test_item.dynamic_index_writes, 2840e5c31af7Sopenharmony_ci primitive_mode, current_test_item.redeclare_clipdistances_array, 2841e5c31af7Sopenharmony_ci current_test_item.redeclare_culldistances_array, current_test_item.use_core_functionality, 2842e5c31af7Sopenharmony_ci current_test_item.use_passthrough_gs, current_test_item.use_passthrough_ts, 2843e5c31af7Sopenharmony_ci current_test_item.fetch_culldistances); 2844e5c31af7Sopenharmony_ci 2845e5c31af7Sopenharmony_ci /* Initialize VAO data */ 2846e5c31af7Sopenharmony_ci configureVAO(clipdistances_array_size, culldistances_array_size, primitive_mode); 2847e5c31af7Sopenharmony_ci 2848e5c31af7Sopenharmony_ci /* Run GLSL program and check results */ 2849e5c31af7Sopenharmony_ci executeRenderTest(clipdistances_array_size, culldistances_array_size, primitive_mode, 2850e5c31af7Sopenharmony_ci current_test_item.use_passthrough_ts, current_test_item.fetch_culldistances); 2851e5c31af7Sopenharmony_ci 2852e5c31af7Sopenharmony_ci } /* for (all iterations) */ 2853e5c31af7Sopenharmony_ci } /* for (all test modes) */ 2854e5c31af7Sopenharmony_ci } /* for (all test items) */ 2855e5c31af7Sopenharmony_ci 2856e5c31af7Sopenharmony_ci /* All done */ 2857e5c31af7Sopenharmony_ci if (has_succeeded) 2858e5c31af7Sopenharmony_ci { 2859e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2860e5c31af7Sopenharmony_ci } 2861e5c31af7Sopenharmony_ci else 2862e5c31af7Sopenharmony_ci { 2863e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 2864e5c31af7Sopenharmony_ci } 2865e5c31af7Sopenharmony_ci 2866e5c31af7Sopenharmony_ci return STOP; 2867e5c31af7Sopenharmony_ci} 2868e5c31af7Sopenharmony_ci 2869e5c31af7Sopenharmony_ci/** Returns pixel red component read from texture at position x, y. 2870e5c31af7Sopenharmony_ci * 2871e5c31af7Sopenharmony_ci * @param x x-coordinate to read pixel color component from 2872e5c31af7Sopenharmony_ci * @param y y-coordinate to read pixel color component from 2873e5c31af7Sopenharmony_ci **/ 2874e5c31af7Sopenharmony_ciglw::GLint CullDistance::FunctionalTest::readRedPixelValue(glw::GLint x, glw::GLint y) 2875e5c31af7Sopenharmony_ci{ 2876e5c31af7Sopenharmony_ci glw::GLint result = -1; 2877e5c31af7Sopenharmony_ci 2878e5c31af7Sopenharmony_ci DE_ASSERT(x >= 0 && (glw::GLuint)x < m_to_width); 2879e5c31af7Sopenharmony_ci DE_ASSERT(y >= 0 && (glw::GLuint)y < m_to_height); 2880e5c31af7Sopenharmony_ci 2881e5c31af7Sopenharmony_ci result = m_to_pixel_data_cache[(m_to_width * y + x) * m_to_pixel_data_cache_color_components]; 2882e5c31af7Sopenharmony_ci 2883e5c31af7Sopenharmony_ci return result; 2884e5c31af7Sopenharmony_ci} 2885e5c31af7Sopenharmony_ci 2886e5c31af7Sopenharmony_ci/** Reads texture into m_to_pixel_data_cache. 2887e5c31af7Sopenharmony_ci * Texture size determined by fields m_to_width, m_to_height 2888e5c31af7Sopenharmony_ci **/ 2889e5c31af7Sopenharmony_civoid CullDistance::FunctionalTest::readTexturePixels() 2890e5c31af7Sopenharmony_ci{ 2891e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2892e5c31af7Sopenharmony_ci 2893e5c31af7Sopenharmony_ci m_to_pixel_data_cache.clear(); 2894e5c31af7Sopenharmony_ci 2895e5c31af7Sopenharmony_ci m_to_pixel_data_cache.resize(m_to_width * m_to_height * m_to_pixel_data_cache_color_components); 2896e5c31af7Sopenharmony_ci 2897e5c31af7Sopenharmony_ci /* Read vertex from texture */ 2898e5c31af7Sopenharmony_ci gl.readPixels(0, /* x */ 2899e5c31af7Sopenharmony_ci 0, /* y */ 2900e5c31af7Sopenharmony_ci m_to_width, /* width */ 2901e5c31af7Sopenharmony_ci m_to_height, /* height */ 2902e5c31af7Sopenharmony_ci GL_RGBA, GL_UNSIGNED_SHORT, &m_to_pixel_data_cache[0]); 2903e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed."); 2904e5c31af7Sopenharmony_ci} 2905e5c31af7Sopenharmony_ci 2906e5c31af7Sopenharmony_ci/** Constructor. 2907e5c31af7Sopenharmony_ci * 2908e5c31af7Sopenharmony_ci * @param context Rendering context handle. 2909e5c31af7Sopenharmony_ci **/ 2910e5c31af7Sopenharmony_ciCullDistance::NegativeTest::NegativeTest(deqp::Context& context) 2911e5c31af7Sopenharmony_ci : TestCase(context, "negative", "Cull Distance Negative Test") 2912e5c31af7Sopenharmony_ci , m_fs_id(0) 2913e5c31af7Sopenharmony_ci , m_po_id(0) 2914e5c31af7Sopenharmony_ci , m_temp_buffer(DE_NULL) 2915e5c31af7Sopenharmony_ci , m_vs_id(0) 2916e5c31af7Sopenharmony_ci{ 2917e5c31af7Sopenharmony_ci /* Left blank on purpose */ 2918e5c31af7Sopenharmony_ci} 2919e5c31af7Sopenharmony_ci 2920e5c31af7Sopenharmony_ci/** @brief Cull Distance Negative Test deinitialization */ 2921e5c31af7Sopenharmony_civoid CullDistance::NegativeTest::deinit() 2922e5c31af7Sopenharmony_ci{ 2923e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2924e5c31af7Sopenharmony_ci 2925e5c31af7Sopenharmony_ci if (m_fs_id != 0) 2926e5c31af7Sopenharmony_ci { 2927e5c31af7Sopenharmony_ci gl.deleteShader(m_fs_id); 2928e5c31af7Sopenharmony_ci 2929e5c31af7Sopenharmony_ci m_fs_id = 0; 2930e5c31af7Sopenharmony_ci } 2931e5c31af7Sopenharmony_ci 2932e5c31af7Sopenharmony_ci if (m_po_id != 0) 2933e5c31af7Sopenharmony_ci { 2934e5c31af7Sopenharmony_ci gl.deleteProgram(m_po_id); 2935e5c31af7Sopenharmony_ci 2936e5c31af7Sopenharmony_ci m_po_id = 0; 2937e5c31af7Sopenharmony_ci } 2938e5c31af7Sopenharmony_ci 2939e5c31af7Sopenharmony_ci if (m_vs_id != 0) 2940e5c31af7Sopenharmony_ci { 2941e5c31af7Sopenharmony_ci gl.deleteShader(m_vs_id); 2942e5c31af7Sopenharmony_ci 2943e5c31af7Sopenharmony_ci m_vs_id = 0; 2944e5c31af7Sopenharmony_ci } 2945e5c31af7Sopenharmony_ci 2946e5c31af7Sopenharmony_ci if (m_temp_buffer != DE_NULL) 2947e5c31af7Sopenharmony_ci { 2948e5c31af7Sopenharmony_ci delete[] m_temp_buffer; 2949e5c31af7Sopenharmony_ci 2950e5c31af7Sopenharmony_ci m_temp_buffer = DE_NULL; 2951e5c31af7Sopenharmony_ci } 2952e5c31af7Sopenharmony_ci} 2953e5c31af7Sopenharmony_ci 2954e5c31af7Sopenharmony_ci/** @brief Get string description of test with given parameters 2955e5c31af7Sopenharmony_ci * 2956e5c31af7Sopenharmony_ci * @param [in] n_test_iteration Test iteration number 2957e5c31af7Sopenharmony_ci * @param [in] should_redeclare_output_variables Indicate whether test redeclared gl_ClipDistance and gl_CullDistance 2958e5c31af7Sopenharmony_ci * @param [in] use_dynamic_index_based_writes Indicate whether test used dynamic index-based setters 2959e5c31af7Sopenharmony_ci * 2960e5c31af7Sopenharmony_ci * @return String containing description. 2961e5c31af7Sopenharmony_ci */ 2962e5c31af7Sopenharmony_cistd::string CullDistance::NegativeTest::getTestDescription(int n_test_iteration, bool should_redeclare_output_variables, 2963e5c31af7Sopenharmony_ci bool use_dynamic_index_based_writes) 2964e5c31af7Sopenharmony_ci{ 2965e5c31af7Sopenharmony_ci std::stringstream stream; 2966e5c31af7Sopenharmony_ci 2967e5c31af7Sopenharmony_ci stream << "Test iteration [" << n_test_iteration << "] which uses a vertex shader that:\n\n" 2968e5c31af7Sopenharmony_ci << ((should_redeclare_output_variables) ? 2969e5c31af7Sopenharmony_ci "* redeclares gl_ClipDistance and gl_CullDistance arrays\n" : 2970e5c31af7Sopenharmony_ci "* does not redeclare gl_ClipDistance and gl_CullDistance arrays\n") 2971e5c31af7Sopenharmony_ci << ((use_dynamic_index_based_writes) ? "* uses dynamic index-based writes\n" : "* uses static writes\n"); 2972e5c31af7Sopenharmony_ci 2973e5c31af7Sopenharmony_ci return stream.str(); 2974e5c31af7Sopenharmony_ci} 2975e5c31af7Sopenharmony_ci 2976e5c31af7Sopenharmony_ci/** Executes test iteration. 2977e5c31af7Sopenharmony_ci * 2978e5c31af7Sopenharmony_ci * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 2979e5c31af7Sopenharmony_ci */ 2980e5c31af7Sopenharmony_citcu::TestNode::IterateResult CullDistance::NegativeTest::iterate() 2981e5c31af7Sopenharmony_ci{ 2982e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2983e5c31af7Sopenharmony_ci 2984e5c31af7Sopenharmony_ci /* Build the test shaders. */ 2985e5c31af7Sopenharmony_ci const glw::GLchar* token_dynamic_index_based_writes = "DYNAMIC_INDEX_BASED_WRITES"; 2986e5c31af7Sopenharmony_ci const glw::GLchar* token_insert_static_writes = "INSERT_STATIC_WRITES"; 2987e5c31af7Sopenharmony_ci const glw::GLchar* token_n_gl_clipdistance_entries = "N_GL_CLIPDISTANCE_ENTRIES"; 2988e5c31af7Sopenharmony_ci const glw::GLchar* token_n_gl_culldistance_entries = "N_GL_CULLDISTANCE_ENTRIES"; 2989e5c31af7Sopenharmony_ci const glw::GLchar* token_redeclare_output_variables = "REDECLARE_OUTPUT_VARIABLES"; 2990e5c31af7Sopenharmony_ci 2991e5c31af7Sopenharmony_ci const glw::GLchar* fs_body = "#version 130\n" 2992e5c31af7Sopenharmony_ci "\n" 2993e5c31af7Sopenharmony_ci "void main()\n" 2994e5c31af7Sopenharmony_ci "{\n" 2995e5c31af7Sopenharmony_ci "}\n"; 2996e5c31af7Sopenharmony_ci 2997e5c31af7Sopenharmony_ci const glw::GLchar* vs_body_preamble = "#version 130\n" 2998e5c31af7Sopenharmony_ci "\n" 2999e5c31af7Sopenharmony_ci " #extension GL_ARB_cull_distance : require\n" 3000e5c31af7Sopenharmony_ci "\n"; 3001e5c31af7Sopenharmony_ci 3002e5c31af7Sopenharmony_ci const glw::GLchar* vs_body_main = "#ifdef REDECLARE_OUTPUT_VARIABLES\n" 3003e5c31af7Sopenharmony_ci " out float gl_ClipDistance[N_GL_CLIPDISTANCE_ENTRIES];\n" 3004e5c31af7Sopenharmony_ci " out float gl_CullDistance[N_GL_CULLDISTANCE_ENTRIES];\n" 3005e5c31af7Sopenharmony_ci "#endif\n" 3006e5c31af7Sopenharmony_ci "\n" 3007e5c31af7Sopenharmony_ci "void main()\n" 3008e5c31af7Sopenharmony_ci "{\n" 3009e5c31af7Sopenharmony_ci "#ifdef DYNAMIC_INDEX_BASED_WRITES\n" 3010e5c31af7Sopenharmony_ci " for (int n_clipdistance_entry = 0;\n" 3011e5c31af7Sopenharmony_ci " n_clipdistance_entry < N_GL_CLIPDISTANCE_ENTRIES;\n" 3012e5c31af7Sopenharmony_ci " ++n_clipdistance_entry)\n" 3013e5c31af7Sopenharmony_ci " {\n" 3014e5c31af7Sopenharmony_ci " gl_ClipDistance[n_clipdistance_entry] = float(n_clipdistance_entry) / " 3015e5c31af7Sopenharmony_ci "float(N_GL_CLIPDISTANCE_ENTRIES);\n" 3016e5c31af7Sopenharmony_ci " }\n" 3017e5c31af7Sopenharmony_ci "\n" 3018e5c31af7Sopenharmony_ci " for (int n_culldistance_entry = 0;\n" 3019e5c31af7Sopenharmony_ci " n_culldistance_entry < N_GL_CULLDISTANCE_ENTRIES;\n" 3020e5c31af7Sopenharmony_ci " ++n_culldistance_entry)\n" 3021e5c31af7Sopenharmony_ci " {\n" 3022e5c31af7Sopenharmony_ci " gl_CullDistance[n_culldistance_entry] = float(n_culldistance_entry) / " 3023e5c31af7Sopenharmony_ci "float(N_GL_CULLDISTANCE_ENTRIES);\n" 3024e5c31af7Sopenharmony_ci " }\n" 3025e5c31af7Sopenharmony_ci "#else\n" 3026e5c31af7Sopenharmony_ci " INSERT_STATIC_WRITES\n" 3027e5c31af7Sopenharmony_ci "#endif\n" 3028e5c31af7Sopenharmony_ci "}\n"; 3029e5c31af7Sopenharmony_ci 3030e5c31af7Sopenharmony_ci /* This test should only be executed if ARB_cull_distance is supported, or if 3031e5c31af7Sopenharmony_ci * we're running a GL4.5 context 3032e5c31af7Sopenharmony_ci */ 3033e5c31af7Sopenharmony_ci if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_cull_distance") && 3034e5c31af7Sopenharmony_ci !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))) 3035e5c31af7Sopenharmony_ci { 3036e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("GL_ARB_cull_distance is not supported"); 3037e5c31af7Sopenharmony_ci } 3038e5c31af7Sopenharmony_ci 3039e5c31af7Sopenharmony_ci /* It only makes sense to run this test if GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 3040e5c31af7Sopenharmony_ci * is lower than a sum of GL_MAX_CLIP_DISTANCES and GL_MAX_CLIP_CULL_DISTANCES. 3041e5c31af7Sopenharmony_ci */ 3042e5c31af7Sopenharmony_ci glw::GLint gl_max_clip_distances_value = 0; 3043e5c31af7Sopenharmony_ci glw::GLint gl_max_combined_clip_and_cull_distances_value = 0; 3044e5c31af7Sopenharmony_ci glw::GLint gl_max_cull_distances_value = 0; 3045e5c31af7Sopenharmony_ci glw::GLuint n_gl_clipdistance_array_items = 0; 3046e5c31af7Sopenharmony_ci std::string n_gl_clipdistance_array_items_string; 3047e5c31af7Sopenharmony_ci glw::GLuint n_gl_culldistance_array_items = 0; 3048e5c31af7Sopenharmony_ci std::string n_gl_culldistance_array_items_string; 3049e5c31af7Sopenharmony_ci std::string static_write_shader_body_part; 3050e5c31af7Sopenharmony_ci 3051e5c31af7Sopenharmony_ci gl.getIntegerv(GL_MAX_CLIP_DISTANCES, &gl_max_clip_distances_value); 3052e5c31af7Sopenharmony_ci gl.getIntegerv(GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES, &gl_max_combined_clip_and_cull_distances_value); 3053e5c31af7Sopenharmony_ci gl.getIntegerv(GL_MAX_CULL_DISTANCES, &gl_max_cull_distances_value); 3054e5c31af7Sopenharmony_ci 3055e5c31af7Sopenharmony_ci if (gl_max_clip_distances_value + gl_max_cull_distances_value < gl_max_combined_clip_and_cull_distances_value) 3056e5c31af7Sopenharmony_ci { 3057e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 3058e5c31af7Sopenharmony_ci << "GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES is larger than or equal to " 3059e5c31af7Sopenharmony_ci "the sum of GL_MAX_CLIP_DISTANCES and GL_MAX_CULL_DISTANCES. Skipping." 3060e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 3061e5c31af7Sopenharmony_ci 3062e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3063e5c31af7Sopenharmony_ci 3064e5c31af7Sopenharmony_ci return STOP; 3065e5c31af7Sopenharmony_ci } 3066e5c31af7Sopenharmony_ci 3067e5c31af7Sopenharmony_ci n_gl_clipdistance_array_items = gl_max_clip_distances_value; 3068e5c31af7Sopenharmony_ci n_gl_culldistance_array_items = gl_max_combined_clip_and_cull_distances_value - gl_max_clip_distances_value + 1; 3069e5c31af7Sopenharmony_ci 3070e5c31af7Sopenharmony_ci /* Determine the number of items we will want the gl_ClipDistance and gl_CullDistance arrays 3071e5c31af7Sopenharmony_ci * to hold for test iterations that will re-declare the built-in output variables. 3072e5c31af7Sopenharmony_ci */ 3073e5c31af7Sopenharmony_ci { 3074e5c31af7Sopenharmony_ci std::stringstream temp_sstream; 3075e5c31af7Sopenharmony_ci 3076e5c31af7Sopenharmony_ci temp_sstream << n_gl_clipdistance_array_items; 3077e5c31af7Sopenharmony_ci 3078e5c31af7Sopenharmony_ci n_gl_clipdistance_array_items_string = temp_sstream.str(); 3079e5c31af7Sopenharmony_ci } 3080e5c31af7Sopenharmony_ci 3081e5c31af7Sopenharmony_ci { 3082e5c31af7Sopenharmony_ci std::stringstream temp_sstream; 3083e5c31af7Sopenharmony_ci 3084e5c31af7Sopenharmony_ci temp_sstream << n_gl_culldistance_array_items; 3085e5c31af7Sopenharmony_ci 3086e5c31af7Sopenharmony_ci n_gl_culldistance_array_items_string = temp_sstream.str(); 3087e5c31af7Sopenharmony_ci } 3088e5c31af7Sopenharmony_ci 3089e5c31af7Sopenharmony_ci /* Form the "static write" shader body part. */ 3090e5c31af7Sopenharmony_ci { 3091e5c31af7Sopenharmony_ci std::stringstream temp_sstream; 3092e5c31af7Sopenharmony_ci 3093e5c31af7Sopenharmony_ci temp_sstream << "gl_ClipDistance[" << n_gl_clipdistance_array_items_string.c_str() << "] = 0.0f;\n" 3094e5c31af7Sopenharmony_ci << "gl_CullDistance[" << n_gl_culldistance_array_items_string.c_str() << "] = 0.0f;\n"; 3095e5c31af7Sopenharmony_ci 3096e5c31af7Sopenharmony_ci static_write_shader_body_part = temp_sstream.str(); 3097e5c31af7Sopenharmony_ci } 3098e5c31af7Sopenharmony_ci 3099e5c31af7Sopenharmony_ci /* Prepare GL objects before we continue */ 3100e5c31af7Sopenharmony_ci glw::GLint compile_status = GL_FALSE; 3101e5c31af7Sopenharmony_ci 3102e5c31af7Sopenharmony_ci m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 3103e5c31af7Sopenharmony_ci m_po_id = gl.createProgram(); 3104e5c31af7Sopenharmony_ci m_vs_id = gl.createShader(GL_VERTEX_SHADER); 3105e5c31af7Sopenharmony_ci 3106e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() / glCreateShader() calls failed."); 3107e5c31af7Sopenharmony_ci 3108e5c31af7Sopenharmony_ci gl.attachShader(m_po_id, m_fs_id); 3109e5c31af7Sopenharmony_ci gl.attachShader(m_po_id, m_vs_id); 3110e5c31af7Sopenharmony_ci 3111e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed."); 3112e5c31af7Sopenharmony_ci 3113e5c31af7Sopenharmony_ci gl.shaderSource(m_fs_id, 1, /* count */ 3114e5c31af7Sopenharmony_ci &fs_body, DE_NULL); /* length */ 3115e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 3116e5c31af7Sopenharmony_ci 3117e5c31af7Sopenharmony_ci gl.compileShader(m_fs_id); 3118e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 3119e5c31af7Sopenharmony_ci 3120e5c31af7Sopenharmony_ci gl.getShaderiv(m_fs_id, GL_COMPILE_STATUS, &compile_status); 3121e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 3122e5c31af7Sopenharmony_ci 3123e5c31af7Sopenharmony_ci if (compile_status == GL_FALSE) 3124e5c31af7Sopenharmony_ci { 3125e5c31af7Sopenharmony_ci TCU_FAIL("Fragment shader failed to compile."); 3126e5c31af7Sopenharmony_ci } 3127e5c31af7Sopenharmony_ci 3128e5c31af7Sopenharmony_ci /* Run three separate test iterations. */ 3129e5c31af7Sopenharmony_ci struct _test_item 3130e5c31af7Sopenharmony_ci { 3131e5c31af7Sopenharmony_ci bool should_redeclare_output_variables; 3132e5c31af7Sopenharmony_ci bool use_dynamic_index_based_writes; 3133e5c31af7Sopenharmony_ci } test_items[] = { /* Negative Test 1 */ 3134e5c31af7Sopenharmony_ci { true, false }, 3135e5c31af7Sopenharmony_ci 3136e5c31af7Sopenharmony_ci /* Negative Test 2 */ 3137e5c31af7Sopenharmony_ci { false, false }, 3138e5c31af7Sopenharmony_ci 3139e5c31af7Sopenharmony_ci /* Negative Test 3 */ 3140e5c31af7Sopenharmony_ci { false, true } 3141e5c31af7Sopenharmony_ci }; 3142e5c31af7Sopenharmony_ci const unsigned int n_test_items = sizeof(test_items) / sizeof(test_items[0]); 3143e5c31af7Sopenharmony_ci 3144e5c31af7Sopenharmony_ci for (unsigned int n_test_item = 0; n_test_item < n_test_items; ++n_test_item) 3145e5c31af7Sopenharmony_ci { 3146e5c31af7Sopenharmony_ci const _test_item& current_test_item = test_items[n_test_item]; 3147e5c31af7Sopenharmony_ci 3148e5c31af7Sopenharmony_ci /* Prepare vertex shader body */ 3149e5c31af7Sopenharmony_ci std::size_t token_position = std::string::npos; 3150e5c31af7Sopenharmony_ci std::stringstream vs_body_sstream; 3151e5c31af7Sopenharmony_ci std::string vs_body_string; 3152e5c31af7Sopenharmony_ci 3153e5c31af7Sopenharmony_ci vs_body_sstream << vs_body_preamble << "\n"; 3154e5c31af7Sopenharmony_ci 3155e5c31af7Sopenharmony_ci if (current_test_item.should_redeclare_output_variables) 3156e5c31af7Sopenharmony_ci { 3157e5c31af7Sopenharmony_ci vs_body_sstream << "#define " << token_redeclare_output_variables << "\n"; 3158e5c31af7Sopenharmony_ci } 3159e5c31af7Sopenharmony_ci 3160e5c31af7Sopenharmony_ci if (current_test_item.use_dynamic_index_based_writes) 3161e5c31af7Sopenharmony_ci { 3162e5c31af7Sopenharmony_ci vs_body_sstream << "#define " << token_dynamic_index_based_writes << "\n"; 3163e5c31af7Sopenharmony_ci } 3164e5c31af7Sopenharmony_ci 3165e5c31af7Sopenharmony_ci vs_body_sstream << vs_body_main; 3166e5c31af7Sopenharmony_ci 3167e5c31af7Sopenharmony_ci /* Replace tokens with meaningful values */ 3168e5c31af7Sopenharmony_ci vs_body_string = vs_body_sstream.str(); 3169e5c31af7Sopenharmony_ci 3170e5c31af7Sopenharmony_ci while ((token_position = vs_body_string.find(token_n_gl_clipdistance_entries)) != std::string::npos) 3171e5c31af7Sopenharmony_ci { 3172e5c31af7Sopenharmony_ci vs_body_string = vs_body_string.replace(token_position, strlen(token_n_gl_clipdistance_entries), 3173e5c31af7Sopenharmony_ci n_gl_clipdistance_array_items_string); 3174e5c31af7Sopenharmony_ci } 3175e5c31af7Sopenharmony_ci 3176e5c31af7Sopenharmony_ci while ((token_position = vs_body_string.find(token_n_gl_culldistance_entries)) != std::string::npos) 3177e5c31af7Sopenharmony_ci { 3178e5c31af7Sopenharmony_ci vs_body_string = vs_body_string.replace(token_position, strlen(token_n_gl_clipdistance_entries), 3179e5c31af7Sopenharmony_ci n_gl_culldistance_array_items_string); 3180e5c31af7Sopenharmony_ci } 3181e5c31af7Sopenharmony_ci 3182e5c31af7Sopenharmony_ci while ((token_position = vs_body_string.find(token_insert_static_writes)) != std::string::npos) 3183e5c31af7Sopenharmony_ci { 3184e5c31af7Sopenharmony_ci vs_body_string = vs_body_string.replace(token_position, strlen(token_insert_static_writes), 3185e5c31af7Sopenharmony_ci static_write_shader_body_part); 3186e5c31af7Sopenharmony_ci } 3187e5c31af7Sopenharmony_ci 3188e5c31af7Sopenharmony_ci /* Try to compile the vertex shader */ 3189e5c31af7Sopenharmony_ci glw::GLint compile_status_internal = GL_FALSE; 3190e5c31af7Sopenharmony_ci const char* vs_body_raw_ptr = vs_body_string.c_str(); 3191e5c31af7Sopenharmony_ci 3192e5c31af7Sopenharmony_ci gl.shaderSource(m_vs_id, 1, /* count */ 3193e5c31af7Sopenharmony_ci &vs_body_raw_ptr, DE_NULL); /* length */ 3194e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); 3195e5c31af7Sopenharmony_ci 3196e5c31af7Sopenharmony_ci gl.compileShader(m_vs_id); 3197e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); 3198e5c31af7Sopenharmony_ci 3199e5c31af7Sopenharmony_ci gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status_internal); 3200e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 3201e5c31af7Sopenharmony_ci 3202e5c31af7Sopenharmony_ci if (compile_status_internal == GL_FALSE) 3203e5c31af7Sopenharmony_ci { 3204e5c31af7Sopenharmony_ci glw::GLint buffer_size = 0; 3205e5c31af7Sopenharmony_ci 3206e5c31af7Sopenharmony_ci /* Log the compilation error */ 3207e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 3208e5c31af7Sopenharmony_ci << getTestDescription(n_test_item, current_test_item.should_redeclare_output_variables, 3209e5c31af7Sopenharmony_ci current_test_item.use_dynamic_index_based_writes) 3210e5c31af7Sopenharmony_ci << "has failed (as expected) to compile with the following info log:\n\n" 3211e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 3212e5c31af7Sopenharmony_ci 3213e5c31af7Sopenharmony_ci gl.getShaderiv(m_vs_id, GL_INFO_LOG_LENGTH, &buffer_size); 3214e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); 3215e5c31af7Sopenharmony_ci 3216e5c31af7Sopenharmony_ci m_temp_buffer = new glw::GLchar[buffer_size + 1]; 3217e5c31af7Sopenharmony_ci 3218e5c31af7Sopenharmony_ci memset(m_temp_buffer, 0, buffer_size + 1); 3219e5c31af7Sopenharmony_ci 3220e5c31af7Sopenharmony_ci gl.getShaderInfoLog(m_vs_id, buffer_size, DE_NULL, /* length */ 3221e5c31af7Sopenharmony_ci m_temp_buffer); 3222e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog() call failed."); 3223e5c31af7Sopenharmony_ci 3224e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << m_temp_buffer << tcu::TestLog::EndMessage; 3225e5c31af7Sopenharmony_ci 3226e5c31af7Sopenharmony_ci delete[] m_temp_buffer; 3227e5c31af7Sopenharmony_ci m_temp_buffer = DE_NULL; 3228e5c31af7Sopenharmony_ci 3229e5c31af7Sopenharmony_ci /* Move on to the next iteration */ 3230e5c31af7Sopenharmony_ci continue; 3231e5c31af7Sopenharmony_ci } 3232e5c31af7Sopenharmony_ci 3233e5c31af7Sopenharmony_ci /* Try to link the program object */ 3234e5c31af7Sopenharmony_ci glw::GLint link_status = GL_FALSE; 3235e5c31af7Sopenharmony_ci 3236e5c31af7Sopenharmony_ci gl.linkProgram(m_po_id); 3237e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); 3238e5c31af7Sopenharmony_ci 3239e5c31af7Sopenharmony_ci gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 3240e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 3241e5c31af7Sopenharmony_ci 3242e5c31af7Sopenharmony_ci if (link_status == GL_TRUE) 3243e5c31af7Sopenharmony_ci { 3244e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 3245e5c31af7Sopenharmony_ci << getTestDescription(n_test_item, current_test_item.should_redeclare_output_variables, 3246e5c31af7Sopenharmony_ci current_test_item.use_dynamic_index_based_writes) 3247e5c31af7Sopenharmony_ci << "has linked successfully which is invalid!" << tcu::TestLog::EndMessage; 3248e5c31af7Sopenharmony_ci 3249e5c31af7Sopenharmony_ci TCU_FAIL("Program object has linked successfully, even though the process should have failed."); 3250e5c31af7Sopenharmony_ci } 3251e5c31af7Sopenharmony_ci else 3252e5c31af7Sopenharmony_ci { 3253e5c31af7Sopenharmony_ci glw::GLint buffer_size = 0; 3254e5c31af7Sopenharmony_ci 3255e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message 3256e5c31af7Sopenharmony_ci << getTestDescription(n_test_item, current_test_item.should_redeclare_output_variables, 3257e5c31af7Sopenharmony_ci current_test_item.use_dynamic_index_based_writes) 3258e5c31af7Sopenharmony_ci << "has failed (as expected) to link with the following info log:\n\n" 3259e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 3260e5c31af7Sopenharmony_ci 3261e5c31af7Sopenharmony_ci gl.getProgramiv(m_po_id, GL_INFO_LOG_LENGTH, &buffer_size); 3262e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); 3263e5c31af7Sopenharmony_ci 3264e5c31af7Sopenharmony_ci m_temp_buffer = new glw::GLchar[buffer_size + 1]; 3265e5c31af7Sopenharmony_ci 3266e5c31af7Sopenharmony_ci memset(m_temp_buffer, 0, buffer_size + 1); 3267e5c31af7Sopenharmony_ci 3268e5c31af7Sopenharmony_ci gl.getProgramInfoLog(m_po_id, buffer_size, DE_NULL, /* length */ 3269e5c31af7Sopenharmony_ci m_temp_buffer); 3270e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog() call failed."); 3271e5c31af7Sopenharmony_ci 3272e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << m_temp_buffer << tcu::TestLog::EndMessage; 3273e5c31af7Sopenharmony_ci 3274e5c31af7Sopenharmony_ci delete[] m_temp_buffer; 3275e5c31af7Sopenharmony_ci m_temp_buffer = DE_NULL; 3276e5c31af7Sopenharmony_ci } 3277e5c31af7Sopenharmony_ci } /* for (all test items) */ 3278e5c31af7Sopenharmony_ci 3279e5c31af7Sopenharmony_ci /* All done */ 3280e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3281e5c31af7Sopenharmony_ci 3282e5c31af7Sopenharmony_ci return STOP; 3283e5c31af7Sopenharmony_ci} 3284e5c31af7Sopenharmony_ci 3285e5c31af7Sopenharmony_ci/** Constructor. 3286e5c31af7Sopenharmony_ci * 3287e5c31af7Sopenharmony_ci * @param context Rendering context. 3288e5c31af7Sopenharmony_ci */ 3289e5c31af7Sopenharmony_ciCullDistance::Tests::Tests(deqp::Context& context) : TestCaseGroup(context, "cull_distance", "Cull Distance Test Suite") 3290e5c31af7Sopenharmony_ci{ 3291e5c31af7Sopenharmony_ci} 3292e5c31af7Sopenharmony_ci 3293e5c31af7Sopenharmony_ci/** Initializes the test group contents. */ 3294e5c31af7Sopenharmony_civoid CullDistance::Tests::init() 3295e5c31af7Sopenharmony_ci{ 3296e5c31af7Sopenharmony_ci addChild(new CullDistance::APICoverageTest(m_context)); 3297e5c31af7Sopenharmony_ci addChild(new CullDistance::FunctionalTest(m_context)); 3298e5c31af7Sopenharmony_ci addChild(new CullDistance::NegativeTest(m_context)); 3299e5c31af7Sopenharmony_ci} 3300e5c31af7Sopenharmony_ci} /* glcts namespace */ 3301