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 "esextcGeometryShaderNonarrayInput.hpp" 25 26#include "gluContextInfo.hpp" 27#include "gluDefs.hpp" 28#include "glwEnums.hpp" 29#include "glwFunctions.hpp" 30#include "tcuTestLog.hpp" 31 32#include <algorithm> 33#include <string> 34#include <vector> 35 36namespace glcts 37{ 38 39/* Fragment shader code */ 40const char* GeometryShaderNonarrayInputCase::m_fs_code = "${VERSION}\n" 41 "\n" 42 "precision highp float;\n" 43 "\n" 44 "out vec4 color;\n" 45 "\n" 46 "void main()\n" 47 "{\n" 48 " color = vec4(0, 1, 0, 1);\n" 49 "}\n"; 50 51/* Geometry shader body parts */ 52const char* GeometryShaderNonarrayInputCase::m_gs_code_preamble = "${VERSION}\n" 53 "${GEOMETRY_SHADER_REQUIRE}\n" 54 "\n"; 55 56const char* GeometryShaderNonarrayInputCase::m_gs_code_body = "layout(points) in;\n" 57 "layout(triangle_strip, max_vertices=4) out;\n" 58 "\n" 59 "#ifndef USE_BLOCK\n" 60 " #define V1 v1[0]\n" 61 " #define V2 v2[0]\n" 62 " #define V3 v3[0]\n" 63 "\n" 64 " in vec4 v1[];\n" 65 " in vec4 v2[];\n" 66 " in vec4 v3[];\n" 67 " \n" 68 " #ifdef CORRUPT\n" 69 " #define V4 v4\n" 70 " in vec4 v4;\n" 71 " #else\n" 72 " #define V4 v4[0]\n" 73 " in vec4 v4[];\n" 74 " #endif\n" 75 "#else\n" 76 " in VS_GS\n" 77 " {\n" 78 " in vec4 v1;\n" 79 " in vec4 v2;\n" 80 " in vec4 v3;\n" 81 " in vec4 v4;\n" 82 " #ifdef CORRUPT\n" 83 " } interface_block;\n" 84 "\n" 85 " #define V1 interface_block.v1\n" 86 " #define V2 interface_block.v2\n" 87 " #define V3 interface_block.v3\n" 88 " #define V4 interface_block.v4\n" 89 " #else\n" 90 " } interface_block[];\n" 91 "\n" 92 " #define V1 interface_block[0].v1\n" 93 " #define V2 interface_block[0].v2\n" 94 " #define V3 interface_block[0].v3\n" 95 " #define V4 interface_block[0].v4\n" 96 " #endif\n" 97 "#endif\n" 98 "\n" 99 "void main()\n" 100 "{\n" 101 " gl_Position = V1;\n" 102 " EmitVertex();\n" 103 " gl_Position = V2;\n" 104 " EmitVertex();\n" 105 " gl_Position = V3;\n" 106 " EmitVertex();\n" 107 " gl_Position = V4;\n" 108 " EmitVertex();\n" 109 " EndPrimitive();\n" 110 "}\n"; 111 112/* Vertex shader body parts */ 113const char* GeometryShaderNonarrayInputCase::m_vs_code_preamble = "${VERSION}\n" 114 "\n"; 115 116const char* GeometryShaderNonarrayInputCase::m_vs_code_body = "#ifndef USE_BLOCK\n" 117 " #define V1 v1\n" 118 " #define V2 v2\n" 119 " #define V3 v3\n" 120 " #define V4 v4\n" 121 "\n" 122 " out vec4 v1;\n" 123 " out vec4 v2;\n" 124 " out vec4 v3;\n" 125 " out vec4 v4;\n" 126 "#else\n" 127 " ${SHADER_IO_BLOCKS_ENABLE}\n" 128 " #define V1 interface_block.v1\n" 129 " #define V2 interface_block.v2\n" 130 " #define V3 interface_block.v3\n" 131 " #define V4 interface_block.v4\n" 132 "\n" 133 " out VS_GS\n" 134 " {\n" 135 " vec4 v1;\n" 136 " vec4 v2;\n" 137 " vec4 v3;\n" 138 " vec4 v4;\n" 139 " } interface_block;\n" 140 "#endif\n" 141 "\n" 142 "void main()\n" 143 "{\n" 144 " V1 = vec4(-1, -1, 0, 1);\n" 145 " V2 = vec4(-1, 1, 0, 1);\n" 146 " V3 = vec4( 1, -1, 0, 1);\n" 147 " V4 = vec4( 1, 1, 0, 1);\n" 148 "}\n"; 149 150/* Definitions */ 151#define TEXTURE_HEIGHT (4) 152#define TEXTURE_WIDTH (4) 153 154/** Constructor 155 * 156 * @param context Test context 157 * @param name Test case's name 158 * @param description Test case's desricption 159 **/ 160GeometryShaderNonarrayInputCase::GeometryShaderNonarrayInputCase(Context& context, const ExtParameters& extParams, 161 const char* name, const char* description) 162 : TestCaseBase(context, extParams, name, description) 163 , m_fbo_id(0) 164 , m_fs(0) 165 , m_gs_invalid_non_ib(0) 166 , m_gs_invalid_ib(0) 167 , m_gs_valid_non_ib(0) 168 , m_gs_valid_ib(0) 169 , m_po_a_invalid(0) 170 , m_po_b_invalid(0) 171 , m_po_a_valid(0) 172 , m_po_b_valid(0) 173 , m_to_id(0) 174 , m_vao_id(0) 175 , m_vs_valid_ib(0) 176 , m_vs_valid_non_ib(0) 177{ 178} 179 180/** Executes the test. 181 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 182 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 183 * Note the function throws exception should an error occur! 184 **/ 185tcu::TestNode::IterateResult GeometryShaderNonarrayInputCase::iterate(void) 186{ 187 glw::GLint compile_status = GL_FALSE; 188 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 189 glw::GLint link_status = GL_FALSE; 190 unsigned int m = 0; 191 unsigned int n = 0; 192 193 /* Form the shaders */ 194 const char* fs_parts[] = { m_fs_code }; 195 const char* gs_invalid_non_ib_parts[] = { m_gs_code_preamble, "#define CORRUPT\n", m_gs_code_body }; 196 const char* gs_invalid_ib_parts[] = { m_gs_code_preamble, "#define CORRUPT\n#define USE_BLOCK\n", m_gs_code_body }; 197 const char* gs_valid_non_ib_parts[] = { m_gs_code_preamble, m_gs_code_body }; 198 const char* gs_valid_ib_parts[] = { m_gs_code_preamble, "#define USE_BLOCK\n", m_gs_code_body }; 199 const char* vs_valid_non_ib_parts[] = { m_vs_code_preamble, m_vs_code_body }; 200 const char* vs_valid_ib_parts[] = { m_vs_code_preamble, "#define USE_BLOCK\n", m_vs_code_body }; 201 202 /* This test should only run if EXT_geometry_shader is supported. 203 * Note that EXT_shader_io_blocks support is implied. */ 204 if (!m_is_geometry_shader_extension_supported) 205 { 206 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 207 } 208 209 /* Create program objects */ 210 m_po_a_invalid = gl.createProgram(); 211 m_po_b_invalid = gl.createProgram(); 212 213 /* Create shader objects */ 214 m_fs = gl.createShader(GL_FRAGMENT_SHADER); 215 m_gs_invalid_non_ib = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 216 m_gs_invalid_ib = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 217 m_gs_valid_non_ib = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 218 m_gs_valid_ib = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 219 m_vs_valid_non_ib = gl.createShader(GL_VERTEX_SHADER); 220 m_vs_valid_ib = gl.createShader(GL_VERTEX_SHADER); 221 222 shaderSourceSpecialized(m_fs, DE_LENGTH_OF_ARRAY(fs_parts), fs_parts); 223 shaderSourceSpecialized(m_gs_invalid_non_ib, DE_LENGTH_OF_ARRAY(gs_invalid_non_ib_parts), gs_invalid_non_ib_parts); 224 shaderSourceSpecialized(m_gs_invalid_ib, DE_LENGTH_OF_ARRAY(gs_invalid_ib_parts), gs_invalid_ib_parts); 225 shaderSourceSpecialized(m_gs_valid_non_ib, DE_LENGTH_OF_ARRAY(gs_valid_non_ib_parts), gs_valid_non_ib_parts); 226 shaderSourceSpecialized(m_gs_valid_ib, DE_LENGTH_OF_ARRAY(gs_valid_ib_parts), gs_valid_ib_parts); 227 shaderSourceSpecialized(m_vs_valid_non_ib, DE_LENGTH_OF_ARRAY(vs_valid_non_ib_parts), vs_valid_non_ib_parts); 228 shaderSourceSpecialized(m_vs_valid_ib, DE_LENGTH_OF_ARRAY(vs_valid_ib_parts), vs_valid_ib_parts); 229 230 /* Create and form invalid programs */ 231 gl.attachShader(m_po_a_invalid, m_fs); 232 gl.attachShader(m_po_a_invalid, m_gs_invalid_non_ib); 233 gl.attachShader(m_po_a_invalid, m_vs_valid_non_ib); 234 235 gl.attachShader(m_po_b_invalid, m_fs); 236 gl.attachShader(m_po_b_invalid, m_gs_invalid_ib); 237 gl.attachShader(m_po_b_invalid, m_vs_valid_ib); 238 239 /* Try to compile the shaders. Do not check GL_COMPILE_STATUS - we expect a linking failure */ 240 gl.compileShader(m_fs); 241 gl.compileShader(m_gs_invalid_non_ib); 242 gl.compileShader(m_gs_invalid_ib); 243 gl.compileShader(m_vs_valid_non_ib); 244 gl.compileShader(m_vs_valid_ib); 245 246 /* Try to link the programs */ 247 gl.linkProgram(m_po_a_invalid); 248 gl.getProgramiv(m_po_a_invalid, GL_LINK_STATUS, &link_status); 249 250 if (link_status != GL_FALSE) 251 { 252 m_testCtx.getLog() << tcu::TestLog::Message 253 << "Program linked sucessfully although it shouldn't because geometry shaders are not " 254 "expected to support non-array input attributes." 255 << tcu::TestLog::EndMessage; 256 257 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 258 return STOP; 259 } 260 261 gl.linkProgram(m_po_b_invalid); 262 gl.getProgramiv(m_po_b_invalid, GL_LINK_STATUS, &link_status); 263 264 if (link_status != GL_FALSE) 265 { 266 m_testCtx.getLog() << tcu::TestLog::Message 267 << "Program linked sucessfully although it shouldn't because geometry shaders are not " 268 "expected to support non-array block input attributes." 269 << tcu::TestLog::EndMessage; 270 271 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 272 return STOP; 273 } 274 275 /* Release the programs before we continue */ 276 gl.deleteProgram(m_po_a_invalid); 277 gl.deleteProgram(m_po_b_invalid); 278 279 m_po_a_invalid = 0; 280 m_po_b_invalid = 0; 281 282 /* Release the invalid geometry shaders */ 283 gl.deleteShader(m_gs_invalid_non_ib); 284 gl.deleteShader(m_gs_invalid_ib); 285 286 m_gs_invalid_non_ib = 0; 287 m_gs_invalid_ib = 0; 288 289 /* Create and form valid programs */ 290 m_po_a_valid = gl.createProgram(); 291 m_po_b_valid = gl.createProgram(); 292 293 gl.attachShader(m_po_a_valid, m_fs); 294 gl.attachShader(m_po_a_valid, m_gs_valid_non_ib); 295 gl.attachShader(m_po_a_valid, m_vs_valid_non_ib); 296 297 gl.attachShader(m_po_b_valid, m_fs); 298 gl.attachShader(m_po_b_valid, m_gs_valid_ib); 299 gl.attachShader(m_po_b_valid, m_vs_valid_ib); 300 301 gl.compileShader(m_gs_valid_non_ib); 302 gl.compileShader(m_gs_valid_ib); 303 304 gl.getShaderiv(m_gs_valid_non_ib, GL_COMPILE_STATUS, &compile_status); 305 306 if (compile_status != GL_TRUE) 307 { 308 std::string log = getCompilationInfoLog(m_gs_valid_non_ib); 309 310 m_testCtx.getLog() << tcu::TestLog::Message << "Valid geometry shader didn't compile. Error message: " << log 311 << tcu::TestLog::EndMessage; 312 313 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 314 return STOP; 315 } 316 317 gl.getShaderiv(m_gs_valid_ib, GL_COMPILE_STATUS, &compile_status); 318 319 if (compile_status != GL_TRUE) 320 { 321 std::string log = getCompilationInfoLog(m_gs_valid_ib); 322 323 m_testCtx.getLog() << tcu::TestLog::Message << "Valid geometry shader didn't compile. Error message: " << log 324 << tcu::TestLog::EndMessage; 325 326 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 327 return STOP; 328 } 329 330 gl.linkProgram(m_po_a_valid); 331 gl.getProgramiv(m_po_a_valid, GL_LINK_STATUS, &link_status); 332 333 if (link_status != GL_TRUE) 334 { 335 std::string log = getLinkingInfoLog(m_po_a_valid); 336 337 m_testCtx.getLog() << tcu::TestLog::Message 338 << "Program failed to link although it was expected to link successfully. Error message: " 339 << log << tcu::TestLog::EndMessage; 340 341 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 342 return STOP; 343 } 344 345 gl.linkProgram(m_po_b_valid); 346 gl.getProgramiv(m_po_b_valid, GL_LINK_STATUS, &link_status); 347 348 if (link_status != GL_TRUE) 349 { 350 std::string log = getLinkingInfoLog(m_po_b_valid); 351 352 m_testCtx.getLog() << tcu::TestLog::Message 353 << "Program failed to link although it was expected to link successfully. Error message: " 354 << log << tcu::TestLog::EndMessage; 355 356 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 357 return STOP; 358 } 359 360 /* Set up a FBO */ 361 gl.genFramebuffers(1, &m_fbo_id); 362 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id); 363 364 gl.genTextures(1, &m_to_id); 365 gl.bindTexture(GL_TEXTURE_2D, m_to_id); 366 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT); 367 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */); 368 369 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set up a framebuffer object"); 370 371 gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT); 372 373 /* Generate and bind a VAO */ 374 gl.genVertexArrays(1, &m_vao_id); 375 gl.bindVertexArray(m_vao_id); 376 377 /* Set up clear color */ 378 gl.clearColor(1.0f, 0, 0, 0); 379 380 /* Use both program objects and verify they work correctly */ 381 for (m = 0; m < 2 /* programs */; ++m) 382 { 383 glw::GLuint program = (m == 0) ? m_po_a_valid : m_po_b_valid; 384 unsigned char result[TEXTURE_WIDTH * TEXTURE_HEIGHT * 4 /*components */]; 385 386 /* Clear the color attachment before we continue */ 387 gl.clear(GL_COLOR_BUFFER_BIT); 388 389 /* Render! */ 390 gl.useProgram(program); 391 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 392 393 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed"); 394 395 /* Read back the result */ 396 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, result); 397 398 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color attachment 0"); 399 400 /* Verify the result data is correct */ 401 for (n = 0; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n) 402 { 403 if (result[n * 4 + 0] != 0 || result[n * 4 + 1] != 255 || result[n * 4 + 2] != 0 || 404 result[n * 4 + 3] != 255) 405 { 406 m_testCtx.getLog() << tcu::TestLog::Message 407 << "Pixel data isn't correct. All pixels should have green color. Pixel at: " 408 << "[" << n / 4 << ", " << n % 4 << "] " 409 << "has color: " 410 << "[" << result[n * 4 + 0] << ", " << result[n * 4 + 1] << ", " << result[n * 4 + 2] 411 << ", " << result[n * 4 + 3] << "]" << tcu::TestLog::EndMessage; 412 413 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 414 return STOP; 415 } /* if (result data is invalid) */ 416 } /* for (all pixels) */ 417 } /* for (all programs) */ 418 419 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 420 return STOP; 421} 422 423/** Deinitializes GLES objects created during the test. 424 * 425 */ 426void GeometryShaderNonarrayInputCase::deinit(void) 427{ 428 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 429 430 /* Reset OpenGL ES state */ 431 gl.useProgram(0); 432 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 433 gl.bindVertexArray(0); 434 435 if (m_po_a_valid != 0) 436 { 437 gl.deleteProgram(m_po_a_valid); 438 } 439 440 if (m_po_b_valid != 0) 441 { 442 gl.deleteProgram(m_po_b_valid); 443 } 444 445 if (m_fs != 0) 446 { 447 gl.deleteShader(m_fs); 448 } 449 450 if (m_gs_invalid_ib != 0) 451 { 452 gl.deleteShader(m_gs_invalid_ib); 453 } 454 455 if (m_gs_invalid_non_ib != 0) 456 { 457 gl.deleteShader(m_gs_invalid_non_ib); 458 } 459 460 if (m_gs_valid_ib != 0) 461 { 462 gl.deleteShader(m_gs_valid_ib); 463 } 464 465 if (m_gs_valid_non_ib != 0) 466 { 467 gl.deleteShader(m_gs_valid_non_ib); 468 } 469 470 if (m_vs_valid_ib != 0) 471 { 472 gl.deleteShader(m_vs_valid_ib); 473 } 474 475 if (m_vs_valid_non_ib != 0) 476 { 477 gl.deleteShader(m_vs_valid_non_ib); 478 } 479 480 if (m_to_id != 0) 481 { 482 gl.deleteTextures(1, &m_to_id); 483 } 484 485 if (m_fbo_id != 0) 486 { 487 gl.deleteFramebuffers(1, &m_fbo_id); 488 } 489 490 if (m_vao_id != 0) 491 { 492 gl.deleteVertexArrays(1, &m_vao_id); 493 } 494 495 /* Release base class */ 496 TestCaseBase::deinit(); 497} 498 499} // namespace glcts 500