1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2015-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 /** 25 * \file gl4cSyncTests.cpp 26 * \brief Declares test classes for synchronization functionality. 27 */ /*-------------------------------------------------------------------*/ 28 29 #include "gl4cIncompleteTextureAccessTests.hpp" 30 31 #include "deSharedPtr.hpp" 32 33 #include "gluContextInfo.hpp" 34 #include "gluDefs.hpp" 35 #include "gluPixelTransfer.hpp" 36 #include "gluStrUtil.hpp" 37 38 #include "tcuFuzzyImageCompare.hpp" 39 #include "tcuImageCompare.hpp" 40 #include "tcuRenderTarget.hpp" 41 #include "tcuSurface.hpp" 42 #include "tcuTestLog.hpp" 43 44 #include "glw.h" 45 #include "glwFunctions.hpp" 46 47 namespace gl4cts 48 { 49 namespace IncompleteTextureAccess 50 { 51 /****************************************** Incomplete Texture Access Tests Group ***********************************************/ 52 53 /** @brief Incomplete Texture Access Tests Group constructor. 54 * 55 * @param [in] context OpenGL context. 56 */ 57 Tests::Tests(deqp::Context& context) 58 : TestCaseGroup(context, "incomplete_texture_access", "Incomplete Texture Access Tests Suite") 59 { 60 } 61 62 /** @brief Incomplete Texture Access Tests initializer. */ 63 void Tests::init() 64 { 65 addChild(new IncompleteTextureAccess::SamplerTest(m_context)); 66 } 67 68 /*************************************** Sampler Incomplete Texture Access Test Test *******************************************/ 69 70 /** @brief Sampler Incomplete Texture Access Test constructor. 71 * 72 * @param [in] context OpenGL context. 73 */ 74 SamplerTest::SamplerTest(deqp::Context& context) 75 : deqp::TestCase(context, "sampler", "Fetch using sampler test"), m_po(0), m_to(0), m_fbo(0), m_rbo(0), m_vao(0) 76 { 77 /* Intentionally left blank. */ 78 } 79 80 /** @brief Iterate Incomplete Texture Access Test cases. 81 * 82 * @return Iteration result. 83 */ 84 tcu::TestNode::IterateResult SamplerTest::iterate() 85 { 86 /* Get context setup. */ 87 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); 88 89 if (!is_at_least_gl_45) 90 { 91 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); 92 93 return STOP; 94 } 95 96 /* Running tests. */ 97 bool is_ok = true; 98 bool is_error = false; 99 100 try 101 { 102 PrepareFramebuffer(); 103 PrepareVertexArrays(); 104 105 for (glw::GLuint i = 0; i < s_configurations_count; ++i) 106 { 107 PrepareProgram(s_configurations[i]); 108 PrepareTexture(s_configurations[i]); 109 110 Draw(); 111 112 if (!Check(s_configurations[i])) 113 { 114 m_context.getTestContext().getLog() 115 << tcu::TestLog::Message << "Incomplete texture sampler access test failed with sampler " 116 << s_configurations[i].sampler_template << "." << tcu::TestLog::EndMessage; 117 118 is_ok = false; 119 } 120 121 CleanCase(); 122 } 123 } 124 catch (...) 125 { 126 is_ok = false; 127 is_error = true; 128 } 129 130 /* Cleanup. */ 131 CleanCase(); 132 CleanTest(); 133 134 /* Result's setup. */ 135 if (is_ok) 136 { 137 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 138 } 139 else 140 { 141 if (is_error) 142 { 143 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 144 } 145 else 146 { 147 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 148 } 149 } 150 151 return STOP; 152 } 153 154 void SamplerTest::PrepareProgram(Configuration configuration) 155 { 156 /* Shortcut for GL functionality */ 157 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 158 159 struct Shader 160 { 161 glw::GLchar const* source[5]; 162 glw::GLsizei const count; 163 glw::GLenum const type; 164 glw::GLuint id; 165 } shader[] = { { { s_vertex_shader, NULL, NULL, NULL, NULL }, 1, GL_VERTEX_SHADER, 0 }, 166 { { s_fragment_shader_head, configuration.sampler_template, s_fragment_shader_body, 167 configuration.fetch_template, s_fragment_shader_tail }, 168 5, 169 GL_FRAGMENT_SHADER, 170 0 } }; 171 172 glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]); 173 174 try 175 { 176 /* Create program. */ 177 m_po = gl.createProgram(); 178 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed."); 179 180 /* Shader compilation. */ 181 182 for (glw::GLuint i = 0; i < shader_count; ++i) 183 { 184 { 185 shader[i].id = gl.createShader(shader[i].type); 186 187 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed."); 188 189 gl.attachShader(m_po, shader[i].id); 190 191 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed."); 192 193 gl.shaderSource(shader[i].id, shader[i].count, shader[i].source, NULL); 194 195 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed."); 196 197 gl.compileShader(shader[i].id); 198 199 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed."); 200 201 glw::GLint status = GL_FALSE; 202 203 gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status); 204 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed."); 205 206 if (GL_FALSE == status) 207 { 208 glw::GLint log_size = 0; 209 gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size); 210 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed."); 211 212 glw::GLchar* log_text = new glw::GLchar[log_size]; 213 214 gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]); 215 216 m_context.getTestContext().getLog() 217 << tcu::TestLog::Message << "Shader compilation has failed.\n" 218 << "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n" 219 << "Shader compilation error log:\n" 220 << log_text << "\n" 221 << "Shader source code:\n" 222 << shader[i].source[0] << (shader[i].source[1] ? shader[i].source[1] : "") 223 << (shader[i].source[2] ? shader[i].source[2] : "") 224 << (shader[i].source[3] ? shader[i].source[3] : "") 225 << (shader[i].source[4] ? shader[i].source[4] : "") << "\n" 226 << tcu::TestLog::EndMessage; 227 228 delete[] log_text; 229 230 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed."); 231 232 throw 0; 233 } 234 } 235 } 236 237 /* Link. */ 238 gl.linkProgram(m_po); 239 240 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed."); 241 242 glw::GLint status = GL_FALSE; 243 244 gl.getProgramiv(m_po, GL_LINK_STATUS, &status); 245 246 if (GL_TRUE == status) 247 { 248 for (glw::GLuint i = 0; i < shader_count; ++i) 249 { 250 if (shader[i].id) 251 { 252 gl.detachShader(m_po, shader[i].id); 253 254 GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed."); 255 } 256 } 257 } 258 else 259 { 260 glw::GLint log_size = 0; 261 262 gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size); 263 264 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed."); 265 266 glw::GLchar* log_text = new glw::GLchar[log_size]; 267 268 gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]); 269 270 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n" 271 << log_text << "\n" 272 << tcu::TestLog::EndMessage; 273 274 delete[] log_text; 275 276 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed."); 277 278 throw 0; 279 } 280 } 281 catch (...) 282 { 283 if (m_po) 284 { 285 gl.deleteProgram(m_po); 286 287 m_po = 0; 288 } 289 } 290 291 for (glw::GLuint i = 0; i < shader_count; ++i) 292 { 293 if (0 != shader[i].id) 294 { 295 gl.deleteShader(shader[i].id); 296 297 shader[i].id = 0; 298 } 299 } 300 301 if (0 == m_po) 302 { 303 throw 0; 304 } 305 else 306 { 307 gl.useProgram(m_po); 308 GLU_EXPECT_NO_ERROR(gl.getError(), "glUsePrograms has failed"); 309 } 310 } 311 312 void SamplerTest::PrepareTexture(Configuration configuration) 313 { 314 /* Shortcut for GL functionality. */ 315 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 316 317 if (m_to) 318 { 319 throw 0; 320 } 321 322 gl.genTextures(1, &m_to); 323 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed"); 324 325 gl.bindTexture(configuration.texture_target, m_to); 326 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture has failed"); 327 } 328 329 void SamplerTest::PrepareFramebuffer() 330 { 331 /* Shortcut for GL functionality. */ 332 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 333 334 /* Sanity checks. */ 335 if (m_fbo || m_rbo) 336 { 337 throw 0; 338 } 339 340 /* Framebuffer creation. */ 341 gl.genFramebuffers(1, &m_fbo); 342 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed"); 343 344 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 345 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed"); 346 347 gl.genRenderbuffers(1, &m_rbo); 348 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed"); 349 350 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo); 351 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed"); 352 353 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 1 /* x size */, 1 /* y size */); 354 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed"); 355 356 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo); 357 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed"); 358 359 /* Sanity checks. */ 360 if (GL_FRAMEBUFFER_COMPLETE != gl.checkFramebufferStatus(GL_FRAMEBUFFER)) 361 { 362 throw 0; 363 } 364 } 365 366 void SamplerTest::PrepareVertexArrays() 367 { 368 /* Shortcut for GL functionality. */ 369 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 370 371 /* Sanity checks.*/ 372 if (m_vao) 373 { 374 throw 0; 375 } 376 377 /* Empty vao creation. */ 378 gl.genVertexArrays(1, &m_vao); 379 GLU_EXPECT_NO_ERROR(gl.getError(), "gGenVertexArrays has failed"); 380 381 gl.bindVertexArray(m_vao); 382 GLU_EXPECT_NO_ERROR(gl.getError(), "gBindVertexArrays has failed"); 383 } 384 385 void SamplerTest::Draw() 386 { 387 /* Shortcut for GL functionality. */ 388 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 389 390 /* Draw setup. */ 391 gl.activeTexture(GL_TEXTURE0); 392 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture has failed"); 393 394 gl.uniform1i(gl.getUniformLocation(m_po, "texture_input"), 0); 395 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i has failed"); 396 397 /* Draw. */ 398 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); 399 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays has failed"); 400 } 401 402 bool SamplerTest::Check(Configuration configuration) 403 { 404 /* Shortcut for GL functionality. */ 405 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 406 407 /* Return storage. */ 408 glw::GLfloat result[4] = { 7.f, 7.f, 7.f, 7.f }; 409 410 /* Fetch. */ 411 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, result); 412 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed"); 413 414 /* Comparison. */ 415 for (glw::GLuint i = 0; i < 4 /* # components */; ++i) 416 { 417 if (de::abs(configuration.expected_result[i] - result[i]) > 0.0125 /* precision */) 418 { 419 /* Fail.*/ 420 return false; 421 } 422 } 423 424 /* Comparsion passed.*/ 425 return true; 426 } 427 428 void SamplerTest::CleanCase() 429 { 430 /* Shortcut for GL functionality. */ 431 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 432 433 /* Program cleanup. */ 434 if (m_po) 435 { 436 gl.deleteProgram(m_po); 437 438 m_po = 0; 439 } 440 441 /* Texture cleanup. */ 442 if (m_to) 443 { 444 gl.deleteTextures(1, &m_to); 445 446 m_to = 0; 447 } 448 449 /* Errors cleanup. */ 450 while (gl.getError()) 451 ; 452 } 453 454 void SamplerTest::CleanTest() 455 { 456 /* Shortcut for GL functionality. */ 457 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 458 459 /* Framebuffer cleanup. */ 460 if (m_fbo) 461 { 462 gl.deleteFramebuffers(1, &m_fbo); 463 464 m_fbo = 0; 465 } 466 467 /* Renderbuffer cleanup. */ 468 if (m_rbo) 469 { 470 gl.deleteRenderbuffers(1, &m_rbo); 471 472 m_rbo = 0; 473 } 474 475 /* Vertex arrays cleanup. */ 476 if (m_vao) 477 { 478 gl.deleteVertexArrays(1, &m_vao); 479 480 m_vao = 0; 481 } 482 483 /* Errors cleanup. */ 484 while (gl.getError()) 485 ; 486 } 487 488 const struct SamplerTest::Configuration SamplerTest::s_configurations[] = { 489 /* regular floating point sampling */ 490 { GL_TEXTURE_1D, "sampler1D", "texture(texture_input, 0.0)", { 0.f, 0.f, 0.f, 1.f } }, 491 { GL_TEXTURE_2D, "sampler2D", "texture(texture_input, vec2(0.0))", { 0.f, 0.f, 0.f, 1.f } }, 492 { GL_TEXTURE_3D, "sampler3D", "texture(texture_input, vec3(0.0))", { 0.f, 0.f, 0.f, 1.f } }, 493 { GL_TEXTURE_CUBE_MAP, "samplerCube", "texture(texture_input, vec3(0.0))", { 0.f, 0.f, 0.f, 1.f } }, 494 { GL_TEXTURE_RECTANGLE, "sampler2DRect", "texture(texture_input, vec2(0.0))", { 0.f, 0.f, 0.f, 1.f } }, 495 { GL_TEXTURE_1D_ARRAY, "sampler1DArray", "texture(texture_input, vec2(0.0))", { 0.f, 0.f, 0.f, 1.f } }, 496 { GL_TEXTURE_2D_ARRAY, "sampler2DArray", "texture(texture_input, vec3(0.0))", { 0.f, 0.f, 0.f, 1.f } }, 497 { GL_TEXTURE_CUBE_MAP_ARRAY, "samplerCubeArray", "texture(texture_input, vec4(0.0))", { 0.f, 0.f, 0.f, 1.f } }, 498 499 /* Shadow textures. */ 500 { GL_TEXTURE_1D, 501 "sampler1DShadow", 502 "vec4(texture(texture_input, vec3(0.0)), 0.0, 0.0, 0.0)", 503 { 0.f, 0.f, 0.f, 0.f } }, 504 { GL_TEXTURE_2D, 505 "sampler2DShadow", 506 "vec4(texture(texture_input, vec3(0.0)), 0.0, 0.0, 0.0)", 507 { 0.f, 0.f, 0.f, 0.f } }, 508 { GL_TEXTURE_CUBE_MAP, 509 "samplerCubeShadow", 510 "vec4(texture(texture_input, vec4(0.0)), 0.0, 0.0, 0.0)", 511 { 0.f, 0.f, 0.f, 0.f } }, 512 { GL_TEXTURE_RECTANGLE, 513 "sampler2DRectShadow", 514 "vec4(texture(texture_input, vec3(0.0)), 0.0, 0.0, 0.0)", 515 { 0.f, 0.f, 0.f, 0.f } }, 516 { GL_TEXTURE_1D_ARRAY, 517 "sampler1DArrayShadow", 518 "vec4(texture(texture_input, vec3(0.0)), 0.0, 0.0, 0.0)", 519 { 0.f, 0.f, 0.f, 0.f } }, 520 { GL_TEXTURE_2D_ARRAY, 521 "sampler2DArrayShadow", 522 "vec4(texture(texture_input, vec4(0.0)), 0.0, 0.0, 0.0)", 523 { 0.f, 0.f, 0.f, 0.f } }, 524 { GL_TEXTURE_CUBE_MAP_ARRAY, 525 "samplerCubeArrayShadow", 526 "vec4(texture(texture_input, vec4(0.0), 1.0), 0.0, 0.0, 0.0)", 527 { 0.f, 0.f, 0.f, 0.f } } 528 }; 529 530 const glw::GLuint SamplerTest::s_configurations_count = sizeof(s_configurations) / sizeof(s_configurations[0]); 531 532 const glw::GLchar* SamplerTest::s_vertex_shader = "#version 450\n" 533 "\n" 534 "void main()\n" 535 "{\n" 536 " switch(gl_VertexID)\n" 537 " {\n" 538 " case 0:\n" 539 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 540 " break;\n" 541 " case 1:\n" 542 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n" 543 " break;\n" 544 " case 2:\n" 545 " gl_Position = vec4(-1.0,-1.0, 0.0, 1.0);\n" 546 " break;\n" 547 " case 3:\n" 548 " gl_Position = vec4( 1.0,-1.0, 0.0, 1.0);\n" 549 " break;\n" 550 " }\n" 551 "}\n"; 552 553 const glw::GLchar* SamplerTest::s_fragment_shader_head = "#version 450\n" 554 "\n" 555 "uniform "; 556 557 const glw::GLchar* SamplerTest::s_fragment_shader_body = " texture_input;\n" 558 "out vec4 texture_output;\n" 559 "\n" 560 "void main()\n" 561 "{\n" 562 " texture_output = "; 563 564 const glw::GLchar* SamplerTest::s_fragment_shader_tail = ";\n" 565 "}\n"; 566 567 } /* IncompleteTextureAccess namespace */ 568 } /* gl4cts namespace */ 569