es31cShaderImageSizeTests.cpp revision 84322c9402f810da3cd80b52e9f9ef72150a9004
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 "es31cShaderImageSizeTests.hpp" 25#include "gluContextInfo.hpp" 26#include "glwEnums.hpp" 27#include "tcuMatrix.hpp" 28#include "tcuRenderTarget.hpp" 29#include "tcuVectorUtil.hpp" 30#include <assert.h> 31#include <cstdarg> 32 33namespace glcts 34{ 35using namespace glw; 36 37namespace 38{ 39typedef tcu::Vec2 vec2; 40typedef tcu::Vec3 vec3; 41typedef tcu::Vec4 vec4; 42typedef tcu::IVec4 ivec4; 43typedef tcu::UVec4 uvec4; 44 45static tcu::TestLog* currentLog; 46void setOutput(tcu::TestLog& log) 47{ 48 currentLog = &log; 49} 50 51void Output(const char* format, ...) 52{ 53 va_list args; 54 va_start(args, format); 55 56 const int MAX_OUTPUT_STRING_SIZE = 40000; 57 static char temp[MAX_OUTPUT_STRING_SIZE]; 58 59 vsnprintf(temp, MAX_OUTPUT_STRING_SIZE - 1, format, args); 60 temp[MAX_OUTPUT_STRING_SIZE - 1] = '\0'; 61 62 char* logLine = strtok(temp, "\n"); 63 while (logLine != NULL) 64 { 65 currentLog->writeMessage(logLine); 66 logLine = strtok(NULL, "\n"); 67 } 68 va_end(args); 69} 70 71const char* const kGLSLVer = 72 "#version 310 es\n" NL "precision highp float;" NL "precision highp int;" NL "precision highp image2D;" NL 73 "precision highp image3D;" NL "precision highp imageCube;" NL "precision highp image2DArray;" NL 74 "precision highp iimage2D;" NL "precision highp iimage3D;" NL "precision highp iimageCube;" NL 75 "precision highp iimage2DArray;" NL "precision highp uimage2D;" NL "precision highp uimage3D;" NL 76 "precision highp uimageCube;" NL "precision highp uimage2DArray;"; 77 78class ShaderImageSizeBase : public glcts::SubcaseBase 79{ 80public: 81 virtual std::string Title() 82 { 83 return NL ""; 84 } 85 virtual std::string Purpose() 86 { 87 return NL ""; 88 } 89 virtual std::string Method() 90 { 91 return NL ""; 92 } 93 virtual std::string PassCriteria() 94 { 95 return NL ""; 96 } 97 bool IsVSFSAvailable(int requiredVS, int requiredFS) 98 { 99 GLint imagesVS, imagesFS; 100 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS); 101 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &imagesFS); 102 if (imagesVS >= requiredVS && imagesFS >= requiredFS) 103 return true; 104 else 105 { 106 std::ostringstream reason; 107 reason << "Required " << requiredVS << " VS storage blocks but only " << imagesVS << " available." 108 << std::endl 109 << "Required " << requiredFS << " FS storage blocks but only " << imagesFS << " available." 110 << std::endl; 111 OutputNotSupported(reason.str()); 112 return false; 113 } 114 } 115}; 116 117template <typename T> 118std::string ImageTypePrefix(); 119 120template <> 121std::string ImageTypePrefix<vec4>() 122{ 123 return ""; 124} 125 126template <> 127std::string ImageTypePrefix<ivec4>() 128{ 129 return "i"; 130} 131 132template <> 133std::string ImageTypePrefix<uvec4>() 134{ 135 return "u"; 136} 137 138template <typename T> 139std::string ImageFormatPostfix(); 140 141template <> 142std::string ImageFormatPostfix<vec4>() 143{ 144 return "f"; 145} 146 147template <> 148std::string ImageFormatPostfix<ivec4>() 149{ 150 return "i"; 151} 152 153template <> 154std::string ImageFormatPostfix<uvec4>() 155{ 156 return "ui"; 157} 158 159template <typename T> 160GLenum TexInternalFormat(); 161 162template <> 163GLenum TexInternalFormat<vec4>() 164{ 165 return GL_RGBA32F; 166} 167 168template <> 169GLenum TexInternalFormat<ivec4>() 170{ 171 return GL_RGBA32I; 172} 173 174template <> 175GLenum TexInternalFormat<uvec4>() 176{ 177 return GL_RGBA32UI; 178} 179 180template <typename T> 181GLenum TexType(); 182 183template <typename T> 184GLenum TexFormat(); 185 186//============================================================================= 187// ImageSizeMachine 188//----------------------------------------------------------------------------- 189class ImageSizeMachine : public glcts::GLWrapper 190{ 191 GLuint m_pipeline; 192 GLuint m_program[3]; 193 GLuint m_vertex_array; 194 GLuint m_buffer; 195 bool pipeline; 196 GLuint m_xfb_id; 197 198 bool CheckProgram(GLuint program) 199 { 200 if (program == 0) 201 return true; 202 GLint status; 203 glGetProgramiv(program, GL_LINK_STATUS, &status); 204 205 if (status == GL_FALSE) 206 { 207 GLint attached_shaders; 208 glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders); 209 210 if (attached_shaders > 0) 211 { 212 std::vector<GLuint> shaders(attached_shaders); 213 glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]); 214 215 for (GLint i = 0; i < attached_shaders; ++i) 216 { 217 GLenum type; 218 glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type)); 219 switch (type) 220 { 221 case GL_VERTEX_SHADER: 222 Output("*** Vertex Shader ***\n"); 223 break; 224 case GL_FRAGMENT_SHADER: 225 Output("*** Fragment Shader ***\n"); 226 break; 227 case GL_COMPUTE_SHADER: 228 Output("*** Compute Shader ***\n"); 229 break; 230 default: 231 Output("*** Unknown Shader ***\n"); 232 break; 233 } 234 GLint length; 235 glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length); 236 if (length > 0) 237 { 238 std::vector<GLchar> source(length); 239 glGetShaderSource(shaders[i], length, NULL, &source[0]); 240 Output("%s\n", &source[0]); 241 } 242 glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length); 243 if (length > 0) 244 { 245 std::vector<GLchar> log(length); 246 glGetShaderInfoLog(shaders[i], length, NULL, &log[0]); 247 Output("%s\n", &log[0]); 248 } 249 } 250 } 251 GLint length; 252 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); 253 if (length > 0) 254 { 255 std::vector<GLchar> log(length); 256 glGetProgramInfoLog(program, length, NULL, &log[0]); 257 Output("%s\n", &log[0]); 258 } 259 } 260 return status == GL_TRUE ? true : false; 261 } 262 263 bool CompileShader(GLuint shader) 264 { 265 glCompileShader(shader); 266 267 GLint status; 268 glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 269 if (status == GL_FALSE) 270 { 271 GLsizei length; 272 GLchar log[1024]; 273 glGetShaderInfoLog(shader, sizeof(log), &length, log); 274 if (length > 1) 275 { 276 Output("Shader Info Log:\n%s\n", log); 277 } 278 return false; 279 } 280 return true; 281 } 282 283 bool LinkProgram(GLuint program) 284 { 285 glLinkProgram(program); 286 287 GLint status; 288 glGetProgramiv(program, GL_LINK_STATUS, &status); 289 if (status == GL_FALSE) 290 { 291 GLsizei length; 292 GLchar log[1024]; 293 glGetProgramInfoLog(program, sizeof(log), &length, log); 294 if (length > 1) 295 { 296 Output("Program Info Log:\n%s\n", log); 297 } 298 return false; 299 } 300 return true; 301 } 302 303 GLuint CreateComputeProgram(const std::string& cs) 304 { 305 const GLuint p = glCreateProgram(); 306 307 if (!cs.empty()) 308 { 309 const GLuint sh = glCreateShader(GL_COMPUTE_SHADER); 310 glAttachShader(p, sh); 311 glDeleteShader(sh); 312 const char* const src[2] = { kGLSLVer, cs.c_str() }; 313 glShaderSource(sh, 2, src, NULL); 314 if (!CompileShader(sh)) 315 { 316 Output("%s%s\n", src[0], src[1]); 317 return p; 318 } 319 } 320 if (!LinkProgram(p)) 321 { 322 if (!cs.empty()) 323 Output("%s%s\n", kGLSLVer, cs.c_str()); 324 return p; 325 } 326 327 return p; 328 } 329 330 GLuint BuildProgram(const char* src_vs, const char* src_fs, bool use_xfb, bool* result = NULL) 331 { 332 const GLuint p = glCreateProgram(); 333 334 if (src_vs) 335 { 336 GLuint sh = glCreateShader(GL_VERTEX_SHADER); 337 glAttachShader(p, sh); 338 glDeleteShader(sh); 339 const char* const src[2] = { kGLSLVer, src_vs }; 340 glShaderSource(sh, 2, src, NULL); 341 if (!CompileShader(sh)) 342 { 343 Output("%s%s\n", src[0], src[1]); 344 if (result) 345 *result = false; 346 return p; 347 } 348 } 349 if (src_fs) 350 { 351 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER); 352 glAttachShader(p, sh); 353 glDeleteShader(sh); 354 const char* const src[2] = { kGLSLVer, src_fs }; 355 glShaderSource(sh, 2, src, NULL); 356 if (!CompileShader(sh)) 357 { 358 Output("%s%s\n", src[0], src[1]); 359 if (result) 360 *result = false; 361 return p; 362 } 363 } 364 if (use_xfb) 365 SetupTransformFeedback(p); 366 if (!LinkProgram(p)) 367 { 368 if (src_vs) 369 Output("%s%s\n", kGLSLVer, src_vs); 370 if (src_fs) 371 Output("%s%s\n", kGLSLVer, src_fs); 372 if (result) 373 *result = false; 374 return p; 375 } 376 377 return p; 378 } 379 380 void SetupTransformFeedback(GLuint program) 381 { 382 const char* const varying_name[] = { "count[0]", "count[1]", "count[2]", "count[3]" }; 383 glTransformFeedbackVaryings(program, 4, varying_name, GL_INTERLEAVED_ATTRIBS); 384 } 385 386 inline bool Equal(const ivec4& result, const ivec4& expected) 387 { 388 if (expected[0] != result[0]) 389 return false; 390 if (expected[1] != result[1]) 391 return false; 392 if (expected[2] != result[2]) 393 return false; 394 if (expected[3] != result[3]) 395 return false; 396 return true; 397 } 398 399 template <typename T> 400 std::string GenShader(int stage) 401 { 402 std::ostringstream os; 403 os << NL "#define KSIZE 4"; 404 if (stage == 0) 405 { // VS uses transform feedback 406 os << NL "flat out ivec4 count[KSIZE];"; 407 } 408 else 409 { // CS + FS use SSBO 410 os << NL "layout(std430) buffer OutputBuffer {" NL " ivec4 count[KSIZE];" NL "};"; 411 } 412 os << NL "layout(binding = 0, rgba32" << ImageFormatPostfix<T>() << ") readonly writeonly uniform highp " 413 << ImageTypePrefix<T>() << "image2D g_image_2d;" NL "layout(binding = 1, rgba32" << ImageFormatPostfix<T>() 414 << ") readonly writeonly uniform highp " << ImageTypePrefix<T>() 415 << "image3D g_image_3d;" NL "layout(binding = 2, rgba32" << ImageFormatPostfix<T>() 416 << ") readonly writeonly uniform highp " << ImageTypePrefix<T>() 417 << "imageCube g_image_cube;" NL "layout(binding = 3, rgba32" << ImageFormatPostfix<T>() 418 << ") readonly writeonly uniform highp " << ImageTypePrefix<T>() << "image2DArray g_image_2d_array;"; 419 if (stage == 0) 420 { // VS 421 os << NL "void main() {" NL " int coord = gl_VertexID;" NL "#ifdef GL_ES" NL " gl_PointSize = 1.0;" NL 422 "#endif"; 423 } 424 else if (stage == 4) 425 { // CS 426 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL " int coord = int(gl_GlobalInvocationID.x);"; 427 } 428 else if (stage == 5) 429 { // FS 430 os << NL "uniform int fakePrimitiveID;" NL "void main() {" NL " int coord = fakePrimitiveID;"; 431 } 432 os << NL " count[coord + 0] = ivec4(imageSize(g_image_2d), 0, 0);" NL 433 " count[coord + 1] = ivec4(imageSize(g_image_3d), 0);" NL 434 " count[coord + 2] = ivec4(imageSize(g_image_cube), 0, 0);" NL 435 " count[coord + 3] = ivec4(imageSize(g_image_2d_array), 0);" NL "}"; 436 return os.str(); 437 } 438 439public: 440 ImageSizeMachine() : pipeline(false) 441 { 442 if (pipeline) 443 glGenProgramPipelines(1, &m_pipeline); 444 memset(m_program, 0, sizeof(m_program)); 445 glGenVertexArrays(1, &m_vertex_array); 446 glGenBuffers(1, &m_buffer); 447 glGenTransformFeedbacks(1, &m_xfb_id); 448 } 449 450 ~ImageSizeMachine() 451 { 452 if (pipeline) 453 { 454 glDeleteProgramPipelines(1, &m_pipeline); 455 for (int i = 0; i < 3; ++i) 456 glDeleteProgram(m_program[i]); 457 } 458 else 459 { 460 glDeleteProgram(m_program[0]); 461 } 462 glDeleteVertexArrays(1, &m_vertex_array); 463 glDeleteBuffers(1, &m_buffer); 464 glDeleteTransformFeedbacks(1, &m_xfb_id); 465 } 466 467 template <typename T> 468 long Run(int stage, ivec4 expected_result[4]) 469 { 470 const int kSize = 4; 471 if (stage == 0) 472 { // VS 473 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id); 474 const char* const glsl_fs = NL "void main() {" NL " discard;" NL "}"; 475 std::string vs = GenShader<T>(stage); 476 const char* const glsl_vs = vs.c_str(); 477 if (pipeline) 478 { 479 m_program[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs); 480 m_program[1] = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs); 481 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]); 482 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_program[1]); 483 } 484 else 485 { 486 m_program[0] = BuildProgram(glsl_vs, glsl_fs, true); 487 } 488 } 489 else if (stage == 4) 490 { // CS 491 std::string cs = GenShader<T>(stage); 492 const char* const glsl_cs = cs.c_str(); 493 if (pipeline) 494 { 495 m_program[0] = glCreateShaderProgramv(GL_COMPUTE_SHADER, 1, &glsl_cs); 496 glUseProgramStages(m_pipeline, GL_COMPUTE_SHADER_BIT, m_program[0]); 497 } 498 else 499 { 500 m_program[0] = CreateComputeProgram(glsl_cs); 501 } 502 } 503 else if (stage == 5) 504 { // FS 505 const char* const glsl_vs = 506 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL 507 "#ifdef GL_ES" NL " gl_PointSize = 1.0;" NL "#endif" NL "}"; 508 std::string fs = GenShader<T>(stage); 509 const char* const glsl_fs = fs.c_str(); 510 if (pipeline) 511 { 512 m_program[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs); 513 m_program[1] = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs); 514 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]); 515 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_program[1]); 516 } 517 else 518 { 519 m_program[0] = BuildProgram(glsl_vs, glsl_fs, false); 520 } 521 } 522 if (!CheckProgram(m_program[0])) 523 return ERROR; 524 if (pipeline) 525 if (!CheckProgram(m_program[1])) 526 return ERROR; 527 528 ivec4 data[kSize]; 529 for (int i = 0; i < kSize; ++i) 530 data[i] = ivec4(100000); 531 532 GLenum output_buffer_type = (stage == 0) ? GL_TRANSFORM_FEEDBACK_BUFFER : GL_SHADER_STORAGE_BUFFER; 533 534 glBindBufferBase(output_buffer_type, 0, m_buffer); 535 glBufferData(output_buffer_type, kSize * 4 * 4, &data[0], GL_STATIC_DRAW); 536 537 if (pipeline) 538 glBindProgramPipeline(m_pipeline); 539 else 540 glUseProgram(m_program[0]); 541 glBindVertexArray(m_vertex_array); 542 543 if (stage == 0) 544 glBeginTransformFeedback(GL_POINTS); 545 546 if (stage == 4) 547 glDispatchCompute(1, 1, 1); 548 else 549 glDrawArrays(GL_POINTS, 0, 1); 550 551 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 552 553 if (stage == 0) 554 glEndTransformFeedback(); 555 556 ivec4* map_data = (ivec4*)glMapBufferRange(output_buffer_type, 0, kSize * 4 * 4, GL_MAP_READ_BIT); 557 for (int i = 0; i < kSize; ++i) 558 { 559 if (!Equal(map_data[i], expected_result[i])) 560 { 561 Output("Returned value is: (%d %d %d %d). Expected value is: (%d %d %d %d). Image unit is: %d.\n", 562 map_data[i][0], map_data[i][1], map_data[i][2], map_data[i][3], expected_result[i][0], 563 expected_result[i][1], expected_result[i][2], expected_result[i][3], i); 564 return ERROR; 565 } 566 } 567 glUnmapBuffer(output_buffer_type); 568 569 if (stage == 0) 570 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); 571 572 return NO_ERROR; 573 } 574}; 575 576//============================================================================= 577// 1.1.x.y BasicNonMS 578//----------------------------------------------------------------------------- 579template <typename T, int STAGE> 580class BasicNonMS : public ShaderImageSizeBase 581{ 582 GLuint m_texture[4]; 583 584 virtual long Setup() 585 { 586 glGenTextures(4, m_texture); 587 return NO_ERROR; 588 } 589 virtual long Run() 590 { 591 if (STAGE == 0 && !IsVSFSAvailable(4, 0)) 592 return NOT_SUPPORTED; 593 if (STAGE == 5 && !IsVSFSAvailable(0, 4)) 594 return NOT_SUPPORTED; 595 596 const GLenum target[4] = { GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY }; 597 for (int i = 0; i < 4; ++i) 598 { 599 glBindTexture(target[i], m_texture[i]); 600 glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); 601 glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); 602 603 if (i == 0) 604 { 605 glTexStorage2D(target[i], 10, TexInternalFormat<T>(), 512, 128); 606 glBindImageTexture(0, m_texture[i], 1, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>()); 607 } 608 else if (i == 1) 609 { 610 glTexStorage3D(target[i], 3, TexInternalFormat<T>(), 8, 8, 4); 611 glBindImageTexture(1, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); 612 } 613 else if (i == 2) 614 { 615 glTexStorage2D(target[i], 4, TexInternalFormat<T>(), 16, 16); 616 glBindImageTexture(2, m_texture[i], 0, GL_TRUE, 0, GL_READ_WRITE, TexInternalFormat<T>()); 617 } 618 else if (i == 3) 619 { 620 glTexStorage3D(target[i], 3, TexInternalFormat<T>(), 127, 39, 12); 621 glBindImageTexture(3, m_texture[i], 2, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); 622 } 623 } 624 ImageSizeMachine machine; 625 ivec4 res[4] = { ivec4(256, 64, 0, 0), ivec4(8, 8, 4, 0), ivec4(16, 16, 0, 0), ivec4(31, 9, 12, 0) }; 626 return machine.Run<T>(STAGE, res); 627 } 628 virtual long Cleanup() 629 { 630 glDeleteTextures(4, m_texture); 631 return NO_ERROR; 632 } 633}; 634//============================================================================= 635// 2.2.x.y AdvancedNonMS 636//----------------------------------------------------------------------------- 637template <typename T, int STAGE> 638class AdvancedNonMS : public ShaderImageSizeBase 639{ 640 GLuint m_texture[4]; 641 642 virtual long Setup() 643 { 644 glGenTextures(4, m_texture); 645 return NO_ERROR; 646 } 647 virtual long Run() 648 { 649 if (STAGE == 0 && !IsVSFSAvailable(4, 0)) 650 return NOT_SUPPORTED; 651 if (STAGE == 5 && !IsVSFSAvailable(0, 4)) 652 return NOT_SUPPORTED; 653 654 const GLenum target[4] = { GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY }; 655 for (int i = 0; i < 4; ++i) 656 { 657 glBindTexture(target[i], m_texture[i]); 658 glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); 659 glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); 660 661 if (i == 0) 662 { 663 glTexStorage3D(target[i], 2, TexInternalFormat<T>(), 2, 2, 7); 664 glBindImageTexture(0, m_texture[i], 1, GL_FALSE, 3, GL_READ_ONLY, TexInternalFormat<T>()); 665 } 666 else if (i == 1) 667 { 668 glTexStorage3D(target[i], 3, TexInternalFormat<T>(), 4, 4, 2); 669 glBindImageTexture(1, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); 670 } 671 else if (i == 2) 672 { 673 glTexStorage2D(target[i], 2, TexInternalFormat<T>(), 2, 2); 674 glBindImageTexture(2, m_texture[i], 0, GL_TRUE, 0, GL_READ_WRITE, TexInternalFormat<T>()); 675 } 676 else if (i == 3) 677 { 678 glTexStorage3D(target[i], 4, TexInternalFormat<T>(), 13, 7, 4); 679 glBindImageTexture(3, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>()); 680 } 681 } 682 ImageSizeMachine machine; 683 ivec4 res[4] = { ivec4(1, 1, 0, 0), ivec4(2, 2, 1, 0), ivec4(2, 2, 0, 0), ivec4(6, 3, 4, 0) }; 684 return machine.Run<T>(STAGE, res); 685 } 686 virtual long Cleanup() 687 { 688 glDeleteTextures(4, m_texture); 689 return NO_ERROR; 690 } 691}; 692//============================================================================= 693// 4.1 NegativeCompileTime 694//----------------------------------------------------------------------------- 695class NegativeCompileTime : public ShaderImageSizeBase 696{ 697 virtual long Run() 698 { 699 if (!Compile( // imagesize return type check 700 "#version 310 es" NL "precision highp float;" NL "precision highp int;" NL 701 "layout(local_size_x = 1) in;" NL "layout(r32f) uniform image2D g_image;" NL 702 "layout(std430) buffer OutputBuffer { vec4 g_color; };" NL "void main() {" NL 703 " if (imageSize(g_image) == ivec3(5)) g_color = vec4(0, 1, 0, 1);" NL 704 " else g_color = vec4(1, 0, 0, 1);" NL "}")) 705 { 706 return ERROR; 707 } 708 if (!Compile( // imageSize(samplertype) 709 "#version 310 es" NL "precision highp float;" NL "precision highp int;" NL 710 "layout(local_size_x = 1) in;" NL "layout(r32f) uniform sampler2D g_image;" NL 711 "layout(std430) buffer OutputBuffer { vec4 g_color; };" NL "void main() {" NL 712 " if (imageSize(g_image) == ivec2(5)) g_color = vec4(0, 1, 0, 1);" NL 713 " else g_color = vec4(1, 0, 0, 1);" NL "}")) 714 { 715 return ERROR; 716 } 717 return NO_ERROR; 718 } 719 720 bool Compile(const std::string& source) 721 { 722 const GLuint sh = glCreateShader(GL_COMPUTE_SHADER); 723 724 const char* const src = source.c_str(); 725 glShaderSource(sh, 1, &src, NULL); 726 glCompileShader(sh); 727 728 GLchar log[1024]; 729 glGetShaderInfoLog(sh, sizeof(log), NULL, log); 730 Output("Shader Info Log:\n%s\n", log); 731 732 GLint status; 733 glGetShaderiv(sh, GL_COMPILE_STATUS, &status); 734 glDeleteShader(sh); 735 736 if (status == GL_TRUE) 737 { 738 Output("Compilation should fail.\n"); 739 return false; 740 } 741 return true; 742 } 743}; 744 745} // anonymous namespace 746 747ShaderImageSizeTests::ShaderImageSizeTests(glcts::Context& context) : TestCaseGroup(context, "shader_image_size", "") 748{ 749} 750 751ShaderImageSizeTests::~ShaderImageSizeTests(void) 752{ 753} 754 755void ShaderImageSizeTests::init() 756{ 757 using namespace glcts; 758 setOutput(m_context.getTestContext().getLog()); 759 addChild(new TestSubcase(m_context, "basic-nonMS-vs-float", TestSubcase::Create<BasicNonMS<vec4, 0> >)); 760 addChild(new TestSubcase(m_context, "basic-nonMS-vs-int", TestSubcase::Create<BasicNonMS<ivec4, 0> >)); 761 addChild(new TestSubcase(m_context, "basic-nonMS-vs-uint", TestSubcase::Create<BasicNonMS<uvec4, 0> >)); 762 addChild(new TestSubcase(m_context, "basic-nonMS-fs-float", TestSubcase::Create<BasicNonMS<vec4, 5> >)); 763 addChild(new TestSubcase(m_context, "basic-nonMS-fs-int", TestSubcase::Create<BasicNonMS<ivec4, 5> >)); 764 addChild(new TestSubcase(m_context, "basic-nonMS-fs-uint", TestSubcase::Create<BasicNonMS<uvec4, 5> >)); 765 addChild(new TestSubcase(m_context, "basic-nonMS-cs-float", TestSubcase::Create<BasicNonMS<vec4, 4> >)); 766 addChild(new TestSubcase(m_context, "basic-nonMS-cs-int", TestSubcase::Create<BasicNonMS<ivec4, 4> >)); 767 addChild(new TestSubcase(m_context, "basic-nonMS-cs-uint", TestSubcase::Create<BasicNonMS<uvec4, 4> >)); 768 addChild(new TestSubcase(m_context, "advanced-nonMS-vs-float", TestSubcase::Create<AdvancedNonMS<vec4, 0> >)); 769 addChild(new TestSubcase(m_context, "advanced-nonMS-vs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 0> >)); 770 addChild(new TestSubcase(m_context, "advanced-nonMS-vs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 0> >)); 771 addChild(new TestSubcase(m_context, "advanced-nonMS-fs-float", TestSubcase::Create<AdvancedNonMS<vec4, 5> >)); 772 addChild(new TestSubcase(m_context, "advanced-nonMS-fs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 5> >)); 773 addChild(new TestSubcase(m_context, "advanced-nonMS-fs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 5> >)); 774 addChild(new TestSubcase(m_context, "advanced-nonMS-cs-float", TestSubcase::Create<AdvancedNonMS<vec4, 4> >)); 775 addChild(new TestSubcase(m_context, "advanced-nonMS-cs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 4> >)); 776 addChild(new TestSubcase(m_context, "advanced-nonMS-cs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 4> >)); 777 addChild(new TestSubcase(m_context, "negative-compileTime", TestSubcase::Create<NegativeCompileTime>)); 778} 779} 780