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 726 case 3: 727 { 728 result &= (expected_blue == buffer[texel_offset + 2]); 729 } 730 731 case 2: 732 { 733 result &= (expected_green == buffer[texel_offset + 1]); 734 } 735 736 case 1: 737 { 738 result &= (expected_red == buffer[texel_offset + 0]); 739 740 break; 741 } 742 743 default: 744 { 745 return false; 746 } 747 } /* switch (pixel_size) */ 748 749 return result; 750 } 751 752 /** Checks whether a combination of fragment/geometry/vertex shader objects compiles and links into a program 753 * 754 * @param n_fs_body_parts Number of elements of @param fs_body_parts array. 755 * @param fs_body_parts Pointer to array of strings to make up fragment shader's body. 756 * Must not be NULL. 757 * 758 * @param n_gs_body_parts Number of elements of @param gs_body_parts array. 759 * @param gs_body_parts Pointer to array of strings to make up geometry shader's body. 760 * Can be NULL. 761 * 762 * @param n_vs_body_parts Number of elements of @param vs_body_parts array. 763 * @param vs_body_parts Pointer to array of strings to make up vertex shader's body. 764 * Must not be NULL. 765 * 766 * @return true if program creation was successful, false otherwise. 767 **/ 768 bool TestCaseBase::doesProgramBuild(unsigned int n_fs_body_parts, const char* const* fs_body_parts, 769 unsigned int n_gs_body_parts, const char* const* gs_body_parts, 770 unsigned int n_vs_body_parts, const char* const* vs_body_parts) 771 { 772 /* General variables */ 773 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 774 bool result = false; 775 776 /* Shaders */ 777 glw::GLuint vertex_shader_id = 0; 778 glw::GLuint geometry_shader_id = 0; 779 glw::GLuint fragment_shader_id = 0; 780 781 /* Program */ 782 glw::GLuint program_object_id = 0; 783 784 /* Create shaders */ 785 vertex_shader_id = gl.createShader(GL_VERTEX_SHADER); 786 geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 787 fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER); 788 789 /* Create program */ 790 program_object_id = gl.createProgram(); 791 792 /* Check createProgram call for errors */ 793 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); 794 795 /* Compile and link the program */ 796 result = buildProgram(program_object_id, fragment_shader_id, n_fs_body_parts, fs_body_parts, geometry_shader_id, 797 n_gs_body_parts, gs_body_parts, vertex_shader_id, n_vs_body_parts, vs_body_parts); 798 799 if (program_object_id != 0) 800 gl.deleteProgram(program_object_id); 801 if (fragment_shader_id != 0) 802 gl.deleteShader(fragment_shader_id); 803 if (geometry_shader_id != 0) 804 gl.deleteShader(geometry_shader_id); 805 if (vertex_shader_id != 0) 806 gl.deleteShader(vertex_shader_id); 807 808 return result; 809 } 810 811 /** Retrieves source for a shader object with GLES id @param shader_id. 812 * 813 * @param shader_id GLES id of a shader object to retrieve source for. 814 * 815 * @return String instance containing the shader source. 816 **/ 817 std::string TestCaseBase::getShaderSource(glw::GLuint shader_id) 818 { 819 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 820 821 glw::GLint length = 0; 822 823 gl.getShaderiv(shader_id, GL_SHADER_SOURCE_LENGTH, &length); 824 825 std::vector<char> result_vec(length + 1); 826 827 gl.getShaderSource(shader_id, length + 1, NULL, &result_vec[0]); 828 829 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve shader source!"); 830 831 return std::string(&result_vec[0]); 832 } 833 834 /** Retrieves compilation info log for a shader object with GLES id 835 * @param shader_id. 836 * 837 * @param shader_id GLES id of a shader object to retrieve compilation 838 * info log for. 839 * 840 * @return String instance containing the log. 841 **/ 842 std::string TestCaseBase::getCompilationInfoLog(glw::GLuint shader_id) 843 { 844 return getInfoLog(LT_SHADER_OBJECT, shader_id); 845 } 846 847 /** Retrieves linking info log for a program object with GLES id 848 * @param po_id. 849 * 850 * @param po_id GLES id of a program object to retrieve linking 851 * info log for. 852 * 853 * @return String instance containing the log. 854 **/ 855 std::string TestCaseBase::getLinkingInfoLog(glw::GLuint po_id) 856 { 857 return getInfoLog(LT_PROGRAM_OBJECT, po_id); 858 } 859 860 /** Retrieves linking info log for a pipeline object with GLES id 861 * @param ppo_id. 862 * 863 * @param ppo_id GLES id of a pipeline object to retrieve validation 864 * info log for. 865 * 866 * @return String instance containing the log. 867 **/ 868 std::string TestCaseBase::getPipelineInfoLog(glw::GLuint ppo_id) 869 { 870 return getInfoLog(LT_PIPELINE_OBJECT, ppo_id); 871 } 872 873 /** Retrieves compilation OR linking info log for a shader/program object with GLES id 874 * @param id. 875 * 876 * @param is_compilation_info_log true if @param id is a GLES id of a shader object; 877 * false if it represents a program object. 878 * @param id GLES id of a shader OR a program object to 879 * retrieve info log for. 880 * 881 * @return String instance containing the log.. 882 **/ 883 std::string TestCaseBase::getInfoLog(LOG_TYPE log_type, glw::GLuint id) 884 { 885 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 886 887 glw::GLint n_characters = 0; 888 /* Retrieve amount of characters needed to store the info log (terminator-inclusive) */ 889 switch (log_type) 890 { 891 case LT_SHADER_OBJECT: 892 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &n_characters); 893 break; 894 case LT_PROGRAM_OBJECT: 895 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &n_characters); 896 break; 897 case LT_PIPELINE_OBJECT: 898 gl.getProgramPipelineiv(id, GL_INFO_LOG_LENGTH, &n_characters); 899 break; 900 default: 901 TCU_FAIL("Invalid parameter"); 902 } 903 904 /* Check if everything is fine so far */ 905 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query info log length!"); 906 907 /* Allocate buffer */ 908 std::vector<char> result_vec(n_characters + 1); 909 910 /* Retrieve the info log */ 911 switch (log_type) 912 { 913 case LT_SHADER_OBJECT: 914 gl.getShaderInfoLog(id, n_characters + 1, 0, &result_vec[0]); 915 break; 916 case LT_PROGRAM_OBJECT: 917 gl.getProgramInfoLog(id, n_characters + 1, 0, &result_vec[0]); 918 break; 919 case LT_PIPELINE_OBJECT: 920 gl.getProgramPipelineInfoLog(id, n_characters + 1, 0, &result_vec[0]); 921 break; 922 } 923 924 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve info log!"); 925 926 return std::string(&result_vec[0]); 927 } 928 929 /** Setup frame buffer: 930 * 1 allocate texture storage for specified format and dimensions, 931 * 2 bind framebuffer and attach texture to GL_COLOR_ATTACHMENT0 932 * 3 setup viewport to specified dimensions 933 * 934 * @param framebuffer_object_id FBO handle 935 * @param color_texture_id Texture handle 936 * @param texture_format Requested texture format, eg. GL_RGBA8 937 * @param texture_width Requested texture width 938 * @param texture_height Requested texture height 939 * 940 * @return true All operations succeded 941 * false In case of any error 942 **/ 943 bool TestCaseBase::setupFramebufferWithTextureAsAttachment(glw::GLuint framebuffer_object_id, 944 glw::GLuint color_texture_id, glw::GLenum texture_format, 945 glw::GLuint texture_width, glw::GLuint texture_height) const 946 { 947 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 948 949 /* Allocate texture storage */ 950 gl.bindTexture(GL_TEXTURE_2D, color_texture_id); 951 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, texture_format, texture_width, texture_height); 952 953 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not allocate texture storage!"); 954 955 /* Setup framebuffer */ 956 gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer_object_id); 957 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_texture_id, 0 /* level */); 958 959 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not setup framebuffer!"); 960 961 /* Setup viewport */ 962 gl.viewport(0, 0, texture_width, texture_height); 963 964 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not setup viewport!"); 965 966 /* Success */ 967 return true; 968 } 969 970 /** Check Framebuffer Status. 971 * Throws a TestError exception, should the framebuffer be found incomplete. 972 * 973 * @param framebuffer - GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER 974 * 975 */ 976 void TestCaseBase::checkFramebufferStatus(glw::GLenum framebuffer) const 977 { 978 /* Get GL entry points */ 979 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 980 981 glw::GLenum framebuffer_status = gl.checkFramebufferStatus(framebuffer); 982 GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting framebuffer status!"); 983 984 if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) 985 { 986 switch (framebuffer_status) 987 { 988 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 989 { 990 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); 991 } 992 993 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 994 { 995 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); 996 } 997 998 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 999 { 1000 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); 1001 } 1002 1003 case GL_FRAMEBUFFER_UNSUPPORTED: 1004 { 1005 TCU_FAIL("Framebuffer incomplete, status: Error: GL_FRAMEBUFFER_UNSUPPORTED"); 1006 } 1007 1008 default: 1009 { 1010 TCU_FAIL("Framebuffer incomplete, status not recognized"); 1011 } 1012 } /* switch (framebuffer_status) */ 1013 } /* if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) */ 1014 } 1015 1016 std::string TestCaseBase::getGLSLExtDirective(ExtensionType type, ExtensionName name, ExtensionBehavior behavior) 1017 { 1018 if (type == EXTENSIONTYPE_NONE && name != EXTENSIONNAME_GEOMETRY_POINT_SIZE && 1019 name != EXTENSIONNAME_TESSELLATION_POINT_SIZE) 1020 { 1021 return ""; 1022 } 1023 1024 const char* type_str = NULL; 1025 const char* name_str = NULL; 1026 const char* behavior_str = NULL; 1027 1028 if (name == EXTENSIONNAME_SHADER_IMAGE_ATOMIC) 1029 { 1030 // There is no EXT version of shader_image_atomic; use OES 1031 type = EXTENSIONTYPE_OES; 1032 } 1033 1034 if (name == EXTENSIONNAME_TESSELLATION_POINT_SIZE) 1035 { 1036 // there is no core version of tessellation_point_size, use OES or EXT 1037 if (isExtensionSupported("GL_OES_tessellation_point_size")) 1038 { 1039 type = EXTENSIONTYPE_OES; 1040 } 1041 else if (isExtensionSupported("GL_EXT_tessellation_point_size")) 1042 { 1043 type = EXTENSIONTYPE_EXT; 1044 } 1045 else 1046 { 1047 return ""; 1048 } 1049 } 1050 1051 if (name == EXTENSIONNAME_GEOMETRY_POINT_SIZE) 1052 { 1053 // there is no core version of geometry_point_size, use OES or EXT 1054 if (isExtensionSupported("GL_OES_geometry_point_size")) 1055 { 1056 type = EXTENSIONTYPE_OES; 1057 } 1058 else if (isExtensionSupported("GL_EXT_geometry_point_size")) 1059 { 1060 type = EXTENSIONTYPE_EXT; 1061 } 1062 else 1063 { 1064 return ""; 1065 } 1066 } 1067 1068 switch (type) 1069 { 1070 case EXTENSIONTYPE_EXT: 1071 type_str = "EXT_"; 1072 break; 1073 case EXTENSIONTYPE_OES: 1074 type_str = "OES_"; 1075 break; 1076 default: 1077 DE_ASSERT(0); 1078 return "#error unknown extension type\n"; 1079 } 1080 1081 switch (name) 1082 { 1083 case EXTENSIONNAME_SHADER_IMAGE_ATOMIC: 1084 name_str = "shader_image_atomic"; 1085 break; 1086 case EXTENSIONNAME_SHADER_IO_BLOCKS: 1087 name_str = "shader_io_blocks"; 1088 break; 1089 case EXTENSIONNAME_GEOMETRY_SHADER: 1090 name_str = "geometry_shader"; 1091 break; 1092 case EXTENSIONNAME_GEOMETRY_POINT_SIZE: 1093 name_str = "geometry_point_size"; 1094 break; 1095 case EXTENSIONNAME_TESSELLATION_SHADER: 1096 name_str = "tessellation_shader"; 1097 break; 1098 case EXTENSIONNAME_TESSELLATION_POINT_SIZE: 1099 name_str = "tessellation_point_size"; 1100 break; 1101 case EXTENSIONNAME_TEXTURE_BUFFER: 1102 name_str = "texture_buffer"; 1103 break; 1104 case EXTENSIONNAME_TEXTURE_CUBE_MAP_ARRAY: 1105 name_str = "texture_cube_map_array"; 1106 break; 1107 case EXTENSIONNAME_GPU_SHADER5: 1108 name_str = "gpu_shader5"; 1109 break; 1110 case EXTENSIONNAME_VIEWPORT_ARRAY: 1111 name_str = "viewport_array"; 1112 break; 1113 default: 1114 DE_ASSERT(0); 1115 return "#error unknown extension name\n"; 1116 } 1117 1118 switch (behavior) 1119 { 1120 case EXTENSIONBEHAVIOR_DISABLE: 1121 behavior_str = "disable"; 1122 break; 1123 case EXTENSIONBEHAVIOR_WARN: 1124 behavior_str = "warn"; 1125 break; 1126 case EXTENSIONBEHAVIOR_ENABLE: 1127 behavior_str = "enable"; 1128 break; 1129 case EXTENSIONBEHAVIOR_REQUIRE: 1130 behavior_str = "require"; 1131 break; 1132 default: 1133 DE_ASSERT(0); 1134 return "#error unknown extension behavior"; 1135 } 1136 1137 std::stringstream str; 1138 str << "#extension GL_" << type_str << name_str << " : " << behavior_str; 1139 return str.str(); 1140 } 1141 1142 } // namespace glcts 1143