1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * OpenGL Conformance Test Suite 3e5c31af7Sopenharmony_ci * ----------------------------- 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright (c) 2014-2016 The Khronos Group Inc. 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci */ /*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief 22e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "esextcTessellationShaderProgramInterfaces.hpp" 25e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp" 26e5c31af7Sopenharmony_ci#include "gluDefs.hpp" 27e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 28e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 29e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 30e5c31af7Sopenharmony_ci 31e5c31af7Sopenharmony_cinamespace glcts 32e5c31af7Sopenharmony_ci{ 33e5c31af7Sopenharmony_ci/** Constructor 34e5c31af7Sopenharmony_ci * 35e5c31af7Sopenharmony_ci * @param context Test context 36e5c31af7Sopenharmony_ci * @param name Test case's name 37e5c31af7Sopenharmony_ci * @param description Test case's desricption 38e5c31af7Sopenharmony_ci **/ 39e5c31af7Sopenharmony_ciTessellationShaderProgramInterfaces::TessellationShaderProgramInterfaces(Context& context, 40e5c31af7Sopenharmony_ci const ExtParameters& extParams) 41e5c31af7Sopenharmony_ci : TestCaseBase(context, extParams, "ext_program_interface_query_dependency", 42e5c31af7Sopenharmony_ci "Verifies EXT_program_interface_query works correctly for tessellation" 43e5c31af7Sopenharmony_ci " control and tessellation evaluation shaders") 44e5c31af7Sopenharmony_ci , m_fs_shader_id(0) 45e5c31af7Sopenharmony_ci , m_po_id(0) 46e5c31af7Sopenharmony_ci , m_tc_shader_id(0) 47e5c31af7Sopenharmony_ci , m_te_shader_id(0) 48e5c31af7Sopenharmony_ci , m_vs_shader_id(0) 49e5c31af7Sopenharmony_ci , m_is_atomic_counters_supported(false) 50e5c31af7Sopenharmony_ci , m_is_shader_storage_blocks_supported(false) 51e5c31af7Sopenharmony_ci{ 52e5c31af7Sopenharmony_ci /* Left blank on purpose */ 53e5c31af7Sopenharmony_ci} 54e5c31af7Sopenharmony_ci 55e5c31af7Sopenharmony_ci/** Deinitializes all ES objects created for the test. */ 56e5c31af7Sopenharmony_civoid TessellationShaderProgramInterfaces::deinit() 57e5c31af7Sopenharmony_ci{ 58e5c31af7Sopenharmony_ci /** Call base class' deinit() function */ 59e5c31af7Sopenharmony_ci TestCaseBase::deinit(); 60e5c31af7Sopenharmony_ci 61e5c31af7Sopenharmony_ci /* Release all objects we might've created */ 62e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 63e5c31af7Sopenharmony_ci 64e5c31af7Sopenharmony_ci if (m_fs_shader_id != 0) 65e5c31af7Sopenharmony_ci { 66e5c31af7Sopenharmony_ci gl.deleteShader(m_fs_shader_id); 67e5c31af7Sopenharmony_ci 68e5c31af7Sopenharmony_ci m_fs_shader_id = 0; 69e5c31af7Sopenharmony_ci } 70e5c31af7Sopenharmony_ci 71e5c31af7Sopenharmony_ci if (m_po_id != 0) 72e5c31af7Sopenharmony_ci { 73e5c31af7Sopenharmony_ci gl.deleteProgram(m_po_id); 74e5c31af7Sopenharmony_ci 75e5c31af7Sopenharmony_ci m_po_id = 0; 76e5c31af7Sopenharmony_ci } 77e5c31af7Sopenharmony_ci 78e5c31af7Sopenharmony_ci if (m_tc_shader_id != 0) 79e5c31af7Sopenharmony_ci { 80e5c31af7Sopenharmony_ci gl.deleteShader(m_tc_shader_id); 81e5c31af7Sopenharmony_ci 82e5c31af7Sopenharmony_ci m_tc_shader_id = 0; 83e5c31af7Sopenharmony_ci } 84e5c31af7Sopenharmony_ci 85e5c31af7Sopenharmony_ci if (m_te_shader_id != 0) 86e5c31af7Sopenharmony_ci { 87e5c31af7Sopenharmony_ci gl.deleteShader(m_te_shader_id); 88e5c31af7Sopenharmony_ci 89e5c31af7Sopenharmony_ci m_te_shader_id = 0; 90e5c31af7Sopenharmony_ci } 91e5c31af7Sopenharmony_ci 92e5c31af7Sopenharmony_ci if (m_vs_shader_id != 0) 93e5c31af7Sopenharmony_ci { 94e5c31af7Sopenharmony_ci gl.deleteShader(m_vs_shader_id); 95e5c31af7Sopenharmony_ci 96e5c31af7Sopenharmony_ci m_vs_shader_id = 0; 97e5c31af7Sopenharmony_ci } 98e5c31af7Sopenharmony_ci} 99e5c31af7Sopenharmony_ci 100e5c31af7Sopenharmony_ci/** Initializes all ES objects that will be used for the test. */ 101e5c31af7Sopenharmony_civoid TessellationShaderProgramInterfaces::initTest() 102e5c31af7Sopenharmony_ci{ 103e5c31af7Sopenharmony_ci /* The test requires EXT_tessellation_shader and EXT_program_interfaces_query extensions */ 104e5c31af7Sopenharmony_ci if (!m_is_tessellation_shader_supported || !m_is_program_interface_query_supported) 105e5c31af7Sopenharmony_ci { 106e5c31af7Sopenharmony_ci return; 107e5c31af7Sopenharmony_ci } 108e5c31af7Sopenharmony_ci 109e5c31af7Sopenharmony_ci /* Generate a program object we will later configure */ 110e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 111e5c31af7Sopenharmony_ci 112e5c31af7Sopenharmony_ci m_po_id = gl.createProgram(); 113e5c31af7Sopenharmony_ci 114e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed"); 115e5c31af7Sopenharmony_ci 116e5c31af7Sopenharmony_ci /* Generate shader objects the test will use */ 117e5c31af7Sopenharmony_ci m_fs_shader_id = gl.createShader(GL_FRAGMENT_SHADER); 118e5c31af7Sopenharmony_ci m_tc_shader_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 119e5c31af7Sopenharmony_ci m_te_shader_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 120e5c31af7Sopenharmony_ci m_vs_shader_id = gl.createShader(GL_VERTEX_SHADER); 121e5c31af7Sopenharmony_ci 122e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed"); 123e5c31af7Sopenharmony_ci 124e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_control_shader_storage_blocks; 125e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_control_atomic_counter_buffers; 126e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_control_atomic_counters; 127e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_evaluation_shader_storage_blocks; 128e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_evaluation_atomic_counter_buffers; 129e5c31af7Sopenharmony_ci glw::GLint gl_max_tess_evaluation_atomic_counters; 130e5c31af7Sopenharmony_ci 131e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS, &gl_max_tess_control_atomic_counter_buffers); 132e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), 133e5c31af7Sopenharmony_ci "glGetIntegerv() failed for GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT pname"); 134e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_CONTROL_ATOMIC_COUNTERS, &gl_max_tess_control_atomic_counters); 135e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT pname"); 136e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &gl_max_tess_control_shader_storage_blocks); 137e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), 138e5c31af7Sopenharmony_ci "glGetIntegerv() failed for GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT pname"); 139e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS, 140e5c31af7Sopenharmony_ci &gl_max_tess_evaluation_atomic_counter_buffers); 141e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), 142e5c31af7Sopenharmony_ci "glGetIntegerv() failed for GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT pname"); 143e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_EVALUATION_ATOMIC_COUNTERS, &gl_max_tess_evaluation_atomic_counters); 144e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT pname"); 145e5c31af7Sopenharmony_ci gl.getIntegerv(m_glExtTokens.MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, 146e5c31af7Sopenharmony_ci &gl_max_tess_evaluation_shader_storage_blocks); 147e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), 148e5c31af7Sopenharmony_ci "glGetIntegerv() failed for GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT pname"); 149e5c31af7Sopenharmony_ci 150e5c31af7Sopenharmony_ci m_is_atomic_counters_supported = 151e5c31af7Sopenharmony_ci (gl_max_tess_control_atomic_counter_buffers > 1) && (gl_max_tess_evaluation_atomic_counter_buffers > 1) && 152e5c31af7Sopenharmony_ci (gl_max_tess_control_atomic_counters > 0) && (gl_max_tess_evaluation_atomic_counters > 0); 153e5c31af7Sopenharmony_ci 154e5c31af7Sopenharmony_ci m_is_shader_storage_blocks_supported = 155e5c31af7Sopenharmony_ci (gl_max_tess_control_shader_storage_blocks > 0) && (gl_max_tess_evaluation_shader_storage_blocks > 0); 156e5c31af7Sopenharmony_ci 157e5c31af7Sopenharmony_ci const char* atomic_counters_header = NULL; 158e5c31af7Sopenharmony_ci if (m_is_atomic_counters_supported) 159e5c31af7Sopenharmony_ci { 160e5c31af7Sopenharmony_ci atomic_counters_header = "#define USE_ATOMIC_COUNTERS 1\n"; 161e5c31af7Sopenharmony_ci } 162e5c31af7Sopenharmony_ci else 163e5c31af7Sopenharmony_ci { 164e5c31af7Sopenharmony_ci atomic_counters_header = "\n"; 165e5c31af7Sopenharmony_ci } 166e5c31af7Sopenharmony_ci 167e5c31af7Sopenharmony_ci const char* shader_storage_blocks_header = NULL; 168e5c31af7Sopenharmony_ci if (m_is_shader_storage_blocks_supported) 169e5c31af7Sopenharmony_ci { 170e5c31af7Sopenharmony_ci shader_storage_blocks_header = "#define USE_SHADER_STORAGE_BLOCKS\n"; 171e5c31af7Sopenharmony_ci } 172e5c31af7Sopenharmony_ci else 173e5c31af7Sopenharmony_ci { 174e5c31af7Sopenharmony_ci shader_storage_blocks_header = "\n"; 175e5c31af7Sopenharmony_ci } 176e5c31af7Sopenharmony_ci 177e5c31af7Sopenharmony_ci /* Build shader program */ 178e5c31af7Sopenharmony_ci const char* fs_body = "${VERSION}\n" 179e5c31af7Sopenharmony_ci "\n" 180e5c31af7Sopenharmony_ci "precision highp float;\n" 181e5c31af7Sopenharmony_ci "\n" 182e5c31af7Sopenharmony_ci "out vec4 test_output;\n" 183e5c31af7Sopenharmony_ci "\n" 184e5c31af7Sopenharmony_ci "void main()\n" 185e5c31af7Sopenharmony_ci "{\n" 186e5c31af7Sopenharmony_ci " test_output = vec4(1, 0, 0, 0);\n" 187e5c31af7Sopenharmony_ci "}\n"; 188e5c31af7Sopenharmony_ci 189e5c31af7Sopenharmony_ci const char* tc_body = "\n" 190e5c31af7Sopenharmony_ci "layout (vertices = 1) out;\n" 191e5c31af7Sopenharmony_ci "\n" 192e5c31af7Sopenharmony_ci /* Uniforms */ 193e5c31af7Sopenharmony_ci "uniform vec2 tc_uniform1;\n" 194e5c31af7Sopenharmony_ci "uniform mat4 tc_uniform2;\n" 195e5c31af7Sopenharmony_ci "\n" 196e5c31af7Sopenharmony_ci /* Uniform blocks */ 197e5c31af7Sopenharmony_ci "uniform tc_uniform_block1\n" 198e5c31af7Sopenharmony_ci "{\n" 199e5c31af7Sopenharmony_ci " float tc_uniform_block1_1;\n" 200e5c31af7Sopenharmony_ci "};\n" 201e5c31af7Sopenharmony_ci /* Atomic counter buffers */ 202e5c31af7Sopenharmony_ci "#ifdef USE_ATOMIC_COUNTERS\n" 203e5c31af7Sopenharmony_ci "layout(binding = 1, offset = 0) uniform atomic_uint tc_atomic_counter1;\n" 204e5c31af7Sopenharmony_ci "#endif\n" 205e5c31af7Sopenharmony_ci /* Shader storage blocks & buffer variables */ 206e5c31af7Sopenharmony_ci "#ifdef USE_SHADER_STORAGE_BLOCKS\n" 207e5c31af7Sopenharmony_ci "layout(std140, binding = 0) buffer tc_shader_storage_block1\n" 208e5c31af7Sopenharmony_ci "{\n" 209e5c31af7Sopenharmony_ci " vec4 tc_shader_storage_buffer_object_1[];\n" 210e5c31af7Sopenharmony_ci "};\n" 211e5c31af7Sopenharmony_ci "#endif\n" 212e5c31af7Sopenharmony_ci /* Body */ 213e5c31af7Sopenharmony_ci "void main()\n" 214e5c31af7Sopenharmony_ci "{\n" 215e5c31af7Sopenharmony_ci " int test = 1;\n" 216e5c31af7Sopenharmony_ci "\n" 217e5c31af7Sopenharmony_ci /* Uniforms */ 218e5c31af7Sopenharmony_ci " if (tc_uniform1.x == 0.0) test = 2;\n" 219e5c31af7Sopenharmony_ci " if (tc_uniform2[0].y == 1.0) test = 3;\n" 220e5c31af7Sopenharmony_ci /* Uniform blocks */ 221e5c31af7Sopenharmony_ci " if (tc_uniform_block1_1 == 3.0) test = 4;\n" 222e5c31af7Sopenharmony_ci /* Atomic counter buffers */ 223e5c31af7Sopenharmony_ci "#ifdef USE_ATOMIC_COUNTERS\n" 224e5c31af7Sopenharmony_ci " if (atomicCounter(tc_atomic_counter1) == 1u) test = 5;\n" 225e5c31af7Sopenharmony_ci "#endif\n" 226e5c31af7Sopenharmony_ci /* Shader storage blocks & buffer variables */ 227e5c31af7Sopenharmony_ci "#ifdef USE_SHADER_STORAGE_BLOCKS\n" 228e5c31af7Sopenharmony_ci " if (tc_shader_storage_buffer_object_1[0].x == 0.0) test = 6;\n" 229e5c31af7Sopenharmony_ci "#endif\n" 230e5c31af7Sopenharmony_ci "\n" 231e5c31af7Sopenharmony_ci " gl_out [gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 232e5c31af7Sopenharmony_ci " gl_TessLevelOuter[0] = 2.0 * float(test);\n" 233e5c31af7Sopenharmony_ci " gl_TessLevelOuter[1] = 3.0;\n" 234e5c31af7Sopenharmony_ci "}\n"; 235e5c31af7Sopenharmony_ci 236e5c31af7Sopenharmony_ci const char* tc_code[] = { "${VERSION}\n", 237e5c31af7Sopenharmony_ci /* Required EXT_tessellation_shader functionality */ 238e5c31af7Sopenharmony_ci "${TESSELLATION_SHADER_REQUIRE}\n", atomic_counters_header, shader_storage_blocks_header, 239e5c31af7Sopenharmony_ci tc_body }; 240e5c31af7Sopenharmony_ci 241e5c31af7Sopenharmony_ci const char* te_body = "\n" 242e5c31af7Sopenharmony_ci "layout (isolines, ccw, equal_spacing, point_mode) in;\n" 243e5c31af7Sopenharmony_ci "\n" 244e5c31af7Sopenharmony_ci /* Uniforms */ 245e5c31af7Sopenharmony_ci "uniform vec2 te_uniform1;\n" 246e5c31af7Sopenharmony_ci "uniform mat4 te_uniform2;\n" 247e5c31af7Sopenharmony_ci "\n" 248e5c31af7Sopenharmony_ci /* Uniform blocks */ 249e5c31af7Sopenharmony_ci "uniform te_uniform_block1\n" 250e5c31af7Sopenharmony_ci "{\n" 251e5c31af7Sopenharmony_ci " float te_uniform_block1_1;\n" 252e5c31af7Sopenharmony_ci "};\n" 253e5c31af7Sopenharmony_ci /* Atomic counter buffers */ 254e5c31af7Sopenharmony_ci "#ifdef USE_ATOMIC_COUNTERS\n" 255e5c31af7Sopenharmony_ci "layout(binding = 2, offset = 0) uniform atomic_uint te_atomic_counter1;\n" 256e5c31af7Sopenharmony_ci "#endif\n" 257e5c31af7Sopenharmony_ci /* Shader storage blocks & buffer variables */ 258e5c31af7Sopenharmony_ci "#ifdef USE_SHADER_STORAGE_BLOCKS\n" 259e5c31af7Sopenharmony_ci "layout(std140, binding = 0) buffer te_shader_storage_block1\n" 260e5c31af7Sopenharmony_ci "{\n" 261e5c31af7Sopenharmony_ci " vec4 te_shader_storage_buffer_object_1[];\n" 262e5c31af7Sopenharmony_ci "};\n" 263e5c31af7Sopenharmony_ci "#endif\n" 264e5c31af7Sopenharmony_ci "void main()\n" 265e5c31af7Sopenharmony_ci "{\n" 266e5c31af7Sopenharmony_ci " int test = 1;\n" 267e5c31af7Sopenharmony_ci "\n" 268e5c31af7Sopenharmony_ci /* Uniforms */ 269e5c31af7Sopenharmony_ci " if (te_uniform1.x == 0.0) test = 2;\n" 270e5c31af7Sopenharmony_ci " if (te_uniform2[0].y == 1.0) test = 3;\n" 271e5c31af7Sopenharmony_ci /* Uniform blocks */ 272e5c31af7Sopenharmony_ci " if (te_uniform_block1_1 == 3.0) test = 4;\n" 273e5c31af7Sopenharmony_ci /* Atomic counter buffers */ 274e5c31af7Sopenharmony_ci "#ifdef USE_ATOMIC_COUNTERS\n" 275e5c31af7Sopenharmony_ci " if (atomicCounter(te_atomic_counter1) == 1u) test = 5;\n" 276e5c31af7Sopenharmony_ci "#endif\n" 277e5c31af7Sopenharmony_ci /* Shader storage blocks & buffer variables */ 278e5c31af7Sopenharmony_ci "#ifdef USE_SHADER_STORAGE_BLOCKS\n" 279e5c31af7Sopenharmony_ci " if (te_shader_storage_buffer_object_1[0].x == 0.0) test = 6;\n" 280e5c31af7Sopenharmony_ci "#endif\n" 281e5c31af7Sopenharmony_ci "\n" 282e5c31af7Sopenharmony_ci " gl_Position = gl_in[0].gl_Position * float(test);\n" 283e5c31af7Sopenharmony_ci "}\n"; 284e5c31af7Sopenharmony_ci 285e5c31af7Sopenharmony_ci const char* te_code[] = { "${VERSION}\n", 286e5c31af7Sopenharmony_ci /* Required EXT_tessellation_shader functionality */ 287e5c31af7Sopenharmony_ci "${TESSELLATION_SHADER_REQUIRE}\n", atomic_counters_header, shader_storage_blocks_header, 288e5c31af7Sopenharmony_ci te_body }; 289e5c31af7Sopenharmony_ci 290e5c31af7Sopenharmony_ci const char* vs_body = "${VERSION}\n" 291e5c31af7Sopenharmony_ci "\n" 292e5c31af7Sopenharmony_ci "in vec4 test_input;\n" 293e5c31af7Sopenharmony_ci "\n" 294e5c31af7Sopenharmony_ci "void main()\n" 295e5c31af7Sopenharmony_ci "{\n" 296e5c31af7Sopenharmony_ci " gl_Position = vec4(gl_VertexID, test_input.y, 0, 1);\n" 297e5c31af7Sopenharmony_ci "}\n"; 298e5c31af7Sopenharmony_ci 299e5c31af7Sopenharmony_ci bool link_success = buildProgram(m_po_id, m_fs_shader_id, 1, &fs_body, m_tc_shader_id, 5, tc_code, m_te_shader_id, 300e5c31af7Sopenharmony_ci 5, te_code, m_vs_shader_id, 1, &vs_body); 301e5c31af7Sopenharmony_ci 302e5c31af7Sopenharmony_ci if (!link_success) 303e5c31af7Sopenharmony_ci { 304e5c31af7Sopenharmony_ci TCU_FAIL("Program compilation and linking failed"); 305e5c31af7Sopenharmony_ci } 306e5c31af7Sopenharmony_ci 307e5c31af7Sopenharmony_ci /* We're good to execute the test! */ 308e5c31af7Sopenharmony_ci} 309e5c31af7Sopenharmony_ci 310e5c31af7Sopenharmony_ci/** Executes the test. 311e5c31af7Sopenharmony_ci * 312e5c31af7Sopenharmony_ci * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 313e5c31af7Sopenharmony_ci * 314e5c31af7Sopenharmony_ci * Note the function throws exception should an error occur! 315e5c31af7Sopenharmony_ci * 316e5c31af7Sopenharmony_ci * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 317e5c31af7Sopenharmony_ci **/ 318e5c31af7Sopenharmony_citcu::TestNode::IterateResult TessellationShaderProgramInterfaces::iterate(void) 319e5c31af7Sopenharmony_ci{ 320e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 321e5c31af7Sopenharmony_ci 322e5c31af7Sopenharmony_ci /* Do not execute if required extensions are not supported. */ 323e5c31af7Sopenharmony_ci if (!m_is_tessellation_shader_supported) 324e5c31af7Sopenharmony_ci { 325e5c31af7Sopenharmony_ci throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 326e5c31af7Sopenharmony_ci } 327e5c31af7Sopenharmony_ci 328e5c31af7Sopenharmony_ci /* Initialize ES objects needed to run the test */ 329e5c31af7Sopenharmony_ci initTest(); 330e5c31af7Sopenharmony_ci 331e5c31af7Sopenharmony_ci /* Iterate through all interfaces */ 332e5c31af7Sopenharmony_ci const glw::GLenum interfaces[] = { 333e5c31af7Sopenharmony_ci GL_UNIFORM, GL_UNIFORM_BLOCK, GL_ATOMIC_COUNTER_BUFFER, GL_SHADER_STORAGE_BLOCK, 334e5c31af7Sopenharmony_ci GL_BUFFER_VARIABLE, GL_PROGRAM_INPUT, GL_PROGRAM_OUTPUT 335e5c31af7Sopenharmony_ci }; 336e5c31af7Sopenharmony_ci const unsigned int n_interfaces = sizeof(interfaces) / sizeof(interfaces[0]); 337e5c31af7Sopenharmony_ci 338e5c31af7Sopenharmony_ci for (unsigned int n_interface = 0; n_interface < n_interfaces; ++n_interface) 339e5c31af7Sopenharmony_ci { 340e5c31af7Sopenharmony_ci glw::GLenum interface = interfaces[n_interface]; 341e5c31af7Sopenharmony_ci 342e5c31af7Sopenharmony_ci if ((interface == GL_SHADER_STORAGE_BLOCK || interface == GL_BUFFER_VARIABLE) && 343e5c31af7Sopenharmony_ci !m_is_shader_storage_blocks_supported) 344e5c31af7Sopenharmony_ci { 345e5c31af7Sopenharmony_ci continue; 346e5c31af7Sopenharmony_ci } 347e5c31af7Sopenharmony_ci 348e5c31af7Sopenharmony_ci if (interface == GL_ATOMIC_COUNTER_BUFFER && !m_is_atomic_counters_supported) 349e5c31af7Sopenharmony_ci { 350e5c31af7Sopenharmony_ci continue; 351e5c31af7Sopenharmony_ci } 352e5c31af7Sopenharmony_ci 353e5c31af7Sopenharmony_ci /* For each interface, we want to check whether a specific resource 354e5c31af7Sopenharmony_ci * is recognized by the implementation. If the name is unknown, 355e5c31af7Sopenharmony_ci * the test should fail; if it's recognized, we should verify it's referenced 356e5c31af7Sopenharmony_ci * by both TC and TE shaders 357e5c31af7Sopenharmony_ci */ 358e5c31af7Sopenharmony_ci const char* tc_resource_name = DE_NULL; 359e5c31af7Sopenharmony_ci const char* te_resource_name = DE_NULL; 360e5c31af7Sopenharmony_ci 361e5c31af7Sopenharmony_ci switch (interface) 362e5c31af7Sopenharmony_ci { 363e5c31af7Sopenharmony_ci case GL_UNIFORM: 364e5c31af7Sopenharmony_ci { 365e5c31af7Sopenharmony_ci tc_resource_name = "tc_uniform1"; 366e5c31af7Sopenharmony_ci te_resource_name = "te_uniform1"; 367e5c31af7Sopenharmony_ci 368e5c31af7Sopenharmony_ci break; 369e5c31af7Sopenharmony_ci } 370e5c31af7Sopenharmony_ci 371e5c31af7Sopenharmony_ci case GL_UNIFORM_BLOCK: 372e5c31af7Sopenharmony_ci { 373e5c31af7Sopenharmony_ci tc_resource_name = "tc_uniform_block1"; 374e5c31af7Sopenharmony_ci te_resource_name = "te_uniform_block1"; 375e5c31af7Sopenharmony_ci 376e5c31af7Sopenharmony_ci break; 377e5c31af7Sopenharmony_ci } 378e5c31af7Sopenharmony_ci 379e5c31af7Sopenharmony_ci case GL_ATOMIC_COUNTER_BUFFER: 380e5c31af7Sopenharmony_ci { 381e5c31af7Sopenharmony_ci /* Atomic counter buffers are tested in a separate codepath. */ 382e5c31af7Sopenharmony_ci break; 383e5c31af7Sopenharmony_ci } 384e5c31af7Sopenharmony_ci 385e5c31af7Sopenharmony_ci case GL_SHADER_STORAGE_BLOCK: 386e5c31af7Sopenharmony_ci { 387e5c31af7Sopenharmony_ci tc_resource_name = "tc_shader_storage_block1"; 388e5c31af7Sopenharmony_ci te_resource_name = "te_shader_storage_block1"; 389e5c31af7Sopenharmony_ci 390e5c31af7Sopenharmony_ci break; 391e5c31af7Sopenharmony_ci } 392e5c31af7Sopenharmony_ci 393e5c31af7Sopenharmony_ci case GL_BUFFER_VARIABLE: 394e5c31af7Sopenharmony_ci { 395e5c31af7Sopenharmony_ci tc_resource_name = "tc_shader_storage_buffer_object_1"; 396e5c31af7Sopenharmony_ci te_resource_name = "te_shader_storage_buffer_object_1"; 397e5c31af7Sopenharmony_ci 398e5c31af7Sopenharmony_ci break; 399e5c31af7Sopenharmony_ci } 400e5c31af7Sopenharmony_ci 401e5c31af7Sopenharmony_ci case GL_PROGRAM_INPUT: 402e5c31af7Sopenharmony_ci { 403e5c31af7Sopenharmony_ci tc_resource_name = DE_NULL; 404e5c31af7Sopenharmony_ci te_resource_name = DE_NULL; 405e5c31af7Sopenharmony_ci 406e5c31af7Sopenharmony_ci break; 407e5c31af7Sopenharmony_ci } 408e5c31af7Sopenharmony_ci 409e5c31af7Sopenharmony_ci case GL_PROGRAM_OUTPUT: 410e5c31af7Sopenharmony_ci { 411e5c31af7Sopenharmony_ci tc_resource_name = DE_NULL; 412e5c31af7Sopenharmony_ci te_resource_name = DE_NULL; 413e5c31af7Sopenharmony_ci 414e5c31af7Sopenharmony_ci break; 415e5c31af7Sopenharmony_ci } 416e5c31af7Sopenharmony_ci 417e5c31af7Sopenharmony_ci default: 418e5c31af7Sopenharmony_ci { 419e5c31af7Sopenharmony_ci TCU_FAIL("Unrecognized interface type"); 420e5c31af7Sopenharmony_ci } 421e5c31af7Sopenharmony_ci } /* switch (interface) */ 422e5c31af7Sopenharmony_ci 423e5c31af7Sopenharmony_ci /* Run in two iterations - first for TC, then for TE */ 424e5c31af7Sopenharmony_ci for (int n_iteration = 0; n_iteration < 2; ++n_iteration) 425e5c31af7Sopenharmony_ci { 426e5c31af7Sopenharmony_ci glw::GLenum property = (n_iteration == 0) ? m_glExtTokens.REFERENCED_BY_TESS_CONTROL_SHADER : 427e5c31af7Sopenharmony_ci m_glExtTokens.REFERENCED_BY_TESS_EVALUATION_SHADER; 428e5c31af7Sopenharmony_ci 429e5c31af7Sopenharmony_ci if (interface == GL_ATOMIC_COUNTER_BUFFER) 430e5c31af7Sopenharmony_ci { 431e5c31af7Sopenharmony_ci /* We only need a single iteration run for this interface */ 432e5c31af7Sopenharmony_ci if (n_iteration == 1) 433e5c31af7Sopenharmony_ci { 434e5c31af7Sopenharmony_ci continue; 435e5c31af7Sopenharmony_ci } 436e5c31af7Sopenharmony_ci 437e5c31af7Sopenharmony_ci /* Atomic counter buffers are not assigned names, hence they need to be 438e5c31af7Sopenharmony_ci * tested slightly differently. 439e5c31af7Sopenharmony_ci * 440e5c31af7Sopenharmony_ci * Exactly two atomic counter buffers should be defined. Make sure that's the case. 441e5c31af7Sopenharmony_ci */ 442e5c31af7Sopenharmony_ci glw::GLint n_active_resources = 0; 443e5c31af7Sopenharmony_ci 444e5c31af7Sopenharmony_ci gl.getProgramInterfaceiv(m_po_id, interface, GL_ACTIVE_RESOURCES, &n_active_resources); 445e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInterfaceiv() failed."); 446e5c31af7Sopenharmony_ci 447e5c31af7Sopenharmony_ci if (n_active_resources != 2) 448e5c31af7Sopenharmony_ci { 449e5c31af7Sopenharmony_ci TCU_FAIL("Invalid amount of atomic counter buffer binding points reported"); 450e5c31af7Sopenharmony_ci } 451e5c31af7Sopenharmony_ci 452e5c31af7Sopenharmony_ci /* Check both resources and make sure they report separate atomic counters */ 453e5c31af7Sopenharmony_ci bool was_tc_atomic_counter_buffer_reported = false; 454e5c31af7Sopenharmony_ci bool was_te_atomic_counter_buffer_reported = false; 455e5c31af7Sopenharmony_ci 456e5c31af7Sopenharmony_ci for (int n_resource = 0; n_resource < n_active_resources; ++n_resource) 457e5c31af7Sopenharmony_ci { 458e5c31af7Sopenharmony_ci const glw::GLenum tc_property = m_glExtTokens.REFERENCED_BY_TESS_CONTROL_SHADER; 459e5c31af7Sopenharmony_ci glw::GLint tc_property_value = 0; 460e5c31af7Sopenharmony_ci const glw::GLenum te_property = m_glExtTokens.REFERENCED_BY_TESS_EVALUATION_SHADER; 461e5c31af7Sopenharmony_ci glw::GLint te_property_value = 0; 462e5c31af7Sopenharmony_ci 463e5c31af7Sopenharmony_ci gl.getProgramResourceiv(m_po_id, interface, n_resource, 1, /* propCount */ 464e5c31af7Sopenharmony_ci &tc_property, 1, /* bufSize */ 465e5c31af7Sopenharmony_ci NULL, /* length */ 466e5c31af7Sopenharmony_ci &tc_property_value); 467e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR( 468e5c31af7Sopenharmony_ci gl.getError(), 469e5c31af7Sopenharmony_ci "glGetProgramResourceiv() failed for GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT property"); 470e5c31af7Sopenharmony_ci 471e5c31af7Sopenharmony_ci gl.getProgramResourceiv(m_po_id, interface, n_resource, 1, /* propCount */ 472e5c31af7Sopenharmony_ci &te_property, 1, /* bufSize */ 473e5c31af7Sopenharmony_ci NULL, /* length */ 474e5c31af7Sopenharmony_ci &te_property_value); 475e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR( 476e5c31af7Sopenharmony_ci gl.getError(), 477e5c31af7Sopenharmony_ci "glGetProgramResourceiv() failed for GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT property"); 478e5c31af7Sopenharmony_ci 479e5c31af7Sopenharmony_ci if (tc_property_value == GL_TRUE) 480e5c31af7Sopenharmony_ci { 481e5c31af7Sopenharmony_ci if (was_tc_atomic_counter_buffer_reported) 482e5c31af7Sopenharmony_ci { 483e5c31af7Sopenharmony_ci TCU_FAIL("Tessellation control-specific atomic counter buffer is reported twice"); 484e5c31af7Sopenharmony_ci } 485e5c31af7Sopenharmony_ci 486e5c31af7Sopenharmony_ci was_tc_atomic_counter_buffer_reported = true; 487e5c31af7Sopenharmony_ci } 488e5c31af7Sopenharmony_ci 489e5c31af7Sopenharmony_ci if (te_property_value == GL_TRUE) 490e5c31af7Sopenharmony_ci { 491e5c31af7Sopenharmony_ci if (was_te_atomic_counter_buffer_reported) 492e5c31af7Sopenharmony_ci { 493e5c31af7Sopenharmony_ci TCU_FAIL("Tessellation evaluation-specific atomic counter buffer is reported twice"); 494e5c31af7Sopenharmony_ci } 495e5c31af7Sopenharmony_ci 496e5c31af7Sopenharmony_ci was_te_atomic_counter_buffer_reported = true; 497e5c31af7Sopenharmony_ci } 498e5c31af7Sopenharmony_ci } /* for (all active resources) */ 499e5c31af7Sopenharmony_ci 500e5c31af7Sopenharmony_ci if (!was_tc_atomic_counter_buffer_reported || !was_te_atomic_counter_buffer_reported) 501e5c31af7Sopenharmony_ci { 502e5c31af7Sopenharmony_ci TCU_FAIL("Either tessellation control or tessellation evaluation atomic counter buffer was not " 503e5c31af7Sopenharmony_ci "reported"); 504e5c31af7Sopenharmony_ci } 505e5c31af7Sopenharmony_ci } 506e5c31af7Sopenharmony_ci else 507e5c31af7Sopenharmony_ci { 508e5c31af7Sopenharmony_ci /* Retrieve resource index first, as long as the name is not NULL. 509e5c31af7Sopenharmony_ci * If it's NULL, the property's value is assumed to be GL_FALSE for 510e5c31af7Sopenharmony_ci * all reported active resources. 511e5c31af7Sopenharmony_ci **/ 512e5c31af7Sopenharmony_ci const char* resource_name = (n_iteration == 0) ? tc_resource_name : te_resource_name; 513e5c31af7Sopenharmony_ci 514e5c31af7Sopenharmony_ci if (resource_name == DE_NULL) 515e5c31af7Sopenharmony_ci { 516e5c31af7Sopenharmony_ci /* Make sure the property has GL_FALSE value for any resources 517e5c31af7Sopenharmony_ci * reported for this interface. */ 518e5c31af7Sopenharmony_ci glw::GLint n_active_resources = 0; 519e5c31af7Sopenharmony_ci 520e5c31af7Sopenharmony_ci gl.getProgramInterfaceiv(m_po_id, interface, GL_ACTIVE_RESOURCES, &n_active_resources); 521e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInterfaceiv() failed."); 522e5c31af7Sopenharmony_ci 523e5c31af7Sopenharmony_ci for (glw::GLint n_resource = 0; n_resource < n_active_resources; ++n_resource) 524e5c31af7Sopenharmony_ci { 525e5c31af7Sopenharmony_ci verifyPropertyValue(interface, property, n_resource, GL_FALSE); 526e5c31af7Sopenharmony_ci } /* for (all resource indices) */ 527e5c31af7Sopenharmony_ci } 528e5c31af7Sopenharmony_ci else 529e5c31af7Sopenharmony_ci { 530e5c31af7Sopenharmony_ci glw::GLuint resource_index = gl.getProgramResourceIndex(m_po_id, interface, resource_name); 531e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex() failed"); 532e5c31af7Sopenharmony_ci 533e5c31af7Sopenharmony_ci if (resource_index == GL_INVALID_INDEX) 534e5c31af7Sopenharmony_ci { 535e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Resource [" << resource_name 536e5c31af7Sopenharmony_ci << "] was not recognized." << tcu::TestLog::EndMessage; 537e5c31af7Sopenharmony_ci 538e5c31af7Sopenharmony_ci TCU_FAIL("Resource not recognized."); 539e5c31af7Sopenharmony_ci } 540e5c31af7Sopenharmony_ci 541e5c31af7Sopenharmony_ci /* Now that we know the index, we can check the GL_REFERENCED_BY_... 542e5c31af7Sopenharmony_ci * property value */ 543e5c31af7Sopenharmony_ci verifyPropertyValue(interface, property, resource_index, GL_TRUE); 544e5c31af7Sopenharmony_ci } 545e5c31af7Sopenharmony_ci } /* (interface != GL_ATOMIC_COUNTER_BUFFER) */ 546e5c31af7Sopenharmony_ci } /* for (both iterations) */ 547e5c31af7Sopenharmony_ci } /* for (all interfaces) */ 548e5c31af7Sopenharmony_ci 549e5c31af7Sopenharmony_ci /* All done */ 550e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 551e5c31af7Sopenharmony_ci return STOP; 552e5c31af7Sopenharmony_ci} 553e5c31af7Sopenharmony_ci 554e5c31af7Sopenharmony_ci/** Checks if a property value reported for user-specified program object interface 555e5c31af7Sopenharmony_ci * at given index is as expected. 556e5c31af7Sopenharmony_ci * 557e5c31af7Sopenharmony_ci * NOTE: This function throws TestError exception if retrieved value does not 558e5c31af7Sopenharmony_ci * match @param expected_value. 559e5c31af7Sopenharmony_ci * 560e5c31af7Sopenharmony_ci * @param interface Program object interface to use for the query; 561e5c31af7Sopenharmony_ci * @param property Interface property to check; 562e5c31af7Sopenharmony_ci * @param index Property index to use for the test; 563e5c31af7Sopenharmony_ci * @param expected_value Value that is expected to be reported by ES implementation. 564e5c31af7Sopenharmony_ci **/ 565e5c31af7Sopenharmony_civoid TessellationShaderProgramInterfaces::verifyPropertyValue(glw::GLenum interface, glw::GLenum property, 566e5c31af7Sopenharmony_ci glw::GLuint index, glw::GLint expected_value) 567e5c31af7Sopenharmony_ci{ 568e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 569e5c31af7Sopenharmony_ci glw::GLint property_value = 0; 570e5c31af7Sopenharmony_ci 571e5c31af7Sopenharmony_ci gl.getProgramResourceiv(m_po_id, interface, index, 1, /* propCount */ 572e5c31af7Sopenharmony_ci &property, 1, /* bufSize */ 573e5c31af7Sopenharmony_ci NULL, /* length */ 574e5c31af7Sopenharmony_ci &property_value); 575e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv() failed"); 576e5c31af7Sopenharmony_ci 577e5c31af7Sopenharmony_ci if (property_value != expected_value) 578e5c31af7Sopenharmony_ci { 579e5c31af7Sopenharmony_ci TCU_FAIL("Invalid GL_REFERENCED_BY_... property value reported"); 580e5c31af7Sopenharmony_ci } 581e5c31af7Sopenharmony_ci} 582e5c31af7Sopenharmony_ci 583e5c31af7Sopenharmony_ci} /* namespace glcts */ 584