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 "esextcTestCaseBase.hpp" 25 #include "gluContextInfo.hpp" 26 #include "glwEnums.hpp" 27 #include "glwFunctions.hpp" 28 #include "tcuStringTemplate.hpp" 29 #include "tcuTestLog.hpp" 30 #include <algorithm> 31 #include <cstdarg> 32 #include <iostream> 33 34 namespace glcts 35 { 36 37 /* Predefined shader source code */ 38 const char* TestCaseBase::m_boilerplate_vs_code = "${VERSION}\n" 39 "\n" 40 "precision highp float;\n" 41 "\n" 42 "void main()\n" 43 "{\n" 44 " gl_Position = vec4(gl_VertexID, 0, 0, 1);\n" 45 "}\n"; 46 47 const float TestCaseBase::m_epsilon_float = 0.0001f; 48 49 /** Constructor 50 * 51 * @param context Test context 52 * @param name Test case's name 53 * @param description Test case's description 54 **/ 55 TestCaseBase::TestCaseBase(Context& context, const ExtParameters& extParam, const char* name, const char* description) 56 : tcu::TestCase(context.getTestContext(), name, description) 57 , m_context(context) 58 , m_glslVersion(extParam.glslVersion) 59 , m_extType(extParam.extType) 60 , m_is_framebuffer_no_attachments_supported(false) 61 , m_is_geometry_shader_extension_supported(false) 62 , m_is_geometry_shader_point_size_supported(false) 63 , m_is_gpu_shader5_supported(false) 64 , m_is_program_interface_query_supported(false) 65 , m_is_shader_image_load_store_supported(false) 66 , m_is_shader_image_atomic_supported(false) 67 , m_is_texture_storage_multisample_supported(false) 68 , m_is_texture_storage_multisample_2d_array_supported(false) 69 , m_is_tessellation_shader_supported(false) 70 , m_is_tessellation_shader_point_size_supported(false) 71 , m_is_texture_cube_map_array_supported(false) 72 , m_is_texture_border_clamp_supported(false) 73 , m_is_texture_buffer_supported(false) 74 , m_is_viewport_array_supported(false) 75 , seed_value(1) 76 { 77 m_glExtTokens.init(context.getRenderContext().getType()); 78 } 79 80 /** Initializes base class that all geometry shader test implementations derive from. 81 * 82 **/ 83 void TestCaseBase::init(void) 84 { 85 initExtensions(); 86 initGLSLSpecializationMap(); 87 } 88 89 /** Initializes function pointers for ES3.1 extensions, as well as determines 90 * availability of these extensions. 91 **/ 92 void TestCaseBase::initExtensions() 93 { 94 const glu::ContextType& context_type = m_context.getRenderContext().getType(); 95 96 /* OpenGL 4.0 or higher is minimum expectation for any of these tests */ 97 if (glu::contextSupports(context_type, glu::ApiType::core(4, 0))) 98 { 99 m_is_geometry_shader_extension_supported = true; 100 m_is_geometry_shader_point_size_supported = true; 101 m_is_gpu_shader5_supported = true; 102 m_is_tessellation_shader_supported = true; 103 m_is_tessellation_shader_point_size_supported = true; 104 m_is_texture_cube_map_array_supported = true; 105 m_is_texture_border_clamp_supported = true; 106 m_is_texture_buffer_supported = true; 107 m_is_shader_image_atomic_supported = glu::contextSupports(context_type, glu::ApiType::core(4, 2)); 108 m_is_texture_storage_multisample_2d_array_supported = 109 glu::contextSupports(context_type, glu::ApiType::core(4, 3)); 110 m_is_framebuffer_no_attachments_supported = glu::contextSupports(context_type, glu::ApiType::core(4, 3)); 111 m_is_program_interface_query_supported = glu::contextSupports(context_type, glu::ApiType::core(4, 3)); 112 m_is_texture_storage_multisample_supported = glu::contextSupports(context_type, glu::ApiType::core(4, 3)); 113 m_is_shader_image_load_store_supported = glu::contextSupports(context_type, glu::ApiType::core(4, 2)); 114 m_is_viewport_array_supported = glu::contextSupports(context_type, glu::ApiType::core(4, 1)); 115 } 116 else if (glu::contextSupports(context_type, glu::ApiType::es(3, 2))) 117 { 118 m_is_geometry_shader_extension_supported = true; 119 m_is_gpu_shader5_supported = true; 120 m_is_tessellation_shader_supported = true; 121 m_is_texture_cube_map_array_supported = true; 122 m_is_texture_border_clamp_supported = true; 123 m_is_texture_buffer_supported = true; 124 m_is_shader_image_atomic_supported = true; 125 m_is_texture_storage_multisample_2d_array_supported = true; 126 m_is_framebuffer_no_attachments_supported = true; 127 m_is_program_interface_query_supported = true; 128 m_is_texture_storage_multisample_supported = true; 129 m_is_shader_image_load_store_supported = true; 130 m_is_geometry_shader_point_size_supported = 131 isExtensionSupported("GL_OES_geometry_point_size") || isExtensionSupported("GL_EXT_geometry_point_size"); 132 m_is_tessellation_shader_point_size_supported = isExtensionSupported("GL_OES_tessellation_point_size") || 133 isExtensionSupported("GL_EXT_tessellation_point_size"); 134 m_is_viewport_array_supported = isExtensionSupported("GL_OES_viewport_array"); 135 } 136 else 137 { 138 /* ES3.1 core functionality is assumed*/ 139 DE_ASSERT(isContextTypeES(context_type)); 140 DE_ASSERT(glu::contextSupports(context_type, glu::ApiType::es(3, 1))); 141 142 /* these are part of ES 3.1 */ 143 m_is_framebuffer_no_attachments_supported = true; 144 m_is_program_interface_query_supported = true; 145 m_is_texture_storage_multisample_supported = true; 146 m_is_shader_image_load_store_supported = true; 147 148 /* AEP extensions - either test OES variants or EXT variants */ 149 if (m_extType == EXTENSIONTYPE_OES) 150 { 151 /* These are all ES 3.1 extensions */ 152 m_is_geometry_shader_extension_supported = isExtensionSupported("GL_OES_geometry_shader"); 153 m_is_geometry_shader_point_size_supported = isExtensionSupported("GL_OES_geometry_point_size"); 154 m_is_gpu_shader5_supported = isExtensionSupported("GL_OES_gpu_shader5"); 155 m_is_tessellation_shader_supported = isExtensionSupported("GL_OES_tessellation_shader"); 156 m_is_tessellation_shader_point_size_supported = isExtensionSupported("GL_OES_tessellation_point_size"); 157 m_is_texture_cube_map_array_supported = isExtensionSupported("GL_OES_texture_cube_map_array"); 158 m_is_texture_border_clamp_supported = isExtensionSupported("GL_OES_texture_border_clamp"); 159 m_is_texture_buffer_supported = isExtensionSupported("GL_OES_texture_buffer"); 160 } 161 else 162 { 163 DE_ASSERT(m_extType == EXTENSIONTYPE_EXT); 164 165 /* These are all ES 3.1 extensions */ 166 m_is_geometry_shader_extension_supported = isExtensionSupported("GL_EXT_geometry_shader"); 167 m_is_geometry_shader_point_size_supported = isExtensionSupported("GL_EXT_geometry_point_size"); 168 m_is_gpu_shader5_supported = isExtensionSupported("GL_EXT_gpu_shader5"); 169 m_is_tessellation_shader_supported = isExtensionSupported("GL_EXT_tessellation_shader"); 170 m_is_tessellation_shader_point_size_supported = isExtensionSupported("GL_EXT_tessellation_point_size"); 171 m_is_texture_cube_map_array_supported = isExtensionSupported("GL_EXT_texture_cube_map_array"); 172 m_is_texture_border_clamp_supported = isExtensionSupported("GL_EXT_texture_border_clamp"); 173 m_is_texture_buffer_supported = isExtensionSupported("GL_EXT_texture_buffer"); 174 } 175 176 /* other ES 3.1 extensions */ 177 m_is_shader_image_atomic_supported = isExtensionSupported("GL_OES_shader_image_atomic"); 178 m_is_texture_storage_multisample_2d_array_supported = 179 isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"); 180 m_is_viewport_array_supported = isExtensionSupported("GL_OES_viewport_array"); 181 } 182 } 183 184 /** Initializes function pointers for ES3.1 extensions, as well as determines 185 * availability of these extensions. 186 **/ 187 void TestCaseBase::initGLSLSpecializationMap() 188 { 189 m_specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(m_glslVersion); 190 m_specializationMap["SHADER_IO_BLOCKS_ENABLE"] = 191 getGLSLExtDirective(m_extType, EXTENSIONNAME_SHADER_IO_BLOCKS, EXTENSIONBEHAVIOR_ENABLE); 192 m_specializationMap["SHADER_IO_BLOCKS_REQUIRE"] = 193 getGLSLExtDirective(m_extType, EXTENSIONNAME_SHADER_IO_BLOCKS, EXTENSIONBEHAVIOR_REQUIRE); 194 m_specializationMap["GEOMETRY_SHADER_ENABLE"] = 195 getGLSLExtDirective(m_extType, EXTENSIONNAME_GEOMETRY_SHADER, EXTENSIONBEHAVIOR_ENABLE); 196 m_specializationMap["GEOMETRY_SHADER_REQUIRE"] = 197 getGLSLExtDirective(m_extType, EXTENSIONNAME_GEOMETRY_SHADER, EXTENSIONBEHAVIOR_REQUIRE); 198 m_specializationMap["GEOMETRY_POINT_SIZE_ENABLE"] = 199 getGLSLExtDirective(m_extType, EXTENSIONNAME_GEOMETRY_POINT_SIZE, EXTENSIONBEHAVIOR_ENABLE); 200 m_specializationMap["GEOMETRY_POINT_SIZE_REQUIRE"] = 201 getGLSLExtDirective(m_extType, EXTENSIONNAME_GEOMETRY_POINT_SIZE, EXTENSIONBEHAVIOR_REQUIRE); 202 m_specializationMap["TESSELLATION_SHADER_ENABLE"] = 203 getGLSLExtDirective(m_extType, EXTENSIONNAME_TESSELLATION_SHADER, EXTENSIONBEHAVIOR_ENABLE); 204 m_specializationMap["TESSELLATION_SHADER_REQUIRE"] = 205 getGLSLExtDirective(m_extType, EXTENSIONNAME_TESSELLATION_SHADER, EXTENSIONBEHAVIOR_REQUIRE); 206 m_specializationMap["TESSELLATION_POINT_SIZE_ENABLE"] = 207 getGLSLExtDirective(m_extType, EXTENSIONNAME_TESSELLATION_POINT_SIZE, EXTENSIONBEHAVIOR_ENABLE); 208 m_specializationMap["TESSELLATION_POINT_SIZE_REQUIRE"] = 209 getGLSLExtDirective(m_extType, EXTENSIONNAME_TESSELLATION_POINT_SIZE, EXTENSIONBEHAVIOR_REQUIRE); 210 m_specializationMap["GPU_SHADER5_ENABLE"] = 211 getGLSLExtDirective(m_extType, EXTENSIONNAME_GPU_SHADER5, EXTENSIONBEHAVIOR_ENABLE); 212 m_specializationMap["GPU_SHADER5_REQUIRE"] = 213 getGLSLExtDirective(m_extType, EXTENSIONNAME_GPU_SHADER5, EXTENSIONBEHAVIOR_REQUIRE); 214 m_specializationMap["TEXTURE_BUFFER_ENABLE"] = 215 getGLSLExtDirective(m_extType, EXTENSIONNAME_TEXTURE_BUFFER, EXTENSIONBEHAVIOR_ENABLE); 216 m_specializationMap["TEXTURE_BUFFER_REQUIRE"] = 217 getGLSLExtDirective(m_extType, EXTENSIONNAME_TEXTURE_BUFFER, EXTENSIONBEHAVIOR_REQUIRE); 218 m_specializationMap["TEXTURE_CUBE_MAP_ARRAY_ENABLE"] = 219 getGLSLExtDirective(m_extType, EXTENSIONNAME_TEXTURE_CUBE_MAP_ARRAY, EXTENSIONBEHAVIOR_ENABLE); 220 m_specializationMap["TEXTURE_CUBE_MAP_ARRAY_REQUIRE"] = 221 getGLSLExtDirective(m_extType, EXTENSIONNAME_TEXTURE_CUBE_MAP_ARRAY, EXTENSIONBEHAVIOR_REQUIRE); 222 m_specializationMap["SHADER_IMAGE_ATOMIC_ENABLE"] = 223 getGLSLExtDirective(m_extType, EXTENSIONNAME_SHADER_IMAGE_ATOMIC, EXTENSIONBEHAVIOR_ENABLE); 224 m_specializationMap["SHADER_IMAGE_ATOMIC_REQUIRE"] = 225 getGLSLExtDirective(m_extType, EXTENSIONNAME_SHADER_IMAGE_ATOMIC, EXTENSIONBEHAVIOR_REQUIRE); 226 m_specializationMap["VIEWPORT_ARRAY_ENABLE"] = 227 getGLSLExtDirective(m_extType, EXTENSIONNAME_VIEWPORT_ARRAY, EXTENSIONBEHAVIOR_ENABLE); 228 m_specializationMap["VIEWPORT_ARRAY_REQUIRE"] = 229 getGLSLExtDirective(m_extType, EXTENSIONNAME_VIEWPORT_ARRAY, EXTENSIONBEHAVIOR_REQUIRE); 230 231 if (glu::isContextTypeES(m_context.getRenderContext().getType())) 232 { 233 m_specializationMap["IN_PER_VERTEX_DECL_ARRAY"] = "\n"; 234 m_specializationMap["IN_PER_VERTEX_DECL_ARRAY_POINT_SIZE"] = "\n"; 235 m_specializationMap["OUT_PER_VERTEX_DECL"] = "\n"; 236 m_specializationMap["OUT_PER_VERTEX_DECL_POINT_SIZE"] = "\n"; 237 m_specializationMap["OUT_PER_VERTEX_DECL_ARRAY"] = "\n"; 238 m_specializationMap["OUT_PER_VERTEX_DECL_ARRAY_POINT_SIZE"] = "\n"; 239 m_specializationMap["IN_DATA_DECL"] = "\n"; 240 m_specializationMap["POSITION_WITH_IN_DATA"] = "gl_Position = gl_in[0].gl_Position;\n"; 241 } 242 else 243 { 244 m_specializationMap["IN_PER_VERTEX_DECL_ARRAY"] = "in gl_PerVertex {\n" 245 " vec4 gl_Position;\n" 246 "} gl_in[];\n"; 247 m_specializationMap["IN_PER_VERTEX_DECL_ARRAY_POINT_SIZE"] = "in gl_PerVertex {\n" 248 " vec4 gl_Position;\n" 249 " float gl_PointSize;\n" 250 "} gl_in[];\n"; 251 m_specializationMap["OUT_PER_VERTEX_DECL"] = "out gl_PerVertex {\n" 252 " vec4 gl_Position;\n" 253 "};\n"; 254 m_specializationMap["OUT_PER_VERTEX_DECL_POINT_SIZE"] = "out gl_PerVertex {\n" 255 " vec4 gl_Position;\n" 256 " float gl_PointSize;\n" 257 "};\n"; 258 m_specializationMap["OUT_PER_VERTEX_DECL_ARRAY"] = "out gl_PerVertex {\n" 259 " vec4 gl_Position;\n" 260 "} gl_out[];\n"; 261 m_specializationMap["OUT_PER_VERTEX_DECL_ARRAY_POINT_SIZE"] = "out gl_PerVertex {\n" 262 " vec4 gl_Position;\n" 263 " float gl_PointSize;\n" 264 "} gl_out[];\n"; 265 m_specializationMap["IN_DATA_DECL"] = "in Data {\n" 266 " vec4 pos;\n" 267 "} input_data[1];\n"; 268 m_specializationMap["POSITION_WITH_IN_DATA"] = "gl_Position = input_data[0].pos;\n"; 269 } 270 } 271 272 /** Sets the seed for the random generator 273 * @param seed - seed for the random generator 274 */ 275 void TestCaseBase::randomSeed(const glw::GLuint seed) 276 { 277 seed_value = seed; 278 } 279 280 /** Returns random unsigned integer from the range [0,max) 281 * @param max - the value that is the upper boundary for the returned random numbers 282 * @return random unsigned integer from the range [0,max) 283 */ 284 glw::GLuint TestCaseBase::randomFormula(const glw::GLuint max) 285 { 286 static const glw::GLuint a = 11; 287 static const glw::GLuint b = 17; 288 289 seed_value = (a * seed_value + b) % max; 290 291 return seed_value; 292 } 293 294 /** Executes the test. 295 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 296 * 297 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 298 * 299 * Note the function throws exception should an error occur! 300 **/ 301 tcu::TestNode::IterateResult TestCaseBase::iterate(void) 302 { 303 qpTestResult result = QP_TEST_RESULT_FAIL; 304 305 m_testCtx.setTestResult(result, "This location should never be called."); 306 307 return STOP; 308 } 309 310 /** Deinitializes base class that all test implementations inherit from. 311 * 312 **/ 313 void TestCaseBase::deinit(void) 314 { 315 /* Left empty on purpose */ 316 } 317 318 /** Tells whether particular extension is supported. 319 * 320 * @param extName: The name of the extension 321 * 322 * @return true if given extension name is reported as supported, false otherwise. 323 **/ 324 bool TestCaseBase::isExtensionSupported(const std::string& extName) const 325 { 326 const std::vector<std::string>& extensions = m_context.getContextInfo().getExtensions(); 327 328 if (std::find(extensions.begin(), extensions.end(), extName) != extensions.end()) 329 { 330 return true; 331 } 332 333 return false; 334 } 335 336 /** Helper method for specializing a shader */ 337 std::string TestCaseBase::specializeShader(const unsigned int parts, const char* const* code) const 338 { 339 std::stringstream code_merged; 340 for (unsigned int i = 0; i < parts; i++) 341 { 342 code_merged << code[i]; 343 } 344 return tcu::StringTemplate(code_merged.str().c_str()).specialize(m_specializationMap); 345 } 346 347 void TestCaseBase::shaderSourceSpecialized(glw::GLuint shader_id, glw::GLsizei shader_count, 348 const glw::GLchar* const* shader_string) 349 { 350 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 351 352 std::string specialized = specializeShader(shader_count, shader_string); 353 const char* specialized_cstr = specialized.c_str(); 354 gl.shaderSource(shader_id, 1, &specialized_cstr, NULL); 355 } 356 357 std::string getShaderTypeName(glw::GLenum shader_type) 358 { 359 switch (shader_type) 360 { 361 case GL_VERTEX_SHADER: 362 return "Vertex shader"; 363 case GL_TESS_CONTROL_SHADER: 364 return "Tessellation control shader"; 365 case GL_TESS_EVALUATION_SHADER: 366 return "Tessellation evaluation shader"; 367 case GL_GEOMETRY_SHADER: 368 return "Geometry shader"; 369 case GL_FRAGMENT_SHADER: 370 return "Fragment shader"; 371 case GL_COMPUTE_SHADER: 372 return "Compute shader"; 373 default: 374 DE_ASSERT(0); 375 return "??? shader"; 376 } 377 } 378 379 /** Compiles and links program with variable amount of shaders 380 * 381 * @param po_id Program handle 382 * @param out_has_compilation_failed Deref will be set to true, if shader compilation 383 * failed for any of the submitted shaders. 384 * Will be set to false otherwise. Can be NULL. 385 * @param sh_stages Shader stages 386 * @for all shader stages 387 * { 388 * @param sh_id Shader handle. 0 means "skip" 389 * @param sh_parts Number of shader source code parts. 390 * 0 means that it's already compiled. 391 * @param sh_code Shader source code. 392 * } 393 **/ 394 bool TestCaseBase::buildProgramVA(glw::GLuint po_id, bool* out_has_compilation_failed, unsigned int sh_stages, ...) 395 { 396 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 397 std::vector<glw::GLuint> vec_sh_id; 398 399 va_list values; 400 va_start(values, sh_stages); 401 402 /* Shaders compilation */ 403 glw::GLint compilation_status = GL_FALSE; 404 405 for (unsigned int stage = 0; stage < sh_stages; ++stage) 406 { 407 glw::GLuint sh_id = va_arg(values, glw::GLuint); 408 unsigned int sh_parts = va_arg(values, unsigned int); 409 const char* const* sh_code = va_arg(values, const char* const*); 410 411 if (sh_id == 0) 412 { 413 continue; 414 } 415 416 if (sh_parts != 0) 417 { 418 std::string sh_merged_string = specializeShader(sh_parts, sh_code); 419 const char* sh_merged_ptr = sh_merged_string.c_str(); 420 421 gl.shaderSource(sh_id, 1, &sh_merged_ptr, NULL); 422 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed!"); 423 424 gl.compileShader(sh_id); 425 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed!"); 426 427 gl.getShaderiv(sh_id, GL_COMPILE_STATUS, &compilation_status); 428 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed!"); 429 430 if (compilation_status != GL_TRUE) 431 { 432 glw::GLint shader_type = 0; 433 std::string info_log = getCompilationInfoLog(sh_id); 434 435 gl.getShaderiv(sh_id, GL_SHADER_TYPE, &shader_type); 436 std::string shader_type_str = getShaderTypeName(shader_type); 437 438 m_testCtx.getLog() << tcu::TestLog::Message << shader_type_str << " compilation failure:\n\n" 439 << info_log << "\n\n" 440 << shader_type_str << " source:\n\n" 441 << sh_merged_string << "\n\n" 442 << tcu::TestLog::EndMessage; 443 444 break; 445 } 446 } 447 448 gl.attachShader(po_id, sh_id); 449 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader(VERTEX_SHADER) call failed"); 450 451 vec_sh_id.push_back(sh_id); 452 } 453 454 va_end(values); 455 456 if (out_has_compilation_failed != NULL) 457 { 458 *out_has_compilation_failed = (compilation_status == GL_FALSE); 459 } 460 461 if (compilation_status != GL_TRUE) 462 { 463 return false; 464 } 465 466 /* Linking the program */ 467 468 glw::GLint link_status = GL_FALSE; 469 gl.linkProgram(po_id); 470 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed!"); 471 472 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status); 473 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed!"); 474 475 if (link_status != GL_TRUE) 476 { 477 /* Dump link log */ 478 std::string link_log = getLinkingInfoLog(po_id); 479 m_testCtx.getLog() << tcu::TestLog::Message << "Link failure:\n\n" 480 << link_log << "\n\n" 481 << tcu::TestLog::EndMessage; 482 483 /* Dump shader source */ 484 for (std::vector<glw::GLuint>::iterator it = vec_sh_id.begin(); it != vec_sh_id.end(); ++it) 485 { 486 glw::GLint shader_type = 0; 487 gl.getShaderiv(*it, GL_SHADER_TYPE, &shader_type); 488 std::string shader_type_str = getShaderTypeName(shader_type); 489 std::string shader_source = getShaderSource(*it); 490 m_testCtx.getLog() << tcu::TestLog::Message << shader_type_str << " source:\n\n" 491 << shader_source << "\n\n" 492 << tcu::TestLog::EndMessage; 493 } 494 495 return false; 496 } 497 498 return true; 499 } 500 501 /** Builds an OpenGL ES program by configuring contents of 1 shader object, 502 * compiling it, attaching to specified program object, and finally 503 * by linking the program object. 504 * 505 * Implementation assumes all aforementioned objects have already been 506 * generated. 507 * 508 * @param po_id ID of program object 509 * @param sh1_shader_id ID of first shader to configure. 510 * @param n_sh1_body_parts Number of elements of @param sh1_body_parts array. 511 * @param sh1_body_parts Pointer to array of strings to make up first shader's body. 512 * Can be NULL. 513 * 514 * @return GTFtrue if successful, false otherwise. 515 */ 516 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts, 517 const char* const* sh1_body_parts, bool* out_has_compilation_failed) 518 { 519 return buildProgramVA(po_id, out_has_compilation_failed, 1, sh1_shader_id, n_sh1_body_parts, sh1_body_parts); 520 } 521 522 /** Builds an OpenGL ES program by configuring contents of 2 shader objects, 523 * compiling them, attaching to specified program object, and finally 524 * by linking the program object. 525 * 526 * Implementation assumes all aforementioned objects have already been 527 * generated. 528 * 529 * @param po_id ID of program object 530 * @param sh1_shader_id ID of first shader to configure. 531 * @param n_sh1_body_parts Number of elements of @param sh1_body_parts array. 532 * @param sh1_body_parts Pointer to array of strings to make up first shader's body. 533 * Can be NULL. 534 * @param sh2_shader_id ID of second shader to configure. 535 * @param n_sh2_body_parts Number of elements of @param sh2_body_parts array. 536 * @param sh2_body_parts Pointer to array of strings to make up second shader's body. 537 * Can be NULL. 538 * 539 * @return GTFtrue if successful, false otherwise. 540 */ 541 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts, 542 const char* const* sh1_body_parts, glw::GLuint sh2_shader_id, 543 unsigned int n_sh2_body_parts, const char* const* sh2_body_parts, 544 bool* out_has_compilation_failed) 545 { 546 return buildProgramVA(po_id, out_has_compilation_failed, 2, sh1_shader_id, n_sh1_body_parts, sh1_body_parts, 547 sh2_shader_id, n_sh2_body_parts, sh2_body_parts); 548 } 549 550 /** Builds an OpenGL ES program by configuring contents of 3 shader objects, 551 * compiling them, attaching to specified program object, and finally 552 * by linking the program object. 553 * 554 * Implementation assumes all aforementioned objects have already been 555 * generated. 556 * 557 * @param po_id ID of program object 558 * @param sh1_shader_id ID of first shader to configure. 559 * @param n_sh1_body_parts Number of elements of @param sh1_body_parts array. 560 * @param sh1_body_parts Pointer to array of strings to make up first shader's body. 561 * Can be NULL. 562 * @param sh2_shader_id ID of second shader to configure. 563 * @param n_sh2_body_parts Number of elements of @param sh2_body_parts array. 564 * @param sh2_body_parts Pointer to array of strings to make up second shader's body. 565 * Can be NULL. 566 * @param sh3_shader_id ID of third shader to configure. 567 * @param n_sh3_body_parts Number of elements of @param sh3_body_parts array. 568 * @param sh3_body_parts Pointer to array of strings to make up third shader's body. 569 * Can be NULL. 570 * @param has_compilation_failed Deref will be set to true if shader compilation failed, 571 * false if shader compilation was successful. Can be NULL. 572 * 573 * @return GTFtrue if successful, false otherwise. 574 */ 575 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts, 576 const char* const* sh1_body_parts, glw::GLuint sh2_shader_id, 577 unsigned int n_sh2_body_parts, const char* const* sh2_body_parts, 578 glw::GLuint sh3_shader_id, unsigned int n_sh3_body_parts, 579 const char* const* sh3_body_parts, bool* out_has_compilation_failed) 580 { 581 return buildProgramVA(po_id, out_has_compilation_failed, 3, sh1_shader_id, n_sh1_body_parts, sh1_body_parts, 582 sh2_shader_id, n_sh2_body_parts, sh2_body_parts, sh3_shader_id, n_sh3_body_parts, 583 sh3_body_parts); 584 } 585 586 /** Builds an OpenGL ES program by configuring contents of 4 shader objects, 587 * compiling them, attaching to specified program object, and finally 588 * by linking the program object. 589 * 590 * Implementation assumes all aforementioned objects have already been 591 * generated. 592 * 593 * @param po_id ID of program object 594 * @param sh1_shader_id ID of first shader to configure. 595 * @param n_sh1_body_parts Number of elements of @param sh1_body_parts array. 596 * @param sh1_body_parts Pointer to array of strings to make up first shader's body. 597 * Can be NULL. 598 * @param sh2_shader_id ID of second shader to configure. 599 * @param n_sh2_body_parts Number of elements of @param sh2_body_parts array. 600 * @param sh2_body_parts Pointer to array of strings to make up second shader's body. 601 * Can be NULL. 602 * @param sh3_shader_id ID of third shader to configure. 603 * @param n_sh3_body_parts Number of elements of @param sh3_body_parts array. 604 * @param sh3_body_parts Pointer to array of strings to make up third shader's body. 605 * Can be NULL. 606 * @param sh4_shader_id ID of fourth shader to configure. 607 * @param n_sh4_body_parts Number of elements of @param sh4_body_parts array. 608 * @param sh4_body_parts Pointer to array of strings to make up fourth shader's body. 609 * Can be NULL. 610 * 611 * @return GTFtrue if successful, false otherwise. 612 */ 613 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts, 614 const char* const* sh1_body_parts, glw::GLuint sh2_shader_id, 615 unsigned int n_sh2_body_parts, const char* const* sh2_body_parts, 616 glw::GLuint sh3_shader_id, unsigned int n_sh3_body_parts, 617 const char* const* sh3_body_parts, glw::GLuint sh4_shader_id, 618 unsigned int n_sh4_body_parts, const char* const* sh4_body_parts, 619 bool* out_has_compilation_failed) 620 { 621 return buildProgramVA(po_id, out_has_compilation_failed, 4, sh1_shader_id, n_sh1_body_parts, sh1_body_parts, 622 sh2_shader_id, n_sh2_body_parts, sh2_body_parts, sh3_shader_id, n_sh3_body_parts, 623 sh3_body_parts, sh4_shader_id, n_sh4_body_parts, sh4_body_parts); 624 } 625 626 /** Builds an OpenGL ES program by configuring contents of 5 shader objects, 627 * compiling them, attaching to specified program object, and finally 628 * by linking the program object. 629 * 630 * Implementation assumes all aforementioned objects have already been 631 * generated. 632 * 633 * @param po_id ID of program object 634 * @param sh1_shader_id ID of first shader to configure. 635 * @param n_sh1_body_parts Number of elements of @param sh1_body_parts array. 636 * @param sh1_body_parts Pointer to array of strings to make up first shader's body. 637 * Can be NULL. 638 * @param sh2_shader_id ID of second shader to configure. 639 * @param n_sh2_body_parts Number of elements of @param sh2_body_parts array. 640 * @param sh2_body_parts Pointer to array of strings to make up second shader's body. 641 * Can be NULL. 642 * @param sh3_shader_id ID of third shader to configure. 643 * @param n_sh3_body_parts Number of elements of @param sh3_body_parts array. 644 * @param sh3_body_parts Pointer to array of strings to make up third shader's body. 645 * Can be NULL. 646 * @param sh4_shader_id ID of fourth shader to configure. 647 * @param n_sh4_body_parts Number of elements of @param sh4_body_parts array. 648 * @param sh4_body_parts Pointer to array of strings to make up fourth shader's body. 649 * Can be NULL. 650 * @param sh5_shader_id ID of fifth shader to configure. 651 * @param n_sh5_body_parts Number of elements of @param sh5_body_parts array. 652 * @param sh5_body_parts Pointer to array of strings to make up fifth shader's body. 653 * Can be NULL. 654 * 655 * @return GTFtrue if successful, false otherwise. 656 */ 657 bool TestCaseBase::buildProgram(glw::GLuint po_id, glw::GLuint sh1_shader_id, unsigned int n_sh1_body_parts, 658 const char* const* sh1_body_parts, glw::GLuint sh2_shader_id, 659 unsigned int n_sh2_body_parts, const char* const* sh2_body_parts, 660 glw::GLuint sh3_shader_id, unsigned int n_sh3_body_parts, 661 const char* const* sh3_body_parts, glw::GLuint sh4_shader_id, 662 unsigned int n_sh4_body_parts, const char* const* sh4_body_parts, 663 glw::GLuint sh5_shader_id, unsigned int n_sh5_body_parts, 664 const char* const* sh5_body_parts, bool* out_has_compilation_failed) 665 { 666 return buildProgramVA(po_id, out_has_compilation_failed, 5, sh1_shader_id, n_sh1_body_parts, sh1_body_parts, 667 sh2_shader_id, n_sh2_body_parts, sh2_body_parts, sh3_shader_id, n_sh3_body_parts, 668 sh3_body_parts, sh4_shader_id, n_sh4_body_parts, sh4_body_parts, sh5_shader_id, 669 n_sh5_body_parts, sh5_body_parts); 670 } 671 672 /** Compare pixel's color with specified value. 673 * Assumptions: 674 * - size of each channel is 1 byte 675 * - channel order is R G B A 676 * - lines are stored one after another, without any additional data 677 * 678 * @param buffer Image data 679 * @param x X coordinate of pixel 680 * @param y Y coordinate of pixel 681 * @param width Image width 682 * @param height Image height 683 * @param pixel_size Size of single pixel in bytes, eg. for RGBA8 it should be set to 4 684 * @param expected_red Expected value of red channel, default is 0 685 * @param expected_green Expected value of green channel, default is 0 686 * @param expected_blue Expected value of blue channel, default is 0 687 * @param expected_alpha Expected value of alpha channel, default is 0 688 * 689 * @retrun true When pixel color matches expected values 690 * false When: 691 * - buffer is null_ptr 692 * - offset of pixel exceeds size of image 693 * - pixel_size is not in range <1 ; 4> 694 * - pixel color does not match expected values 695 **/ 696 bool TestCaseBase::comparePixel(const unsigned char* buffer, unsigned int x, unsigned int y, unsigned int width, 697 unsigned int height, unsigned int pixel_size, unsigned char expected_red, 698 unsigned char expected_green, unsigned char expected_blue, 699 unsigned char expected_alpha) const 700 { 701 const unsigned int line_size = width * pixel_size; 702 const unsigned int image_size = height * line_size; 703 const unsigned int texel_offset = y * line_size + x * pixel_size; 704 705 bool result = true; 706 707 /* Sanity checks */ 708 if (0 == buffer) 709 { 710 return false; 711 } 712 713 if (image_size < texel_offset) 714 { 715 return false; 716 } 717 718 switch (pixel_size) 719 { 720 /* Fall through by design */ 721 case 4: 722 { 723 result &= (expected_alpha == buffer[texel_offset + 3]); 724 } 725 /* Fallthrough */ 726 727 case 3: 728 { 729 result &= (expected_blue == buffer[texel_offset + 2]); 730 } 731 /* Fallthrough */ 732 733 case 2: 734 { 735 result &= (expected_green == buffer[texel_offset + 1]); 736 } 737 /* Fallthrough */ 738 739 case 1: 740 { 741 result &= (expected_red == buffer[texel_offset + 0]); 742 743 break; 744 } 745 746 default: 747 { 748 return false; 749 } 750 } /* switch (pixel_size) */ 751 752 return result; 753 } 754 755 /** Checks whether a combination of fragment/geometry/vertex shader objects compiles and links into a program 756 * 757 * @param n_fs_body_parts Number of elements of @param fs_body_parts array. 758 * @param fs_body_parts Pointer to array of strings to make up fragment shader's body. 759 * Must not be NULL. 760 * 761 * @param n_gs_body_parts Number of elements of @param gs_body_parts array. 762 * @param gs_body_parts Pointer to array of strings to make up geometry shader's body. 763 * Can be NULL. 764 * 765 * @param n_vs_body_parts Number of elements of @param vs_body_parts array. 766 * @param vs_body_parts Pointer to array of strings to make up vertex shader's body. 767 * Must not be NULL. 768 * 769 * @return true if program creation was successful, false otherwise. 770 **/ 771 bool TestCaseBase::doesProgramBuild(unsigned int n_fs_body_parts, const char* const* fs_body_parts, 772 unsigned int n_gs_body_parts, const char* const* gs_body_parts, 773 unsigned int n_vs_body_parts, const char* const* vs_body_parts) 774 { 775 /* General variables */ 776 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 777 bool result = false; 778 779 /* Shaders */ 780 glw::GLuint vertex_shader_id = 0; 781 glw::GLuint geometry_shader_id = 0; 782 glw::GLuint fragment_shader_id = 0; 783 784 /* Program */ 785 glw::GLuint program_object_id = 0; 786 787 /* Create shaders */ 788 vertex_shader_id = gl.createShader(GL_VERTEX_SHADER); 789 geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 790 fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER); 791 792 /* Create program */ 793 program_object_id = gl.createProgram(); 794 795 /* Check createProgram call for errors */ 796 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 797 798 /* Compile and link the program */ 799 result = buildProgram(program_object_id, fragment_shader_id, n_fs_body_parts, fs_body_parts, geometry_shader_id, 800 n_gs_body_parts, gs_body_parts, vertex_shader_id, n_vs_body_parts, vs_body_parts); 801 802 if (program_object_id != 0) 803 gl.deleteProgram(program_object_id); 804 if (fragment_shader_id != 0) 805 gl.deleteShader(fragment_shader_id); 806 if (geometry_shader_id != 0) 807 gl.deleteShader(geometry_shader_id); 808 if (vertex_shader_id != 0) 809 gl.deleteShader(vertex_shader_id); 810 811 return result; 812 } 813 814 /** Retrieves source for a shader object with GLES id @param shader_id. 815 * 816 * @param shader_id GLES id of a shader object to retrieve source for. 817 * 818 * @return String instance containing the shader source. 819 **/ 820 std::string TestCaseBase::getShaderSource(glw::GLuint shader_id) 821 { 822 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 823 824 glw::GLint length = 0; 825 826 gl.getShaderiv(shader_id, GL_SHADER_SOURCE_LENGTH, &length); 827 828 std::vector<char> result_vec(length + 1); 829 830 gl.getShaderSource(shader_id, length + 1, NULL, &result_vec[0]); 831 832 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve shader source!"); 833 834 return std::string(&result_vec[0]); 835 } 836 837 /** Retrieves compilation info log for a shader object with GLES id 838 * @param shader_id. 839 * 840 * @param shader_id GLES id of a shader object to retrieve compilation 841 * info log for. 842 * 843 * @return String instance containing the log. 844 **/ 845 std::string TestCaseBase::getCompilationInfoLog(glw::GLuint shader_id) 846 { 847 return getInfoLog(LT_SHADER_OBJECT, shader_id); 848 } 849 850 /** Retrieves linking info log for a program object with GLES id 851 * @param po_id. 852 * 853 * @param po_id GLES id of a program object to retrieve linking 854 * info log for. 855 * 856 * @return String instance containing the log. 857 **/ 858 std::string TestCaseBase::getLinkingInfoLog(glw::GLuint po_id) 859 { 860 return getInfoLog(LT_PROGRAM_OBJECT, po_id); 861 } 862 863 /** Retrieves linking info log for a pipeline object with GLES id 864 * @param ppo_id. 865 * 866 * @param ppo_id GLES id of a pipeline object to retrieve validation 867 * info log for. 868 * 869 * @return String instance containing the log. 870 **/ 871 std::string TestCaseBase::getPipelineInfoLog(glw::GLuint ppo_id) 872 { 873 return getInfoLog(LT_PIPELINE_OBJECT, ppo_id); 874 } 875 876 /** Retrieves compilation OR linking info log for a shader/program object with GLES id 877 * @param id. 878 * 879 * @param is_compilation_info_log true if @param id is a GLES id of a shader object; 880 * false if it represents a program object. 881 * @param id GLES id of a shader OR a program object to 882 * retrieve info log for. 883 * 884 * @return String instance containing the log.. 885 **/ 886 std::string TestCaseBase::getInfoLog(LOG_TYPE log_type, glw::GLuint id) 887 { 888 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 889 890 glw::GLint n_characters = 0; 891 /* Retrieve amount of characters needed to store the info log (terminator-inclusive) */ 892 switch (log_type) 893 { 894 case LT_SHADER_OBJECT: 895 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &n_characters); 896 break; 897 case LT_PROGRAM_OBJECT: 898 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &n_characters); 899 break; 900 case LT_PIPELINE_OBJECT: 901 gl.getProgramPipelineiv(id, GL_INFO_LOG_LENGTH, &n_characters); 902 break; 903 default: 904 TCU_FAIL("Invalid parameter"); 905 } 906 907 /* Check if everything is fine so far */ 908 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query info log length!"); 909 910 /* Allocate buffer */ 911 std::vector<char> result_vec(n_characters + 1); 912 913 /* Retrieve the info log */ 914 switch (log_type) 915 { 916 case LT_SHADER_OBJECT: 917 gl.getShaderInfoLog(id, n_characters + 1, 0, &result_vec[0]); 918 break; 919 case LT_PROGRAM_OBJECT: 920 gl.getProgramInfoLog(id, n_characters + 1, 0, &result_vec[0]); 921 break; 922 case LT_PIPELINE_OBJECT: 923 gl.getProgramPipelineInfoLog(id, n_characters + 1, 0, &result_vec[0]); 924 break; 925 } 926 927 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve info log!"); 928 929 return std::string(&result_vec[0]); 930 } 931 932 /** Setup frame buffer: 933 * 1 allocate texture storage for specified format and dimensions, 934 * 2 bind framebuffer and attach texture to GL_COLOR_ATTACHMENT0 935 * 3 setup viewport to specified dimensions 936 * 937 * @param framebuffer_object_id FBO handle 938 * @param color_texture_id Texture handle 939 * @param texture_format Requested texture format, eg. GL_RGBA8 940 * @param texture_width Requested texture width 941 * @param texture_height Requested texture height 942 * 943 * @return true All operations succeded 944 * false In case of any error 945 **/ 946 bool TestCaseBase::setupFramebufferWithTextureAsAttachment(glw::GLuint framebuffer_object_id, 947 glw::GLuint color_texture_id, glw::GLenum texture_format, 948 glw::GLuint texture_width, glw::GLuint texture_height) const 949 { 950 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 951 952 /* Allocate texture storage */ 953 gl.bindTexture(GL_TEXTURE_2D, color_texture_id); 954 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, texture_format, texture_width, texture_height); 955 956 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not allocate texture storage!"); 957 958 /* Setup framebuffer */ 959 gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer_object_id); 960 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_texture_id, 0 /* level */); 961 962 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not setup framebuffer!"); 963 964 /* Setup viewport */ 965 gl.viewport(0, 0, texture_width, texture_height); 966 967 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not setup viewport!"); 968 969 /* Success */ 970 return true; 971 } 972 973 /** Check Framebuffer Status. 974 * Throws a TestError exception, should the framebuffer be found incomplete. 975 * 976 * @param framebuffer - GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER 977 * 978 */ 979 void TestCaseBase::checkFramebufferStatus(glw::GLenum framebuffer) const 980 { 981 /* Get GL entry points */ 982 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 983 984 glw::GLenum framebuffer_status = gl.checkFramebufferStatus(framebuffer); 985 GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting framebuffer status!"); 986 987 if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) 988 { 989 switch (framebuffer_status) 990 { 991 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 992 { 993 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); 994 } 995 996 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 997 { 998 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); 999 } 1000 1001 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 1002 { 1003 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); 1004 } 1005 1006 case GL_FRAMEBUFFER_UNSUPPORTED: 1007 { 1008 TCU_FAIL("Framebuffer incomplete, status: Error: GL_FRAMEBUFFER_UNSUPPORTED"); 1009 } 1010 1011 default: 1012 { 1013 TCU_FAIL("Framebuffer incomplete, status not recognized"); 1014 } 1015 } /* switch (framebuffer_status) */ 1016 } /* if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) */ 1017 } 1018 1019 std::string TestCaseBase::getGLSLExtDirective(ExtensionType type, ExtensionName name, ExtensionBehavior behavior) 1020 { 1021 if (type == EXTENSIONTYPE_NONE && name != EXTENSIONNAME_GEOMETRY_POINT_SIZE && 1022 name != EXTENSIONNAME_TESSELLATION_POINT_SIZE) 1023 { 1024 return ""; 1025 } 1026 1027 const char* type_str = NULL; 1028 const char* name_str = NULL; 1029 const char* behavior_str = NULL; 1030 1031 if (name == EXTENSIONNAME_SHADER_IMAGE_ATOMIC) 1032 { 1033 // There is no EXT version of shader_image_atomic; use OES 1034 type = EXTENSIONTYPE_OES; 1035 } 1036 1037 if (name == EXTENSIONNAME_TESSELLATION_POINT_SIZE) 1038 { 1039 // there is no core version of tessellation_point_size, use OES or EXT 1040 if (isExtensionSupported("GL_OES_tessellation_point_size")) 1041 { 1042 type = EXTENSIONTYPE_OES; 1043 } 1044 else if (isExtensionSupported("GL_EXT_tessellation_point_size")) 1045 { 1046 type = EXTENSIONTYPE_EXT; 1047 } 1048 else 1049 { 1050 return ""; 1051 } 1052 } 1053 1054 if (name == EXTENSIONNAME_GEOMETRY_POINT_SIZE) 1055 { 1056 // there is no core version of geometry_point_size, use OES or EXT 1057 if (isExtensionSupported("GL_OES_geometry_point_size")) 1058 { 1059 type = EXTENSIONTYPE_OES; 1060 } 1061 else if (isExtensionSupported("GL_EXT_geometry_point_size")) 1062 { 1063 type = EXTENSIONTYPE_EXT; 1064 } 1065 else 1066 { 1067 return ""; 1068 } 1069 } 1070 1071 switch (type) 1072 { 1073 case EXTENSIONTYPE_EXT: 1074 type_str = "EXT_"; 1075 break; 1076 case EXTENSIONTYPE_OES: 1077 type_str = "OES_"; 1078 break; 1079 default: 1080 DE_ASSERT(0); 1081 return "#error unknown extension type\n"; 1082 } 1083 1084 switch (name) 1085 { 1086 case EXTENSIONNAME_SHADER_IMAGE_ATOMIC: 1087 name_str = "shader_image_atomic"; 1088 break; 1089 case EXTENSIONNAME_SHADER_IO_BLOCKS: 1090 name_str = "shader_io_blocks"; 1091 break; 1092 case EXTENSIONNAME_GEOMETRY_SHADER: 1093 name_str = "geometry_shader"; 1094 break; 1095 case EXTENSIONNAME_GEOMETRY_POINT_SIZE: 1096 name_str = "geometry_point_size"; 1097 break; 1098 case EXTENSIONNAME_TESSELLATION_SHADER: 1099 name_str = "tessellation_shader"; 1100 break; 1101 case EXTENSIONNAME_TESSELLATION_POINT_SIZE: 1102 name_str = "tessellation_point_size"; 1103 break; 1104 case EXTENSIONNAME_TEXTURE_BUFFER: 1105 name_str = "texture_buffer"; 1106 break; 1107 case EXTENSIONNAME_TEXTURE_CUBE_MAP_ARRAY: 1108 name_str = "texture_cube_map_array"; 1109 break; 1110 case EXTENSIONNAME_GPU_SHADER5: 1111 name_str = "gpu_shader5"; 1112 break; 1113 case EXTENSIONNAME_VIEWPORT_ARRAY: 1114 name_str = "viewport_array"; 1115 break; 1116 default: 1117 DE_ASSERT(0); 1118 return "#error unknown extension name\n"; 1119 } 1120 1121 switch (behavior) 1122 { 1123 case EXTENSIONBEHAVIOR_DISABLE: 1124 behavior_str = "disable"; 1125 break; 1126 case EXTENSIONBEHAVIOR_WARN: 1127 behavior_str = "warn"; 1128 break; 1129 case EXTENSIONBEHAVIOR_ENABLE: 1130 behavior_str = "enable"; 1131 break; 1132 case EXTENSIONBEHAVIOR_REQUIRE: 1133 behavior_str = "require"; 1134 break; 1135 default: 1136 DE_ASSERT(0); 1137 return "#error unknown extension behavior"; 1138 } 1139 1140 std::stringstream str; 1141 str << "#extension GL_" << type_str << name_str << " : " << behavior_str; 1142 return str.str(); 1143 } 1144 1145 } // namespace glcts 1146