1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2014-2016 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ /*! 20 * \file 21 * \brief 22 */ /*-------------------------------------------------------------------*/ 23 24 #include "esextcTessellationShaderProperties.hpp" 25 #include "gluContextInfo.hpp" 26 #include "gluDefs.hpp" 27 #include "glwEnums.hpp" 28 #include "glwFunctions.hpp" 29 #include "tcuTestLog.hpp" 30 #include <cmath> 31 #include <cstring> 32 33 namespace glcts 34 { 35 /** Constructor 36 * 37 * @param context Test context 38 **/ 39 TessellationShaderPropertiesDefaultContextWideValues::TessellationShaderPropertiesDefaultContextWideValues( 40 Context& context, const ExtParameters& extParams) 41 : TestCaseBase(context, extParams, "default_values_of_context_wide_properties", 42 "Verifies default values of context-wide tessellation stage properties") 43 { 44 /* Left blank on purpose */ 45 } 46 47 /** Executes the test. 48 * 49 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 50 * 51 * Note the function throws exception should an error occur! 52 * 53 * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 54 **/ 55 tcu::TestNode::IterateResult TessellationShaderPropertiesDefaultContextWideValues::iterate(void) 56 { 57 /* Do not execute if required extensions are not supported. */ 58 if (!m_is_tessellation_shader_supported) 59 { 60 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 61 } 62 63 /* Iterate through all context-wide properties and compare expected values 64 * against the reference ones 65 */ 66 const float epsilon = (float)1e-5; 67 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 68 69 const glw::GLint property_value_data[] = { /* pname */ /* n components */ /* default value */ 70 static_cast<glw::GLint>(m_glExtTokens.PATCH_VERTICES), 1, 3, 71 /* The following values are only applicable to Desktop OpenGL. */ 72 GL_PATCH_DEFAULT_OUTER_LEVEL, 4, 1, GL_PATCH_DEFAULT_INNER_LEVEL, 2, 1 }; 73 74 const unsigned int n_properties = (glu::isContextTypeES(m_context.getRenderContext().getType())) ? 1 : 3; 75 76 for (unsigned int n_property = 0; n_property < n_properties; ++n_property) 77 { 78 glw::GLboolean bool_value[4] = { GL_FALSE }; 79 glw::GLfloat float_value[4] = { 0.0f }; 80 glw::GLint int_value[4] = { 0 }; 81 82 glw::GLenum pname = property_value_data[n_property * 3 + 0]; 83 glw::GLint n_components = property_value_data[n_property * 3 + 1]; 84 glw::GLint expected_value = property_value_data[n_property * 3 + 2]; 85 86 /* Call all relevant getters */ 87 gl.getBooleanv(pname, bool_value); 88 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() failed."); 89 90 gl.getFloatv(pname, float_value); 91 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() failed."); 92 93 gl.getIntegerv(pname, int_value); 94 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed."); 95 96 /* Compare retrieved vector value components against expected value */ 97 glw::GLboolean expected_bool_value[4] = { 98 (expected_value != 0) ? (glw::GLboolean)GL_TRUE : (glw::GLboolean)GL_FALSE, 99 (expected_value != 0) ? (glw::GLboolean)GL_TRUE : (glw::GLboolean)GL_FALSE, 100 (expected_value != 0) ? (glw::GLboolean)GL_TRUE : (glw::GLboolean)GL_FALSE, 101 (expected_value != 0) ? (glw::GLboolean)GL_TRUE : (glw::GLboolean)GL_FALSE 102 }; 103 glw::GLint expected_int_value[4] = { expected_value, expected_value, expected_value, expected_value }; 104 105 if (memcmp(expected_bool_value, bool_value, sizeof(bool) * n_components) != 0) 106 { 107 m_testCtx.getLog() << tcu::TestLog::Message << "glGetBooleanv() called for pname " << pname 108 << " reported invalid value." << tcu::TestLog::EndMessage; 109 110 TCU_FAIL("Invalid value reported by glGetBooleanv()"); 111 } 112 113 if (memcmp(expected_int_value, int_value, sizeof(int) * n_components) != 0) 114 { 115 m_testCtx.getLog() << tcu::TestLog::Message << "glGetIntegerv() called for pname " << pname 116 << " reported invalid value." << tcu::TestLog::EndMessage; 117 118 TCU_FAIL("Invalid value reported by glGetIntegerv()"); 119 } 120 121 if ((n_components >= 1 && de::abs(float_value[0] - (float)expected_value) > epsilon) || 122 (n_components >= 2 && de::abs(float_value[1] - (float)expected_value) > epsilon) || 123 (n_components >= 3 && de::abs(float_value[2] - (float)expected_value) > epsilon) || 124 (n_components >= 4 && de::abs(float_value[3] - (float)expected_value) > epsilon)) 125 { 126 m_testCtx.getLog() << tcu::TestLog::Message << "glGetFloatv() called for pname " << pname 127 << " reported invalid value." << tcu::TestLog::EndMessage; 128 129 TCU_FAIL("Invalid value reported by glGetFloatv()"); 130 } 131 } /* for (all properties) */ 132 133 /* All done */ 134 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 135 return STOP; 136 } 137 138 /** Constructor 139 * 140 * @param context Test context 141 **/ 142 TessellationShaderPropertiesProgramObject::TessellationShaderPropertiesProgramObject(Context& context, 143 const ExtParameters& extParams) 144 : TestCaseBase(context, extParams, "program_object_properties", 145 "Verifies tessellation-specific properties of program objects are reported correctly.") 146 , m_fs_id(0) 147 , m_po_id(0) 148 , m_tc_id(0) 149 , m_te_id(0) 150 , m_vs_id(0) 151 { 152 /* Left blank on purpose */ 153 } 154 155 /** Deinitializes ES objects created for the test */ 156 void TessellationShaderPropertiesProgramObject::deinit(void) 157 { 158 /* Call base class' deinit() */ 159 TestCaseBase::deinit(); 160 161 /* Release any ES objects created */ 162 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 163 164 if (m_fs_id != 0) 165 { 166 gl.deleteShader(m_fs_id); 167 168 m_fs_id = 0; 169 } 170 171 if (m_po_id != 0) 172 { 173 gl.deleteProgram(m_po_id); 174 175 m_po_id = 0; 176 } 177 178 if (m_tc_id != 0) 179 { 180 gl.deleteShader(m_tc_id); 181 182 m_tc_id = 0; 183 } 184 185 if (m_te_id != 0) 186 { 187 gl.deleteShader(m_te_id); 188 189 m_te_id = 0; 190 } 191 192 if (m_vs_id != 0) 193 { 194 gl.deleteShader(m_vs_id); 195 196 m_vs_id = 0; 197 } 198 } 199 200 /** Initializes ES objects necessary to execute the test */ 201 void TessellationShaderPropertiesProgramObject::initTest(void) 202 { 203 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 204 205 /* Do not execute if required extension is not supported */ 206 if (!m_is_tessellation_shader_supported) 207 { 208 return; 209 } 210 211 /* Generate all objects */ 212 m_po_id = gl.createProgram(); 213 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed"); 214 215 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 216 m_tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER); 217 m_te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER); 218 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 219 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed"); 220 221 /* Attach the shader to the program object */ 222 gl.attachShader(m_po_id, m_fs_id); 223 gl.attachShader(m_po_id, m_tc_id); 224 gl.attachShader(m_po_id, m_te_id); 225 gl.attachShader(m_po_id, m_vs_id); 226 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed"); 227 228 /* Since this test does not care much about fragment & vertex shaders, set 229 * their bodies and compile these shaders now */ 230 const char* fs_body = "${VERSION}\n" 231 "\n" 232 "void main()\n" 233 "{\n" 234 "}\n"; 235 236 const char* vs_body = "${VERSION}\n" 237 "\n" 238 "void main()\n" 239 "{\n" 240 "}\n"; 241 242 glw::GLint fs_compile_status = GL_FALSE; 243 glw::GLint vs_compile_status = GL_FALSE; 244 245 shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body); 246 shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body); 247 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed"); 248 249 gl.compileShader(m_fs_id); 250 gl.compileShader(m_vs_id); 251 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed"); 252 253 gl.getShaderiv(m_fs_id, GL_COMPILE_STATUS, &fs_compile_status); 254 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &vs_compile_status); 255 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed"); 256 257 if (fs_compile_status != GL_TRUE) 258 { 259 TCU_FAIL("Could not compile fragment shader"); 260 } 261 262 if (vs_compile_status != GL_TRUE) 263 { 264 TCU_FAIL("Could not compile vertex shader"); 265 } 266 } 267 268 /** Executes the test. 269 * 270 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 271 * 272 * Note the function throws exception should an error occur! 273 * 274 * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 275 **/ 276 tcu::TestNode::IterateResult TessellationShaderPropertiesProgramObject::iterate(void) 277 { 278 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 279 280 /* Do not execute if required extensions are not supported. */ 281 if (!m_is_tessellation_shader_supported) 282 { 283 throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED); 284 } 285 286 /* Initialize ES test objects */ 287 initTest(); 288 289 /* Test 1: Default values. Values as per spec, define as little qualifiers as possible */ 290 _test_descriptor test_1; 291 292 test_1.expected_control_output_vertices_value = 4; 293 test_1.expected_gen_mode_value = m_glExtTokens.QUADS; 294 test_1.expected_gen_point_mode_value = GL_FALSE; 295 test_1.expected_gen_spacing_value = GL_EQUAL; 296 test_1.expected_gen_vertex_order_value = GL_CCW; 297 test_1.tc_body = "${VERSION}\n" 298 "${TESSELLATION_SHADER_REQUIRE}\n" 299 "\n" 300 "layout(vertices=4) out;\n" 301 "\n" 302 "void main()\n" 303 "{\n" 304 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 305 "}\n"; 306 test_1.te_body = "${VERSION}\n" 307 "${TESSELLATION_SHADER_REQUIRE}\n" 308 "\n" 309 "layout(quads) in;\n" 310 "\n" 311 "void main()\n" 312 "{\n" 313 " gl_Position = gl_in[0].gl_Position;\n" 314 "}\n"; 315 316 /* Test 2: 16 vertices per patch + isolines + fractional_even_spacing + cw combination */ 317 _test_descriptor test_2; 318 319 test_2.expected_control_output_vertices_value = 16; 320 test_2.expected_gen_mode_value = m_glExtTokens.ISOLINES; 321 test_2.expected_gen_point_mode_value = GL_FALSE; 322 test_2.expected_gen_spacing_value = m_glExtTokens.FRACTIONAL_EVEN; 323 test_2.expected_gen_vertex_order_value = GL_CW; 324 test_2.tc_body = "${VERSION}\n" 325 "${TESSELLATION_SHADER_REQUIRE}\n" 326 "\n" 327 "layout(vertices=16) out;\n" 328 "\n" 329 "void main()\n" 330 "{\n" 331 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 332 "}\n"; 333 test_2.te_body = "${VERSION}\n" 334 "${TESSELLATION_SHADER_REQUIRE}\n" 335 "\n" 336 "layout(isolines, fractional_even_spacing, cw) in;\n" 337 "\n" 338 "void main()\n" 339 "{\n" 340 " gl_Position = gl_in[0].gl_Position;\n" 341 "}\n"; 342 343 /* Test 3: 32 vertices per patch + triangles + fractional_odd_spacing + ccw combination + point mode*/ 344 _test_descriptor test_3; 345 346 test_3.expected_control_output_vertices_value = 32; 347 test_3.expected_gen_mode_value = GL_TRIANGLES; 348 test_3.expected_gen_point_mode_value = GL_TRUE; 349 test_3.expected_gen_spacing_value = m_glExtTokens.FRACTIONAL_ODD; 350 test_3.expected_gen_vertex_order_value = GL_CCW; 351 test_3.tc_body = "${VERSION}\n" 352 "${TESSELLATION_SHADER_REQUIRE}\n" 353 "\n" 354 "layout(vertices=32) out;\n" 355 "\n" 356 "void main()\n" 357 "{\n" 358 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 359 "}\n"; 360 test_3.te_body = "${VERSION}\n" 361 "${TESSELLATION_SHADER_REQUIRE}\n" 362 "\n" 363 "layout(triangles, fractional_odd_spacing, ccw, point_mode) in;\n" 364 "\n" 365 "void main()\n" 366 "{\n" 367 " gl_Position = gl_in[0].gl_Position;\n" 368 "}\n"; 369 370 /* Test 4: 8 vertices per patch + quads + equal_spacing + ccw combination + point mode*/ 371 _test_descriptor test_4; 372 373 test_4.expected_control_output_vertices_value = 8; 374 test_4.expected_gen_mode_value = m_glExtTokens.QUADS; 375 test_4.expected_gen_point_mode_value = GL_TRUE; 376 test_4.expected_gen_spacing_value = GL_EQUAL; 377 test_4.expected_gen_vertex_order_value = GL_CCW; 378 test_4.tc_body = "${VERSION}\n" 379 "${TESSELLATION_SHADER_REQUIRE}\n" 380 "\n" 381 "layout(vertices=8) out;\n" 382 "\n" 383 "void main()\n" 384 "{\n" 385 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 386 "}\n"; 387 test_4.te_body = "${VERSION}\n" 388 "${TESSELLATION_SHADER_REQUIRE}\n" 389 "\n" 390 "layout(quads, equal_spacing, ccw, point_mode) in;\n" 391 "\n" 392 "void main()\n" 393 "{\n" 394 " gl_Position = gl_in[0].gl_Position;\n" 395 "}\n"; 396 397 /* Store all tests in a single vector */ 398 _tests tests; 399 400 tests.push_back(test_1); 401 tests.push_back(test_2); 402 tests.push_back(test_3); 403 tests.push_back(test_4); 404 405 /* Iterate through all the tests and verify the values reported */ 406 for (_tests_const_iterator test_iterator = tests.begin(); test_iterator != tests.end(); test_iterator++) 407 { 408 const _test_descriptor& test = *test_iterator; 409 410 /* Set tessellation control & evaluation shader bodies. */ 411 shaderSourceSpecialized(m_tc_id, 1 /* count */, &test.tc_body); 412 shaderSourceSpecialized(m_te_id, 1 /* count */, &test.te_body); 413 414 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed"); 415 416 /* Compile the shaders */ 417 gl.compileShader(m_tc_id); 418 gl.compileShader(m_te_id); 419 420 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed"); 421 422 /* Make sure the shaders compiled */ 423 glw::GLint tc_compile_status = GL_FALSE; 424 glw::GLint te_compile_status = GL_FALSE; 425 426 gl.getShaderiv(m_tc_id, GL_COMPILE_STATUS, &tc_compile_status); 427 gl.getShaderiv(m_te_id, GL_COMPILE_STATUS, &te_compile_status); 428 429 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed"); 430 431 if (tc_compile_status != GL_TRUE) 432 { 433 TCU_FAIL("Could not compile tessellation control shader"); 434 } 435 436 if (te_compile_status != GL_TRUE) 437 { 438 TCU_FAIL("Could not compile tessellation evaluation shader"); 439 } 440 441 /* Try to link the program object */ 442 glw::GLint link_status = GL_FALSE; 443 444 gl.linkProgram(m_po_id); 445 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed"); 446 447 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); 448 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed"); 449 450 if (link_status != GL_TRUE) 451 { 452 TCU_FAIL("Program linking failed"); 453 } 454 455 /* Query the tessellation properties of the program object and make sure 456 * the values reported are valid */ 457 glw::GLint control_output_vertices_value = 0; 458 glw::GLint gen_mode_value = GL_NONE; 459 glw::GLint gen_spacing_value = GL_NONE; 460 glw::GLint gen_vertex_order_value = GL_NONE; 461 glw::GLint gen_point_mode_value = GL_NONE; 462 463 gl.getProgramiv(m_po_id, m_glExtTokens.TESS_CONTROL_OUTPUT_VERTICES, &control_output_vertices_value); 464 gl.getProgramiv(m_po_id, m_glExtTokens.TESS_GEN_MODE, &gen_mode_value); 465 gl.getProgramiv(m_po_id, m_glExtTokens.TESS_GEN_SPACING, &gen_spacing_value); 466 gl.getProgramiv(m_po_id, m_glExtTokens.TESS_GEN_POINT_MODE, &gen_point_mode_value); 467 gl.getProgramiv(m_po_id, m_glExtTokens.TESS_GEN_VERTEX_ORDER, &gen_vertex_order_value); 468 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() for tessellation-specific properties failed."); 469 470 if (control_output_vertices_value != test.expected_control_output_vertices_value) 471 { 472 m_testCtx.getLog() << tcu::TestLog::Message 473 << "Invalid value reported for GL_TESS_CONTROL_OUTPUT_VERTICES_EXT property; " 474 << " expected: " << test.expected_control_output_vertices_value 475 << ", retrieved: " << control_output_vertices_value << tcu::TestLog::EndMessage; 476 477 TCU_FAIL("Invalid value reported for GL_TESS_CONTROL_OUTPUT_VERTICES_EXT property."); 478 } 479 480 if ((glw::GLuint)gen_mode_value != test.expected_gen_mode_value) 481 { 482 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported for GL_TESS_GEN_MODE_EXT property; " 483 << " expected: " << test.expected_gen_mode_value << ", retrieved: " << gen_mode_value 484 << tcu::TestLog::EndMessage; 485 486 TCU_FAIL("Invalid value reported for GL_TESS_GEN_MODE_EXT property."); 487 } 488 489 if ((glw::GLuint)gen_spacing_value != test.expected_gen_spacing_value) 490 { 491 m_testCtx.getLog() << tcu::TestLog::Message 492 << "Invalid value reported for GL_TESS_GEN_SPACING_EXT property; " 493 << " expected: " << test.expected_gen_spacing_value 494 << ", retrieved: " << gen_spacing_value << tcu::TestLog::EndMessage; 495 496 TCU_FAIL("Invalid value reported for GL_TESS_GEN_SPACING_EXT property."); 497 } 498 499 if ((glw::GLuint)gen_point_mode_value != test.expected_gen_point_mode_value) 500 { 501 m_testCtx.getLog() << tcu::TestLog::Message 502 << "Invalid value reported for GL_TESS_GEN_POINT_MODE_EXT property; " 503 << " expected: " << test.expected_gen_point_mode_value 504 << ", retrieved: " << gen_point_mode_value << tcu::TestLog::EndMessage; 505 506 TCU_FAIL("Invalid value reported for GL_TESS_GEN_POINT_MODE_EXT property."); 507 } 508 509 if ((glw::GLuint)gen_vertex_order_value != test.expected_gen_vertex_order_value) 510 { 511 m_testCtx.getLog() << tcu::TestLog::Message 512 << "Invalid value reported for GL_TESS_GEN_VERTEX_ORDER_EXT property; " 513 << " expected: " << test.expected_gen_vertex_order_value 514 << ", retrieved: " << gen_vertex_order_value << tcu::TestLog::EndMessage; 515 516 TCU_FAIL("Invalid value reported for GL_TESS_GEN_VERTEX_ORDER_EXT property."); 517 } 518 } /* for (all test descriptors) */ 519 520 /* All done */ 521 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 522 return STOP; 523 } 524 525 } /* namespace glcts */ 526