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