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 "gl4cShaderImageLoadStoreTests.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 <climits> 32#include <cstdarg> 33#include <deque> 34#include <iomanip> 35#include <map> 36#include <sstream> 37#include <tcuFloat.hpp> 38 39namespace gl4cts 40{ 41using namespace glw; 42 43namespace 44{ 45typedef tcu::Vec2 vec2; 46typedef tcu::Vec4 vec4; 47typedef tcu::IVec4 ivec4; 48typedef tcu::UVec4 uvec4; 49typedef tcu::Mat4 mat4; 50 51class ShaderImageLoadStoreBase : public deqp::SubcaseBase 52{ 53 virtual std::string Title() 54 { 55 return ""; 56 } 57 58 virtual std::string Purpose() 59 { 60 return ""; 61 } 62 63 virtual std::string Method() 64 { 65 return ""; 66 } 67 68 virtual std::string PassCriteria() 69 { 70 return ""; 71 } 72 73public: 74 bool SupportedInVS(int requiredVS) 75 { 76 GLint imagesVS; 77 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS); 78 if (imagesVS >= requiredVS) 79 return true; 80 else 81 { 82 std::ostringstream reason; 83 reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available." 84 << std::endl; 85 OutputNotSupported(reason.str()); 86 return false; 87 } 88 } 89 90 bool SupportedInTCS(int requiredTCS) 91 { 92 GLint imagesTCS; 93 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS); 94 if (imagesTCS >= requiredTCS) 95 return true; 96 else 97 { 98 std::ostringstream reason; 99 reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available." 100 << std::endl; 101 OutputNotSupported(reason.str()); 102 return false; 103 } 104 } 105 106 bool SupportedInTES(int requiredTES) 107 { 108 GLint imagesTES; 109 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES); 110 if (imagesTES >= requiredTES) 111 return true; 112 else 113 { 114 std::ostringstream reason; 115 reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available." 116 << std::endl; 117 OutputNotSupported(reason.str()); 118 return false; 119 } 120 } 121 122 bool SupportedInGS(int requiredGS) 123 { 124 GLint imagesGS; 125 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS); 126 if (imagesGS >= requiredGS) 127 return true; 128 else 129 { 130 std::ostringstream reason; 131 reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available." 132 << std::endl; 133 OutputNotSupported(reason.str()); 134 return false; 135 } 136 } 137 138 bool SupportedInGeomStages(int required) 139 { 140 return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) && 141 SupportedInGS(required); 142 } 143 144 bool SupportedInStage(int stage, int required) 145 { 146 switch (stage) 147 { 148 case 0: 149 return SupportedInVS(required); 150 case 1: 151 return SupportedInTCS(required); 152 case 2: 153 return SupportedInTES(required); 154 case 3: 155 return SupportedInGS(required); 156 default: 157 return true; 158 } 159 } 160 161 bool SupportedSamples(int required) 162 { 163 int i; 164 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i); 165 if (i >= required) 166 return true; 167 else 168 { 169 std::ostringstream reason; 170 reason << "Required " << required << " image samples but only " << i << " available." << std::endl; 171 OutputNotSupported(reason.str()); 172 return false; 173 } 174 } 175 176 int getWindowWidth() 177 { 178 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 179 return renderTarget.getWidth(); 180 } 181 182 int getWindowHeight() 183 { 184 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 185 return renderTarget.getHeight(); 186 } 187 188 inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon) 189 { 190 if (fabs(c0[0] - c1[0]) > epsilon[0]) 191 return false; 192 if (fabs(c0[1] - c1[1]) > epsilon[1]) 193 return false; 194 if (fabs(c0[2] - c1[2]) > epsilon[2]) 195 return false; 196 if (fabs(c0[3] - c1[3]) > epsilon[3]) 197 return false; 198 return true; 199 } 200 201 bool IsEqual(vec4 a, vec4 b) 202 { 203 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]); 204 } 205 206 bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat) 207 { 208 if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM) 209 { 210 return ColorEqual(v0, v1, vec4(0.0001f)); 211 } 212 else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM) 213 { 214 return ColorEqual(v0, v1, vec4(0.01f)); 215 } 216 return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]); 217 } 218 219 bool Equal(const ivec4& a, const ivec4& b, GLenum) 220 { 221 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]); 222 } 223 224 bool Equal(const uvec4& a, const uvec4& b, GLenum) 225 { 226 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]); 227 } 228 229 template <class T> 230 std::string ToString(T v) 231 { 232 std::ostringstream s; 233 s << "["; 234 for (int i = 0; i < 4; ++i) 235 s << v[i] << (i == 3 ? "" : ","); 236 s << "]"; 237 return s.str(); 238 } 239 240 bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected) 241 { 242 bool status = true; 243 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 244 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat(); 245 vec4 g_color_eps = vec4( 246 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits), 247 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits)); 248 249 std::vector<vec4> fb(w * h); 250 glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]); 251 252 for (int yy = 0; yy < h; ++yy) 253 { 254 for (int xx = 0; xx < w; ++xx) 255 { 256 const int idx = yy * w + xx; 257 if (!ColorEqual(fb[idx], expected, g_color_eps)) 258 { 259 m_context.getTestContext().getLog() 260 << tcu::TestLog::Message << "First bad color: " << ToString(fb[idx]) 261 << tcu::TestLog::EndMessage; 262 status = false; 263 return status; 264 } 265 } 266 } 267 return status; 268 } 269 270 bool CompileShader(GLuint shader) 271 { 272 glCompileShader(shader); 273 274 GLint status; 275 glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 276 if (status == GL_FALSE) 277 { 278 GLsizei length; 279 GLchar log[1024]; 280 glGetShaderInfoLog(shader, sizeof(log), &length, log); 281 if (length > 1) 282 { 283 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n" 284 << log << tcu::TestLog::EndMessage; 285 } 286 return false; 287 } 288 return true; 289 } 290 291 bool LinkProgram(GLuint program) 292 { 293 glLinkProgram(program); 294 295 GLint status; 296 glGetProgramiv(program, GL_LINK_STATUS, &status); 297 if (status == GL_FALSE) 298 { 299 GLsizei length; 300 GLchar log[1024]; 301 glGetProgramInfoLog(program, sizeof(log), &length, log); 302 if (length > 1) 303 { 304 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n" 305 << log << tcu::TestLog::EndMessage; 306 } 307 return false; 308 } 309 return true; 310 } 311 312 GLuint BuildProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs, 313 const char* src_fs, bool* result = NULL) 314 { 315 const GLuint p = glCreateProgram(); 316 317 if (src_vs) 318 { 319 GLuint sh = glCreateShader(GL_VERTEX_SHADER); 320 glAttachShader(p, sh); 321 glDeleteShader(sh); 322 glShaderSource(sh, 1, &src_vs, NULL); 323 if (!CompileShader(sh)) 324 { 325 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage; 326 if (result) 327 *result = false; 328 return p; 329 } 330 } 331 if (src_tcs) 332 { 333 GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER); 334 glAttachShader(p, sh); 335 glDeleteShader(sh); 336 glShaderSource(sh, 1, &src_tcs, NULL); 337 if (!CompileShader(sh)) 338 { 339 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage; 340 if (result) 341 *result = false; 342 return p; 343 } 344 } 345 if (src_tes) 346 { 347 GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER); 348 glAttachShader(p, sh); 349 glDeleteShader(sh); 350 glShaderSource(sh, 1, &src_tes, NULL); 351 if (!CompileShader(sh)) 352 { 353 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage; 354 if (result) 355 *result = false; 356 return p; 357 } 358 } 359 if (src_gs) 360 { 361 GLuint sh = glCreateShader(GL_GEOMETRY_SHADER); 362 glAttachShader(p, sh); 363 glDeleteShader(sh); 364 glShaderSource(sh, 1, &src_gs, NULL); 365 if (!CompileShader(sh)) 366 { 367 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage; 368 if (result) 369 *result = false; 370 return p; 371 } 372 } 373 if (src_fs) 374 { 375 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER); 376 glAttachShader(p, sh); 377 glDeleteShader(sh); 378 glShaderSource(sh, 1, &src_fs, NULL); 379 if (!CompileShader(sh)) 380 { 381 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage; 382 if (result) 383 *result = false; 384 return p; 385 } 386 } 387 if (!LinkProgram(p)) 388 { 389 if (src_vs) 390 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage; 391 if (src_tcs) 392 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage; 393 if (src_tes) 394 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage; 395 if (src_gs) 396 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage; 397 if (src_fs) 398 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage; 399 if (result) 400 *result = false; 401 return p; 402 } 403 404 return p; 405 } 406 407 GLuint BuildShaderProgram(GLenum type, const char* src) 408 { 409 const GLuint p = glCreateShaderProgramv(type, 1, &src); 410 411 GLint status; 412 glGetProgramiv(p, GL_LINK_STATUS, &status); 413 if (status == GL_FALSE) 414 { 415 GLchar log[1024]; 416 glGetProgramInfoLog(p, sizeof(log), NULL, log); 417 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n" 418 << log << "\n" 419 << src << tcu::TestLog::EndMessage; 420 } 421 422 return p; 423 } 424 425 void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo) 426 { 427 assert(vao && vbo); 428 429 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red)) 430 const float v[] = { 431 -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 432 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 433 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 434 }; 435 glGenBuffers(1, vbo); 436 glBindBuffer(GL_ARRAY_BUFFER, *vbo); 437 glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW); 438 glBindBuffer(GL_ARRAY_BUFFER, 0); 439 440 if (ebo) 441 { 442 std::vector<GLushort> index_data(4); 443 for (int i = 0; i < 4; ++i) 444 { 445 index_data[i] = static_cast<GLushort>(i); 446 } 447 glGenBuffers(1, ebo); 448 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo); 449 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW); 450 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 451 } 452 453 glGenVertexArrays(1, vao); 454 glBindVertexArray(*vao); 455 glBindBuffer(GL_ARRAY_BUFFER, *vbo); 456 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0); 457 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2)); 458 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5)); 459 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8)); 460 glBindBuffer(GL_ARRAY_BUFFER, 0); 461 glEnableVertexAttribArray(0); 462 glEnableVertexAttribArray(1); 463 glEnableVertexAttribArray(2); 464 glEnableVertexAttribArray(3); 465 if (ebo) 466 { 467 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo); 468 } 469 glBindVertexArray(0); 470 } 471 472 std::string FormatEnumToString(GLenum e) 473 { 474 switch (e) 475 { 476 case GL_RGBA32F: 477 return "rgba32f"; 478 case GL_RGBA16F: 479 return "rgba16f"; 480 case GL_RG32F: 481 return "rg32f"; 482 case GL_RG16F: 483 return "rg16f"; 484 case GL_R11F_G11F_B10F: 485 return "r11f_g11f_b10f"; 486 case GL_R32F: 487 return "r32f"; 488 case GL_R16F: 489 return "r16f"; 490 491 case GL_RGBA32UI: 492 return "rgba32ui"; 493 case GL_RGBA16UI: 494 return "rgba16ui"; 495 case GL_RGB10_A2UI: 496 return "rgb10_a2ui"; 497 case GL_RGBA8UI: 498 return "rgba8ui"; 499 case GL_RG32UI: 500 return "rg32ui"; 501 case GL_RG16UI: 502 return "rg16ui"; 503 case GL_RG8UI: 504 return "rg8ui"; 505 case GL_R32UI: 506 return "r32ui"; 507 case GL_R16UI: 508 return "r16ui"; 509 case GL_R8UI: 510 return "r8ui"; 511 512 case GL_RGBA32I: 513 return "rgba32i"; 514 case GL_RGBA16I: 515 return "rgba16i"; 516 case GL_RGBA8I: 517 return "rgba8i"; 518 case GL_RG32I: 519 return "rg32i"; 520 case GL_RG16I: 521 return "rg16i"; 522 case GL_RG8I: 523 return "rg8i"; 524 case GL_R32I: 525 return "r32i"; 526 case GL_R16I: 527 return "r16i"; 528 case GL_R8I: 529 return "r8i"; 530 531 case GL_RGBA16: 532 return "rgba16"; 533 case GL_RGB10_A2: 534 return "rgb10_a2"; 535 case GL_RGBA8: 536 return "rgba8"; 537 case GL_RG16: 538 return "rg16"; 539 case GL_RG8: 540 return "rg8"; 541 case GL_R16: 542 return "r16"; 543 case GL_R8: 544 return "r8"; 545 546 case GL_RGBA16_SNORM: 547 return "rgba16_snorm"; 548 case GL_RGBA8_SNORM: 549 return "rgba8_snorm"; 550 case GL_RG16_SNORM: 551 return "rg16_snorm"; 552 case GL_RG8_SNORM: 553 return "rg8_snorm"; 554 case GL_R16_SNORM: 555 return "r16_snorm"; 556 case GL_R8_SNORM: 557 return "r8_snorm"; 558 } 559 560 assert(0); 561 return ""; 562 } 563 564 const char* StageName(int stage) 565 { 566 switch (stage) 567 { 568 case 0: 569 return "Vertex Shader"; 570 case 1: 571 return "Tessellation Control Shader"; 572 case 2: 573 return "Tessellation Evaluation Shader"; 574 case 3: 575 return "Geometry Shader"; 576 case 4: 577 return "Compute Shader"; 578 } 579 assert(0); 580 return NULL; 581 } 582 583 template <typename T> 584 GLenum Format(); 585 586 template <typename T> 587 GLenum Type(); 588 589 template <typename T> 590 std::string TypePrefix(); 591 592 template <typename T> 593 GLenum ImageType(GLenum target); 594 595 void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color) 596 { 597 glClearBufferfv(buffer, drawbuffer, &color[0]); 598 } 599 600 void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color) 601 { 602 glClearBufferiv(buffer, drawbuffer, &color[0]); 603 } 604 605 void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color) 606 { 607 glClearBufferuiv(buffer, drawbuffer, &color[0]); 608 } 609 610 bool CheckUniform(GLuint program, const std::string& name, const std::map<std::string, GLuint>& name_index_map, 611 GLint size, GLenum type) 612 { 613 std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name); 614 assert(iter != name_index_map.end()); 615 616 GLchar name_gl[32]; 617 GLsizei length_gl; 618 GLint size_gl; 619 GLenum type_gl; 620 621 glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl); 622 623 if (std::string(name_gl) != name) 624 { 625 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl 626 << " should be " << name << tcu::TestLog::EndMessage; 627 return false; 628 } 629 if (length_gl != static_cast<GLsizei>(name.length())) 630 { 631 m_context.getTestContext().getLog() 632 << tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl 633 << ")" << tcu::TestLog::EndMessage; 634 return false; 635 } 636 if (size_gl != size) 637 { 638 m_context.getTestContext().getLog() 639 << tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl 640 << ")" << tcu::TestLog::EndMessage; 641 return false; 642 } 643 if (type_gl != type) 644 { 645 m_context.getTestContext().getLog() 646 << tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl 647 << ")" << tcu::TestLog::EndMessage; 648 return false; 649 } 650 651 return true; 652 } 653 654 bool CheckMax(GLenum pname, GLint min_value) 655 { 656 GLboolean b; 657 GLint i; 658 GLfloat f; 659 GLdouble d; 660 GLint64 i64; 661 662 glGetIntegerv(pname, &i); 663 if (i < min_value) 664 return false; 665 666 glGetBooleanv(pname, &b); 667 if (b != (i ? GL_TRUE : GL_FALSE)) 668 return false; 669 670 glGetFloatv(pname, &f); 671 if (static_cast<GLint>(f) < min_value) 672 return false; 673 674 glGetDoublev(pname, &d); 675 if (static_cast<GLint>(d) < min_value) 676 return false; 677 678 glGetInteger64v(pname, &i64); 679 if (static_cast<GLint>(i64) < min_value) 680 return false; 681 682 return true; 683 } 684 685 bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, 686 GLenum format) 687 { 688 GLint i; 689 GLboolean b; 690 691 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i); 692 if (static_cast<GLuint>(i) != texture) 693 { 694 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i 695 << " should be " << texture << tcu::TestLog::EndMessage; 696 return false; 697 } 698 glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b); 699 if (b != (i ? GL_TRUE : GL_FALSE)) 700 { 701 m_context.getTestContext().getLog() 702 << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be " 703 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage; 704 return false; 705 } 706 707 glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i); 708 if (i != level) 709 { 710 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i 711 << " should be " << level << tcu::TestLog::EndMessage; 712 return false; 713 } 714 glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b); 715 if (b != (i ? GL_TRUE : GL_FALSE)) 716 { 717 m_context.getTestContext().getLog() 718 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be " 719 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage; 720 return false; 721 } 722 723 glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i); 724 if (i != layered) 725 { 726 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i 727 << " should be " << layered << tcu::TestLog::EndMessage; 728 return false; 729 } 730 glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b); 731 if (b != (i ? GL_TRUE : GL_FALSE)) 732 { 733 m_context.getTestContext().getLog() 734 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be " 735 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage; 736 return false; 737 } 738 739 glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i); 740 if (i != layer) 741 { 742 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i 743 << " should be " << layer << tcu::TestLog::EndMessage; 744 return false; 745 } 746 glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b); 747 if (b != (i ? GL_TRUE : GL_FALSE)) 748 { 749 m_context.getTestContext().getLog() 750 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be " 751 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage; 752 return false; 753 } 754 755 glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i); 756 if (static_cast<GLenum>(i) != access) 757 { 758 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i 759 << " should be " << access << tcu::TestLog::EndMessage; 760 return false; 761 } 762 glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b); 763 if (b != (i ? GL_TRUE : GL_FALSE)) 764 { 765 m_context.getTestContext().getLog() 766 << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be " 767 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage; 768 return false; 769 } 770 771 glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i); 772 if (static_cast<GLenum>(i) != format) 773 { 774 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i 775 << " should be " << format << tcu::TestLog::EndMessage; 776 return false; 777 } 778 glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b); 779 if (b != (i ? GL_TRUE : GL_FALSE)) 780 { 781 m_context.getTestContext().getLog() 782 << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be " 783 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage; 784 return false; 785 } 786 787 return true; 788 } 789 const char* EnumToString(GLenum e) 790 { 791 switch (e) 792 { 793 case GL_TEXTURE_1D: 794 return "GL_TEXTURE_1D"; 795 case GL_TEXTURE_2D: 796 return "GL_TEXTURE_2D"; 797 case GL_TEXTURE_3D: 798 return "GL_TEXTURE_3D"; 799 case GL_TEXTURE_RECTANGLE: 800 return "GL_TEXTURE_RECTANGLE"; 801 case GL_TEXTURE_CUBE_MAP: 802 return "GL_TEXTURE_CUBE_MAP"; 803 case GL_TEXTURE_1D_ARRAY: 804 return "GL_TEXTURE_1D_ARRAY"; 805 case GL_TEXTURE_2D_ARRAY: 806 return "GL_TEXTURE_2D_ARRAY"; 807 case GL_TEXTURE_CUBE_MAP_ARRAY: 808 return "GL_TEXTURE_CUBE_MAP_ARRAY"; 809 810 default: 811 assert(0); 812 break; 813 } 814 return NULL; 815 } 816}; 817 818template <> 819GLenum ShaderImageLoadStoreBase::Format<vec4>() 820{ 821 return GL_RGBA; 822} 823 824template <> 825GLenum ShaderImageLoadStoreBase::Format<ivec4>() 826{ 827 return GL_RGBA_INTEGER; 828} 829 830template <> 831GLenum ShaderImageLoadStoreBase::Format<uvec4>() 832{ 833 return GL_RGBA_INTEGER; 834} 835 836template <> 837GLenum ShaderImageLoadStoreBase::Format<GLint>() 838{ 839 return GL_RED_INTEGER; 840} 841 842template <> 843GLenum ShaderImageLoadStoreBase::Format<GLuint>() 844{ 845 return GL_RED_INTEGER; 846} 847 848template <> 849GLenum ShaderImageLoadStoreBase::Type<vec4>() 850{ 851 return GL_FLOAT; 852} 853 854template <> 855GLenum ShaderImageLoadStoreBase::Type<ivec4>() 856{ 857 return GL_INT; 858} 859 860template <> 861GLenum ShaderImageLoadStoreBase::Type<uvec4>() 862{ 863 return GL_UNSIGNED_INT; 864} 865 866template <> 867GLenum ShaderImageLoadStoreBase::Type<GLint>() 868{ 869 return GL_INT; 870} 871 872template <> 873GLenum ShaderImageLoadStoreBase::Type<GLuint>() 874{ 875 return GL_UNSIGNED_INT; 876} 877 878template <> 879std::string ShaderImageLoadStoreBase::TypePrefix<vec4>() 880{ 881 return ""; 882} 883 884template <> 885std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>() 886{ 887 return "i"; 888} 889 890template <> 891std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>() 892{ 893 return "u"; 894} 895 896template <> 897std::string ShaderImageLoadStoreBase::TypePrefix<GLint>() 898{ 899 return "i"; 900} 901 902template <> 903std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>() 904{ 905 return "u"; 906} 907 908template <> 909GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target) 910{ 911 switch (target) 912 { 913 case GL_TEXTURE_1D: 914 return GL_IMAGE_1D; 915 case GL_TEXTURE_2D: 916 return GL_IMAGE_2D; 917 case GL_TEXTURE_3D: 918 return GL_IMAGE_3D; 919 case GL_TEXTURE_RECTANGLE: 920 return GL_IMAGE_2D_RECT; 921 case GL_TEXTURE_CUBE_MAP: 922 return GL_IMAGE_CUBE; 923 case GL_TEXTURE_BUFFER: 924 return GL_IMAGE_BUFFER; 925 case GL_TEXTURE_1D_ARRAY: 926 return GL_IMAGE_1D_ARRAY; 927 case GL_TEXTURE_2D_ARRAY: 928 return GL_IMAGE_2D_ARRAY; 929 case GL_TEXTURE_CUBE_MAP_ARRAY: 930 return GL_IMAGE_CUBE_MAP_ARRAY; 931 case GL_TEXTURE_2D_MULTISAMPLE: 932 return GL_IMAGE_2D_MULTISAMPLE; 933 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 934 return GL_IMAGE_2D_MULTISAMPLE_ARRAY; 935 } 936 assert(0); 937 return 0; 938} 939 940template <> 941GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target) 942{ 943 switch (target) 944 { 945 case GL_TEXTURE_1D: 946 return GL_INT_IMAGE_1D; 947 case GL_TEXTURE_2D: 948 return GL_INT_IMAGE_2D; 949 case GL_TEXTURE_3D: 950 return GL_INT_IMAGE_3D; 951 case GL_TEXTURE_RECTANGLE: 952 return GL_INT_IMAGE_2D_RECT; 953 case GL_TEXTURE_CUBE_MAP: 954 return GL_INT_IMAGE_CUBE; 955 case GL_TEXTURE_BUFFER: 956 return GL_INT_IMAGE_BUFFER; 957 case GL_TEXTURE_1D_ARRAY: 958 return GL_INT_IMAGE_1D_ARRAY; 959 case GL_TEXTURE_2D_ARRAY: 960 return GL_INT_IMAGE_2D_ARRAY; 961 case GL_TEXTURE_CUBE_MAP_ARRAY: 962 return GL_INT_IMAGE_CUBE_MAP_ARRAY; 963 case GL_TEXTURE_2D_MULTISAMPLE: 964 return GL_INT_IMAGE_2D_MULTISAMPLE; 965 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 966 return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY; 967 } 968 assert(0); 969 return 0; 970} 971 972template <> 973GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target) 974{ 975 switch (target) 976 { 977 case GL_TEXTURE_1D: 978 return GL_UNSIGNED_INT_IMAGE_1D; 979 case GL_TEXTURE_2D: 980 return GL_UNSIGNED_INT_IMAGE_2D; 981 case GL_TEXTURE_3D: 982 return GL_UNSIGNED_INT_IMAGE_3D; 983 case GL_TEXTURE_RECTANGLE: 984 return GL_UNSIGNED_INT_IMAGE_2D_RECT; 985 case GL_TEXTURE_CUBE_MAP: 986 return GL_UNSIGNED_INT_IMAGE_CUBE; 987 case GL_TEXTURE_BUFFER: 988 return GL_UNSIGNED_INT_IMAGE_BUFFER; 989 case GL_TEXTURE_1D_ARRAY: 990 return GL_UNSIGNED_INT_IMAGE_1D_ARRAY; 991 case GL_TEXTURE_2D_ARRAY: 992 return GL_UNSIGNED_INT_IMAGE_2D_ARRAY; 993 case GL_TEXTURE_CUBE_MAP_ARRAY: 994 return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY; 995 case GL_TEXTURE_2D_MULTISAMPLE: 996 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE; 997 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 998 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY; 999 } 1000 assert(0); 1001 return 0; 1002} 1003 1004//----------------------------------------------------------------------------- 1005// 1.1.1 BasicAPIGet 1006//----------------------------------------------------------------------------- 1007class BasicAPIGet : public ShaderImageLoadStoreBase 1008{ 1009 virtual long Run() 1010 { 1011 if (!CheckMax(GL_MAX_IMAGE_UNITS, 8)) 1012 { 1013 m_context.getTestContext().getLog() 1014 << tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage; 1015 return ERROR; 1016 } 1017 if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8)) 1018 { 1019 m_context.getTestContext().getLog() 1020 << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid." 1021 << tcu::TestLog::EndMessage; 1022 return ERROR; 1023 } 1024 if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0)) 1025 { 1026 m_context.getTestContext().getLog() 1027 << tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage; 1028 return ERROR; 1029 } 1030 if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0)) 1031 { 1032 m_context.getTestContext().getLog() 1033 << tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid." 1034 << tcu::TestLog::EndMessage; 1035 return ERROR; 1036 } 1037 if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0)) 1038 { 1039 m_context.getTestContext().getLog() 1040 << tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid." 1041 << tcu::TestLog::EndMessage; 1042 return ERROR; 1043 } 1044 if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0)) 1045 { 1046 m_context.getTestContext().getLog() 1047 << tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid." 1048 << tcu::TestLog::EndMessage; 1049 return ERROR; 1050 } 1051 if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0)) 1052 { 1053 m_context.getTestContext().getLog() 1054 << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid." 1055 << tcu::TestLog::EndMessage; 1056 return ERROR; 1057 } 1058 if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8)) 1059 { 1060 m_context.getTestContext().getLog() 1061 << tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid." 1062 << tcu::TestLog::EndMessage; 1063 return ERROR; 1064 } 1065 if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8)) 1066 { 1067 m_context.getTestContext().getLog() 1068 << tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid." 1069 << tcu::TestLog::EndMessage; 1070 return ERROR; 1071 } 1072 return NO_ERROR; 1073 } 1074}; 1075//----------------------------------------------------------------------------- 1076// 1.1.2 BasicAPIBind 1077//----------------------------------------------------------------------------- 1078class BasicAPIBind : public ShaderImageLoadStoreBase 1079{ 1080 GLuint m_texture; 1081 1082 virtual long Setup() 1083 { 1084 m_texture = 0; 1085 return NO_ERROR; 1086 } 1087 1088 virtual long Run() 1089 { 1090 for (GLuint index = 0; index < 8; ++index) 1091 { 1092 if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8)) 1093 { 1094 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index 1095 << " has invalid default state." << tcu::TestLog::EndMessage; 1096 return ERROR; 1097 } 1098 } 1099 1100 glGenTextures(1, &m_texture); 1101 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 1102 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL); 1103 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL); 1104 glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL); 1105 glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL); 1106 glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL); 1107 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 1108 1109 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); 1110 if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F)) 1111 return ERROR; 1112 1113 glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8); 1114 if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8)) 1115 return ERROR; 1116 1117 glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16); 1118 if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16)) 1119 return ERROR; 1120 1121 glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I); 1122 if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I)) 1123 return ERROR; 1124 1125 glDeleteTextures(1, &m_texture); 1126 m_texture = 0; 1127 1128 for (GLuint index = 0; index < 8; ++index) 1129 { 1130 GLint name; 1131 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name); 1132 if (name != 0) 1133 { 1134 m_context.getTestContext().getLog() 1135 << tcu::TestLog::Message << "Binding point " << index 1136 << " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage; 1137 return ERROR; 1138 } 1139 } 1140 1141 return NO_ERROR; 1142 } 1143 1144 virtual long Cleanup() 1145 { 1146 glDeleteTextures(1, &m_texture); 1147 return NO_ERROR; 1148 } 1149}; 1150//----------------------------------------------------------------------------- 1151// 1.1.3 BasicAPIBarrier 1152//----------------------------------------------------------------------------- 1153class BasicAPIBarrier : public ShaderImageLoadStoreBase 1154{ 1155 virtual long Run() 1156 { 1157 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT); 1158 glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT); 1159 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT); 1160 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); 1161 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 1162 glMemoryBarrier(GL_COMMAND_BARRIER_BIT); 1163 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); 1164 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 1165 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 1166 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); 1167 glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT); 1168 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT); 1169 1170 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT | 1171 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT | 1172 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT | 1173 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT); 1174 1175 glMemoryBarrier(GL_ALL_BARRIER_BITS); 1176 1177 return NO_ERROR; 1178 } 1179}; 1180//----------------------------------------------------------------------------- 1181// 1.1.4 BasicAPITexParam 1182//----------------------------------------------------------------------------- 1183class BasicAPITexParam : public ShaderImageLoadStoreBase 1184{ 1185 GLuint m_texture; 1186 1187 virtual long Setup() 1188 { 1189 m_texture = 0; 1190 return NO_ERROR; 1191 } 1192 1193 virtual long Run() 1194 { 1195 glGenTextures(1, &m_texture); 1196 glBindTexture(GL_TEXTURE_2D, m_texture); 1197 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL); 1198 1199 GLint i; 1200 GLfloat f; 1201 GLuint ui; 1202 1203 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i); 1204 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE) 1205 { 1206 m_context.getTestContext().getLog() 1207 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to " 1208 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL." 1209 << tcu::TestLog::EndMessage; 1210 return ERROR; 1211 } 1212 glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f); 1213 if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE) 1214 { 1215 m_context.getTestContext().getLog() 1216 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to " 1217 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL." 1218 << tcu::TestLog::EndMessage; 1219 return ERROR; 1220 } 1221 glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i); 1222 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE) 1223 { 1224 m_context.getTestContext().getLog() 1225 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to " 1226 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL." 1227 << tcu::TestLog::EndMessage; 1228 return ERROR; 1229 } 1230 glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui); 1231 if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE) 1232 { 1233 m_context.getTestContext().getLog() 1234 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to " 1235 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL." 1236 << tcu::TestLog::EndMessage; 1237 return ERROR; 1238 } 1239 1240 return NO_ERROR; 1241 } 1242 1243 virtual long Cleanup() 1244 { 1245 glDeleteTextures(1, &m_texture); 1246 return NO_ERROR; 1247 } 1248}; 1249//----------------------------------------------------------------------------- 1250// 1.2.1 BasicAllFormatsStore 1251//----------------------------------------------------------------------------- 1252class BasicAllFormatsStore : public ShaderImageLoadStoreBase 1253{ 1254 GLuint m_vao; 1255 GLuint m_vbo; 1256 1257 virtual long Setup() 1258 { 1259 m_vao = 0; 1260 m_vbo = 0; 1261 return NO_ERROR; 1262 } 1263 1264 virtual long Run() 1265 { 1266 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 1267 1268 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1269 return ERROR; 1270 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1271 return ERROR; 1272 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1273 return ERROR; 1274 1275 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1276 return ERROR; 1277 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1278 return ERROR; 1279 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1280 return ERROR; 1281 1282 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1283 return ERROR; 1284 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1285 return ERROR; 1286 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1287 return ERROR; 1288 1289 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f))) 1290 return ERROR; 1291 1292 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1293 return ERROR; 1294 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1295 return ERROR; 1296 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1297 return ERROR; 1298 1299 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1300 return ERROR; 1301 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1302 return ERROR; 1303 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1304 return ERROR; 1305 1306 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1307 return ERROR; 1308 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1309 return ERROR; 1310 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1311 return ERROR; 1312 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1313 return ERROR; 1314 1315 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1316 return ERROR; 1317 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1318 return ERROR; 1319 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1320 return ERROR; 1321 1322 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1323 return ERROR; 1324 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1325 return ERROR; 1326 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1327 return ERROR; 1328 1329 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f))) 1330 return ERROR; 1331 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f))) 1332 return ERROR; 1333 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1334 return ERROR; 1335 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1336 return ERROR; 1337 1338 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 1339 return ERROR; 1340 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1341 return ERROR; 1342 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1343 return ERROR; 1344 1345 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1346 return ERROR; 1347 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1348 return ERROR; 1349 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1350 return ERROR; 1351 1352 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1353 return ERROR; 1354 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1355 return ERROR; 1356 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1357 return ERROR; 1358 1359 return NO_ERROR; 1360 } 1361 1362 template <typename T> 1363 bool Write(GLenum internalformat, const T& write_value, const T& expected_value) 1364 { 1365 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 1366 " gl_Position = i_position;" NL "}"; 1367 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str()); 1368 const int kSize = 16; 1369 std::vector<T> data(kSize * kSize); 1370 GLuint texture; 1371 glGenTextures(1, &texture); 1372 1373 for (GLuint unit = 0; unit < 8; ++unit) 1374 { 1375 glBindTexture(GL_TEXTURE_2D, texture); 1376 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1377 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1378 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 1379 glBindTexture(GL_TEXTURE_2D, 0); 1380 1381 glViewport(0, 0, kSize, kSize); 1382 glUseProgram(program); 1383 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 1384 glBindVertexArray(m_vao); 1385 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1386 1387 glBindTexture(GL_TEXTURE_2D, texture); 1388 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 1389 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]); 1390 1391 for (int i = 0; i < kSize * kSize; ++i) 1392 { 1393 if (!Equal(data[i], expected_value, internalformat)) 1394 { 1395 glDeleteTextures(1, &texture); 1396 glUseProgram(0); 1397 glDeleteProgram(program); 1398 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i]) 1399 << ". Value should be: " << ToString(expected_value) 1400 << ". Format is: " << FormatEnumToString(internalformat) 1401 << ". Unit is: " << unit << tcu::TestLog::EndMessage; 1402 return false; 1403 } 1404 } 1405 1406 if (unit < 7) 1407 { 1408 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1)); 1409 } 1410 } 1411 1412 glDeleteTextures(1, &texture); 1413 glUseProgram(0); 1414 glDeleteProgram(program); 1415 1416 return true; 1417 } 1418 1419 virtual long Cleanup() 1420 { 1421 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 1422 glDeleteVertexArrays(1, &m_vao); 1423 glDeleteBuffers(1, &m_vbo); 1424 return NO_ERROR; 1425 } 1426 1427 template <typename T> 1428 std::string GenFS(GLenum internalformat, const T& value) 1429 { 1430 std::ostringstream os; 1431 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 1432 << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 1433 " imageStore(g_image, coord, " 1434 << TypePrefix<T>() << "vec4" << value << ");" NL " discard;" NL "}"; 1435 return os.str(); 1436 } 1437}; 1438//----------------------------------------------------------------------------- 1439// 1.2.2 BasicAllFormatsLoad 1440//----------------------------------------------------------------------------- 1441class BasicAllFormatsLoad : public ShaderImageLoadStoreBase 1442{ 1443 GLuint m_vao; 1444 GLuint m_vbo; 1445 1446 virtual long Setup() 1447 { 1448 m_vao = 0; 1449 m_vbo = 0; 1450 return NO_ERROR; 1451 } 1452 1453 virtual long Run() 1454 { 1455 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 1456 1457 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1458 return ERROR; 1459 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1460 return ERROR; 1461 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1462 return ERROR; 1463 1464 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1465 return ERROR; 1466 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1467 return ERROR; 1468 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1469 return ERROR; 1470 1471 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1472 return ERROR; 1473 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1474 return ERROR; 1475 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1476 return ERROR; 1477 1478 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f))) 1479 return ERROR; 1480 1481 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1482 return ERROR; 1483 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1484 return ERROR; 1485 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1486 return ERROR; 1487 1488 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1489 return ERROR; 1490 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1491 return ERROR; 1492 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1493 return ERROR; 1494 1495 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1496 return ERROR; 1497 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1498 return ERROR; 1499 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1500 return ERROR; 1501 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1502 return ERROR; 1503 1504 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1505 return ERROR; 1506 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1507 return ERROR; 1508 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1509 return ERROR; 1510 1511 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1512 return ERROR; 1513 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1514 return ERROR; 1515 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1516 return ERROR; 1517 1518 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f))) 1519 return ERROR; 1520 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f))) 1521 return ERROR; 1522 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1523 return ERROR; 1524 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1525 return ERROR; 1526 1527 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 1528 return ERROR; 1529 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1530 return ERROR; 1531 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1532 return ERROR; 1533 1534 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1535 return ERROR; 1536 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1537 return ERROR; 1538 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1539 return ERROR; 1540 1541 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1542 return ERROR; 1543 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1544 return ERROR; 1545 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1546 return ERROR; 1547 1548 return NO_ERROR; 1549 } 1550 1551 template <typename T> 1552 bool Read(GLenum internalformat, const T& value, const T& expected_value) 1553 { 1554 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 1555 " gl_Position = i_position;" NL "}"; 1556 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str()); 1557 const int kSize = 16; 1558 std::vector<T> data(kSize * kSize, value); 1559 GLuint texture; 1560 glGenTextures(1, &texture); 1561 1562 for (GLuint unit = 0; unit < 8; ++unit) 1563 { 1564 glBindTexture(GL_TEXTURE_2D, texture); 1565 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1566 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1567 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 1568 glBindTexture(GL_TEXTURE_2D, 0); 1569 1570 glViewport(0, 0, kSize, kSize); 1571 glClear(GL_COLOR_BUFFER_BIT); 1572 glUseProgram(program); 1573 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 1574 glBindVertexArray(m_vao); 1575 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1576 1577 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 1578 { 1579 glDeleteTextures(1, &texture); 1580 glUseProgram(0); 1581 glDeleteProgram(program); 1582 m_context.getTestContext().getLog() 1583 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat) 1584 << ". Unit is: " << unit << tcu::TestLog::EndMessage; 1585 return false; 1586 } 1587 1588 if (unit < 7) 1589 { 1590 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1)); 1591 } 1592 } 1593 1594 glDeleteTextures(1, &texture); 1595 glUseProgram(0); 1596 glDeleteProgram(program); 1597 1598 return true; 1599 } 1600 1601 virtual long Cleanup() 1602 { 1603 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 1604 glDeleteVertexArrays(1, &m_vao); 1605 glDeleteBuffers(1, &m_vbo); 1606 return NO_ERROR; 1607 } 1608 1609 template <typename T> 1610 std::string GenFS(GLenum internalformat, const T& expected_value) 1611 { 1612 std::ostringstream os; 1613 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 1614 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 1615 << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " " 1616 << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL " if (v != " << TypePrefix<T>() << "vec4" 1617 << expected_value 1618 << ") o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " else o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}"; 1619 return os.str(); 1620 } 1621}; 1622//----------------------------------------------------------------------------- 1623// 1.2.3 BasicAllFormatsStoreGeometryStages 1624//----------------------------------------------------------------------------- 1625class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase 1626{ 1627 GLuint m_vao; 1628 1629 virtual long Setup() 1630 { 1631 glGenVertexArrays(1, &m_vao); 1632 return NO_ERROR; 1633 } 1634 1635 virtual long Run() 1636 { 1637 if (!SupportedInGeomStages(1)) 1638 return NOT_SUPPORTED; 1639 glEnable(GL_RASTERIZER_DISCARD); 1640 1641 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1642 return ERROR; 1643 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1644 return ERROR; 1645 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1646 return ERROR; 1647 1648 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1649 return ERROR; 1650 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1651 return ERROR; 1652 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1653 return ERROR; 1654 1655 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1656 return ERROR; 1657 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1658 return ERROR; 1659 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1660 return ERROR; 1661 1662 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f))) 1663 return ERROR; 1664 1665 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1666 return ERROR; 1667 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1668 return ERROR; 1669 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1670 return ERROR; 1671 1672 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1673 return ERROR; 1674 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1675 return ERROR; 1676 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1677 return ERROR; 1678 1679 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1680 return ERROR; 1681 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1682 return ERROR; 1683 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1684 return ERROR; 1685 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1686 return ERROR; 1687 1688 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1689 return ERROR; 1690 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1691 return ERROR; 1692 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1693 return ERROR; 1694 1695 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1696 return ERROR; 1697 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1698 return ERROR; 1699 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1700 return ERROR; 1701 1702 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f))) 1703 return ERROR; 1704 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f))) 1705 return ERROR; 1706 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1707 return ERROR; 1708 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1709 return ERROR; 1710 1711 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 1712 return ERROR; 1713 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1714 return ERROR; 1715 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1716 return ERROR; 1717 1718 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1719 return ERROR; 1720 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1721 return ERROR; 1722 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1723 return ERROR; 1724 1725 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1726 return ERROR; 1727 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1728 return ERROR; 1729 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1730 return ERROR; 1731 1732 return NO_ERROR; 1733 } 1734 1735 template <typename T> 1736 bool Write(GLenum internalformat, const T& write_value, const T& expected_value) 1737 { 1738 const GLuint program = 1739 BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(), 1740 GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL); 1741 const int kSize = 1; 1742 std::vector<T> data(kSize * kSize); 1743 GLuint texture[4]; 1744 glGenTextures(4, texture); 1745 1746 for (int i = 0; i < 4; ++i) 1747 { 1748 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]); 1749 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1750 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1751 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]); 1752 } 1753 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 1754 1755 glUseProgram(program); 1756 glUniform1i(glGetUniformLocation(program, "g_image0"), 0); 1757 glUniform1i(glGetUniformLocation(program, "g_image1"), 1); 1758 glUniform1i(glGetUniformLocation(program, "g_image2"), 2); 1759 glUniform1i(glGetUniformLocation(program, "g_image3"), 3); 1760 for (GLuint i = 0; i < 4; ++i) 1761 { 1762 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 1763 } 1764 glBindVertexArray(m_vao); 1765 glPatchParameteri(GL_PATCH_VERTICES, 1); 1766 glDrawArrays(GL_PATCHES, 0, 1); 1767 glPatchParameteri(GL_PATCH_VERTICES, 3); 1768 1769 for (int i = 0; i < 4; ++i) 1770 { 1771 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]); 1772 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 1773 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]); 1774 1775 if (!Equal(data[0], expected_value, internalformat)) 1776 { 1777 glDeleteTextures(4, texture); 1778 glUseProgram(0); 1779 glDeleteProgram(program); 1780 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0]) 1781 << ". Value should be: " << ToString(expected_value) 1782 << ". Format is: " << FormatEnumToString(internalformat) 1783 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage; 1784 return false; 1785 } 1786 } 1787 glDeleteTextures(4, texture); 1788 glUseProgram(0); 1789 glDeleteProgram(program); 1790 return true; 1791 } 1792 1793 virtual long Cleanup() 1794 { 1795 glDisable(GL_RASTERIZER_DISCARD); 1796 glDeleteVertexArrays(1, &m_vao); 1797 return NO_ERROR; 1798 } 1799 1800 template <typename T> 1801 std::string GenVS(GLenum internalformat, const T& value) 1802 { 1803 std::ostringstream os; 1804 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 1805 << TypePrefix<T>() << "image2DArray g_image0;" NL "void main() {" NL 1806 " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " imageStore(g_image0, coord, " 1807 << TypePrefix<T>() << "vec4" << value << ");" NL "}"; 1808 return os.str(); 1809 } 1810 1811 template <typename T> 1812 std::string GenTCS(GLenum internalformat, const T& value) 1813 { 1814 std::ostringstream os; 1815 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat) 1816 << ") writeonly uniform " << TypePrefix<T>() 1817 << "image2DArray g_image1;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL 1818 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL 1819 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL 1820 " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " imageStore(g_image1, coord, " 1821 << TypePrefix<T>() << "vec4" << value << ");" NL "}"; 1822 return os.str(); 1823 } 1824 1825 template <typename T> 1826 std::string GenTES(GLenum internalformat, const T& value) 1827 { 1828 std::ostringstream os; 1829 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout(" 1830 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 1831 << "image2DArray g_image2;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL 1832 " imageStore(g_image2, coord, " 1833 << TypePrefix<T>() << "vec4" << value << ");" NL "}"; 1834 return os.str(); 1835 } 1836 1837 template <typename T> 1838 std::string GenGS(GLenum internalformat, const T& value) 1839 { 1840 std::ostringstream os; 1841 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout(" 1842 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 1843 << "image2DArray g_image3;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL 1844 " imageStore(g_image3, coord, " 1845 << TypePrefix<T>() << "vec4" << value << ");" NL "}"; 1846 return os.str(); 1847 } 1848}; 1849//----------------------------------------------------------------------------- 1850// 1.2.4 BasicAllFormatsLoadGeometryStages 1851//----------------------------------------------------------------------------- 1852class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase 1853{ 1854 GLuint m_vao; 1855 1856 virtual long Setup() 1857 { 1858 glGenVertexArrays(1, &m_vao); 1859 return NO_ERROR; 1860 } 1861 1862 virtual long Run() 1863 { 1864 if (!SupportedInGeomStages(2)) 1865 return NOT_SUPPORTED; 1866 glEnable(GL_RASTERIZER_DISCARD); 1867 1868 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1869 return ERROR; 1870 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1871 return ERROR; 1872 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1873 return ERROR; 1874 1875 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1876 return ERROR; 1877 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1878 return ERROR; 1879 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1880 return ERROR; 1881 1882 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1883 return ERROR; 1884 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1885 return ERROR; 1886 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1887 return ERROR; 1888 1889 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f))) 1890 return ERROR; 1891 1892 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1893 return ERROR; 1894 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1895 return ERROR; 1896 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1897 return ERROR; 1898 1899 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1900 return ERROR; 1901 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1902 return ERROR; 1903 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1904 return ERROR; 1905 1906 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1907 return ERROR; 1908 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1909 return ERROR; 1910 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1911 return ERROR; 1912 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1913 return ERROR; 1914 1915 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1916 return ERROR; 1917 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1918 return ERROR; 1919 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1920 return ERROR; 1921 1922 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1923 return ERROR; 1924 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1925 return ERROR; 1926 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1927 return ERROR; 1928 1929 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f))) 1930 return ERROR; 1931 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f))) 1932 return ERROR; 1933 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1934 return ERROR; 1935 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1936 return ERROR; 1937 1938 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 1939 return ERROR; 1940 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1941 return ERROR; 1942 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1943 return ERROR; 1944 1945 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1946 return ERROR; 1947 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1948 return ERROR; 1949 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1950 return ERROR; 1951 1952 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1953 return ERROR; 1954 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1955 return ERROR; 1956 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1957 return ERROR; 1958 1959 return NO_ERROR; 1960 } 1961 1962 template <typename T> 1963 bool Read(GLenum internalformat, const T& value, const T& expected_value) 1964 { 1965 const GLuint program = BuildProgram( 1966 GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(), 1967 GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL); 1968 const int kSize = 1; 1969 std::vector<T> data(kSize * kSize, value); 1970 GLuint texture[8]; 1971 glGenTextures(8, texture); 1972 1973 for (int i = 0; i < 4; ++i) 1974 { 1975 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]); 1976 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1977 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1978 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]); 1979 } 1980 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 1981 vec4 zero(0); 1982 for (int i = 4; i < 8; ++i) 1983 { 1984 glBindTexture(GL_TEXTURE_2D, texture[i]); 1985 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1986 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1987 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero); 1988 } 1989 glBindTexture(GL_TEXTURE_2D, 0); 1990 1991 glUseProgram(program); 1992 glUniform1i(glGetUniformLocation(program, "g_image0"), 0); 1993 glUniform1i(glGetUniformLocation(program, "g_image1"), 1); 1994 glUniform1i(glGetUniformLocation(program, "g_image2"), 2); 1995 glUniform1i(glGetUniformLocation(program, "g_image3"), 3); 1996 glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4); 1997 glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5); 1998 glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6); 1999 glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7); 2000 2001 for (GLuint i = 0; i < 4; ++i) 2002 { 2003 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 2004 } 2005 for (GLuint i = 4; i < 8; ++i) 2006 { 2007 glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 2008 } 2009 glBindVertexArray(m_vao); 2010 glPatchParameteri(GL_PATCH_VERTICES, 1); 2011 glDrawArrays(GL_PATCHES, 0, 1); 2012 glPatchParameteri(GL_PATCH_VERTICES, 3); 2013 2014 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 2015 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat(); 2016 vec4 g_color_eps = vec4( 2017 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits), 2018 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits)); 2019 2020 for (int i = 0; i < 4; ++i) 2021 { 2022 glBindTexture(GL_TEXTURE_2D, texture[i + 4]); 2023 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2024 vec4 result; 2025 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]); 2026 if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps)) 2027 { 2028 glDeleteTextures(8, texture); 2029 glUseProgram(0); 2030 glDeleteProgram(program); 2031 m_context.getTestContext().getLog() 2032 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat) 2033 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage; 2034 return false; 2035 } 2036 } 2037 glDeleteTextures(8, texture); 2038 glUseProgram(0); 2039 glDeleteProgram(program); 2040 return true; 2041 } 2042 2043 virtual long Cleanup() 2044 { 2045 glDisable(GL_RASTERIZER_DISCARD); 2046 glDeleteVertexArrays(1, &m_vao); 2047 return NO_ERROR; 2048 } 2049 2050 template <typename T> 2051 std::string GenVS(GLenum internalformat, const T& expected_value) 2052 { 2053 std::ostringstream os; 2054 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 2055 << TypePrefix<T>() 2056 << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL 2057 "void main() {" NL " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " " 2058 << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL " if (v != " << TypePrefix<T>() << "vec4" 2059 << expected_value << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL 2060 " else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}"; 2061 return os.str(); 2062 } 2063 2064 template <typename T> 2065 std::string GenTCS(GLenum internalformat, const T& expected_value) 2066 { 2067 std::ostringstream os; 2068 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat) 2069 << ") readonly uniform " << TypePrefix<T>() 2070 << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL 2071 "void main() {" NL " gl_TessLevelInner[0] = 1;" NL " gl_TessLevelInner[1] = 1;" NL 2072 " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL " gl_TessLevelOuter[2] = 1;" NL 2073 " gl_TessLevelOuter[3] = 1;" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " " 2074 << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL " if (v != " << TypePrefix<T>() << "vec4" 2075 << expected_value << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL 2076 " else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}"; 2077 return os.str(); 2078 } 2079 2080 template <typename T> 2081 std::string GenTES(GLenum internalformat, const T& expected_value) 2082 { 2083 std::ostringstream os; 2084 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout(" 2085 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 2086 << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL 2087 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " " 2088 << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL " if (v != " << TypePrefix<T>() << "vec4" 2089 << expected_value << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL 2090 " else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}"; 2091 return os.str(); 2092 } 2093 2094 template <typename T> 2095 std::string GenGS(GLenum internalformat, const T& expected_value) 2096 { 2097 std::ostringstream os; 2098 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout(" 2099 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 2100 << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL 2101 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL " " 2102 << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL " if (v != " << TypePrefix<T>() << "vec4" 2103 << expected_value << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL 2104 " else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}"; 2105 return os.str(); 2106 } 2107}; 2108//----------------------------------------------------------------------------- 2109// 1.2.5 BasicAllFormatsLoadStoreComputeStage 2110//----------------------------------------------------------------------------- 2111class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase 2112{ 2113 virtual long Run() 2114 { 2115 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) 2116 { 2117 m_context.getTestContext().getLog() 2118 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test" 2119 << tcu::TestLog::EndMessage; 2120 return NOT_SUPPORTED; 2121 } 2122 2123 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 2124 return ERROR; 2125 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 2126 return ERROR; 2127 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 2128 return ERROR; 2129 2130 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 2131 return ERROR; 2132 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 2133 return ERROR; 2134 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 2135 return ERROR; 2136 2137 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2138 return ERROR; 2139 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 2140 return ERROR; 2141 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 2142 return ERROR; 2143 2144 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f))) 2145 return ERROR; 2146 2147 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2148 return ERROR; 2149 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 2150 return ERROR; 2151 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 2152 return ERROR; 2153 2154 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2155 return ERROR; 2156 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 2157 return ERROR; 2158 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 2159 return ERROR; 2160 2161 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 2162 return ERROR; 2163 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 2164 return ERROR; 2165 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 2166 return ERROR; 2167 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 2168 return ERROR; 2169 2170 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 2171 return ERROR; 2172 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 2173 return ERROR; 2174 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 2175 return ERROR; 2176 2177 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 2178 return ERROR; 2179 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 2180 return ERROR; 2181 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 2182 return ERROR; 2183 2184 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f))) 2185 return ERROR; 2186 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f))) 2187 return ERROR; 2188 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 2189 return ERROR; 2190 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 2191 return ERROR; 2192 2193 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 2194 return ERROR; 2195 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 2196 return ERROR; 2197 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 2198 return ERROR; 2199 2200 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 2201 return ERROR; 2202 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 2203 return ERROR; 2204 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 2205 return ERROR; 2206 2207 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 2208 return ERROR; 2209 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 2210 return ERROR; 2211 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 2212 return ERROR; 2213 2214 return NO_ERROR; 2215 } 2216 2217 template <typename T> 2218 bool Read(GLenum internalformat, const T& value, const T& expected_value) 2219 { 2220 GLuint program; 2221 std::string source = GenCS<T>(internalformat); 2222 const char* const src = source.c_str(); 2223 GLuint sh = glCreateShader(GL_COMPUTE_SHADER); 2224 glShaderSource(sh, 1, &src, NULL); 2225 glCompileShader(sh); 2226 program = glCreateProgram(); 2227 glAttachShader(program, sh); 2228 glLinkProgram(program); 2229 glDeleteShader(sh); 2230 2231 const int kSize = 1; 2232 std::vector<T> data(kSize * kSize, value); 2233 GLuint texture[2]; 2234 glGenTextures(2, texture); 2235 2236 glBindTexture(GL_TEXTURE_2D, texture[0]); 2237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2238 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2239 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2240 glBindTexture(GL_TEXTURE_2D, texture[1]); 2241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2243 vec4 zero(0); 2244 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero); 2245 2246 glBindTexture(GL_TEXTURE_2D, 0); 2247 2248 glUseProgram(program); 2249 glUniform1i(glGetUniformLocation(program, "g_image_read"), 0); 2250 glUniform1i(glGetUniformLocation(program, "g_image_write"), 1); 2251 2252 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 2253 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2254 2255 glDispatchCompute(1, 1, 1); 2256 2257 for (int i = 0; i < 2; ++i) 2258 { 2259 glBindTexture(GL_TEXTURE_2D, texture[i]); 2260 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2261 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]); 2262 2263 if (!Equal(data[0], expected_value, internalformat)) 2264 { 2265 glDeleteTextures(4, texture); 2266 glUseProgram(0); 2267 glDeleteProgram(program); 2268 m_context.getTestContext().getLog() 2269 << tcu::TestLog::Message << "Value is: " << ToString(data[0]) 2270 << ". Value should be: " << ToString(expected_value) 2271 << ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage; 2272 return false; 2273 } 2274 } 2275 glDeleteTextures(2, texture); 2276 glUseProgram(0); 2277 glDeleteProgram(program); 2278 return true; 2279 } 2280 2281 template <typename T> 2282 std::string GenCS(GLenum internalformat) 2283 { 2284 std::ostringstream os; 2285 os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL 2286 "layout(" 2287 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 2288 << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 2289 << TypePrefix<T>() << "image2D g_image_write;" NL "void main() {" NL 2290 " ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL " " 2291 << TypePrefix<T>() 2292 << "vec4 v = imageLoad(g_image_read, coord);" NL " imageStore(g_image_write, coord, v);" NL "}"; 2293 return os.str(); 2294 } 2295}; 2296//----------------------------------------------------------------------------- 2297// 1.3.1 BasicAllTargetsStore 2298//----------------------------------------------------------------------------- 2299class BasicAllTargetsStore : public ShaderImageLoadStoreBase 2300{ 2301 GLuint m_vao; 2302 GLuint m_vbo; 2303 2304 virtual long Setup() 2305 { 2306 m_vao = 0; 2307 m_vbo = 0; 2308 return NO_ERROR; 2309 } 2310 2311 virtual long Run() 2312 { 2313 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 2314 2315 if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 2316 return ERROR; 2317 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2318 return ERROR; 2319 if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 2320 return ERROR; 2321 2322 if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 2323 return ERROR; 2324 if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2325 return ERROR; 2326 if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 2327 return ERROR; 2328 2329 if (SupportedSamples(4)) 2330 { 2331 if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 2332 return ERROR; 2333 2334 GLint isamples; 2335 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples); 2336 if (isamples >= 4) 2337 { 2338 if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2339 return ERROR; 2340 if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 2341 return ERROR; 2342 } 2343 } 2344 return NO_ERROR; 2345 } 2346 2347 virtual long Cleanup() 2348 { 2349 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 2350 glDeleteVertexArrays(1, &m_vao); 2351 glDeleteBuffers(1, &m_vbo); 2352 return NO_ERROR; 2353 } 2354 2355 template <typename T> 2356 bool Write(GLenum internalformat, const T& write_value, const T& expected_value) 2357 { 2358 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 2359 " gl_Position = i_position;" NL "}"; 2360 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str()); 2361 GLuint textures[8]; 2362 GLuint buffer; 2363 glGenTextures(8, textures); 2364 glGenBuffers(1, &buffer); 2365 2366 const int kSize = 16; 2367 std::vector<T> data(kSize * kSize * 2); 2368 2369 glBindTexture(GL_TEXTURE_1D, textures[0]); 2370 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2371 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2372 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2373 glBindTexture(GL_TEXTURE_1D, 0); 2374 2375 glBindTexture(GL_TEXTURE_2D, textures[1]); 2376 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2377 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2378 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2379 glBindTexture(GL_TEXTURE_2D, 0); 2380 2381 glBindTexture(GL_TEXTURE_3D, textures[2]); 2382 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2383 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2384 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 2385 glBindTexture(GL_TEXTURE_3D, 0); 2386 2387 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]); 2388 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2389 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2390 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2391 glBindTexture(GL_TEXTURE_RECTANGLE, 0); 2392 2393 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); 2394 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2395 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2396 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 2397 &data[0]); 2398 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 2399 &data[0]); 2400 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 2401 &data[0]); 2402 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 2403 &data[0]); 2404 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 2405 &data[0]); 2406 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 2407 &data[0]); 2408 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 2409 2410 glBindBuffer(GL_TEXTURE_BUFFER, buffer); 2411 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW); 2412 glBindBuffer(GL_TEXTURE_BUFFER, 0); 2413 glBindTexture(GL_TEXTURE_BUFFER, textures[5]); 2414 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer); 2415 glBindTexture(GL_TEXTURE_BUFFER, 0); 2416 2417 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]); 2418 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2419 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2420 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 2421 glBindTexture(GL_TEXTURE_1D_ARRAY, 0); 2422 2423 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); 2424 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2425 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2426 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 2427 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 2428 2429 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 2430 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 2431 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2432 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 2433 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2434 glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 2435 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2436 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2437 2438 glUseProgram(program); 2439 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0); 2440 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1); 2441 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2); 2442 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3); 2443 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4); 2444 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5); 2445 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6); 2446 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7); 2447 2448 glBindVertexArray(m_vao); 2449 glViewport(0, 0, kSize, kSize); 2450 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 2451 2452 bool status = true; 2453 2454 glBindTexture(GL_TEXTURE_1D, textures[0]); 2455 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2456 glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]); 2457 glBindTexture(GL_TEXTURE_1D, 0); 2458 for (int i = 0; i < kSize; ++i) 2459 { 2460 if (!tcu::allEqual(data[i], expected_value)) 2461 { 2462 status = false; 2463 m_context.getTestContext().getLog() 2464 << tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i]) 2465 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2466 break; 2467 } 2468 } 2469 std::fill(data.begin(), data.end(), T(0)); 2470 2471 glBindTexture(GL_TEXTURE_2D, textures[1]); 2472 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2473 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]); 2474 glBindTexture(GL_TEXTURE_2D, 0); 2475 for (int i = 0; i < kSize * kSize; ++i) 2476 { 2477 if (!tcu::allEqual(data[i], expected_value)) 2478 { 2479 status = false; 2480 m_context.getTestContext().getLog() 2481 << tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i]) 2482 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2483 break; 2484 } 2485 } 2486 2487 glBindTexture(GL_TEXTURE_3D, textures[2]); 2488 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2489 glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]); 2490 glBindTexture(GL_TEXTURE_3D, 0); 2491 for (int i = 0; i < kSize * kSize * 2; ++i) 2492 { 2493 if (!tcu::allEqual(data[i], expected_value)) 2494 { 2495 status = false; 2496 m_context.getTestContext().getLog() 2497 << tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i]) 2498 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2499 break; 2500 } 2501 } 2502 2503 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]); 2504 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2505 glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]); 2506 glBindTexture(GL_TEXTURE_RECTANGLE, 0); 2507 for (int i = 0; i < kSize * kSize; ++i) 2508 { 2509 if (!tcu::allEqual(data[i], expected_value)) 2510 { 2511 status = false; 2512 m_context.getTestContext().getLog() 2513 << tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i]) 2514 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2515 break; 2516 } 2517 } 2518 2519 { 2520 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); 2521 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2522 for (int face = 0; face < 6; ++face) 2523 { 2524 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]); 2525 for (int i = 0; i < kSize * kSize; ++i) 2526 { 2527 if (!tcu::allEqual(data[i], expected_value)) 2528 { 2529 status = false; 2530 m_context.getTestContext().getLog() 2531 << tcu::TestLog::Message 2532 << "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i]) 2533 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2534 break; 2535 } 2536 } 2537 } 2538 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 2539 } 2540 2541 glBindTexture(GL_TEXTURE_BUFFER, textures[5]); 2542 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2543 glBindTexture(GL_TEXTURE_BUFFER, 0); 2544 glBindBuffer(GL_TEXTURE_BUFFER, buffer); 2545 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]); 2546 glBindBuffer(GL_TEXTURE_BUFFER, 0); 2547 for (int i = 0; i < kSize; ++i) 2548 { 2549 if (!tcu::allEqual(data[i], expected_value)) 2550 { 2551 status = false; 2552 m_context.getTestContext().getLog() 2553 << tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i]) 2554 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2555 break; 2556 } 2557 } 2558 2559 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]); 2560 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2561 glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]); 2562 glBindTexture(GL_TEXTURE_1D_ARRAY, 0); 2563 for (int i = 0; i < kSize * 2; ++i) 2564 { 2565 if (!tcu::allEqual(data[i], expected_value)) 2566 { 2567 status = false; 2568 m_context.getTestContext().getLog() 2569 << tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i]) 2570 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2571 break; 2572 } 2573 } 2574 2575 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); 2576 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2577 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]); 2578 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 2579 for (int i = 0; i < kSize * kSize * 2; ++i) 2580 { 2581 if (!tcu::allEqual(data[i], expected_value)) 2582 { 2583 status = false; 2584 m_context.getTestContext().getLog() 2585 << tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i]) 2586 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2587 break; 2588 } 2589 } 2590 2591 glUseProgram(0); 2592 glDeleteProgram(program); 2593 glDeleteTextures(8, textures); 2594 glDeleteBuffers(1, &buffer); 2595 2596 return status; 2597 } 2598 2599 template <typename T> 2600 bool WriteMS(GLenum internalformat, const T& write_value, const T& expected_value) 2601 { 2602 2603 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 2604 " gl_Position = i_position;" NL "}"; 2605 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str()); 2606 const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str()); 2607 GLuint textures[2]; 2608 glGenTextures(2, textures); 2609 2610 const int kSize = 16; 2611 2612 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]); 2613 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE); 2614 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); 2615 2616 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]); 2617 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE); 2618 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0); 2619 2620 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 2621 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2622 2623 glClear(GL_COLOR_BUFFER_BIT); 2624 glUseProgram(program); 2625 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1); 2626 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4); 2627 2628 glBindVertexArray(m_vao); 2629 glViewport(0, 0, kSize, kSize); 2630 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 2631 2632 bool status = true; 2633 2634 glActiveTexture(GL_TEXTURE0); 2635 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]); 2636 glActiveTexture(GL_TEXTURE1); 2637 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]); 2638 2639 glUseProgram(val_program); 2640 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0); 2641 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1); 2642 2643 glBindVertexArray(m_vao); 2644 glViewport(0, 0, kSize, kSize); 2645 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 2646 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 2647 2648 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 2649 { 2650 status = false; 2651 m_context.getTestContext().getLog() 2652 << tcu::TestLog::Message 2653 << "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed." 2654 << tcu::TestLog::EndMessage; 2655 } 2656 2657 glActiveTexture(GL_TEXTURE0); 2658 glDeleteTextures(2, textures); 2659 glUseProgram(0); 2660 glDeleteProgram(program); 2661 glDeleteProgram(val_program); 2662 2663 return status; 2664 } 2665 2666 template <typename T> 2667 bool WriteCubeArray(GLenum internalformat, const T& write_value, const T& expected_value) 2668 { 2669 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 2670 " gl_Position = i_position;" NL "}"; 2671 const GLuint program = 2672 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str()); 2673 GLuint textures[1]; 2674 glGenTextures(1, textures); 2675 2676 const int kSize = 16; 2677 2678 std::vector<T> data(kSize * kSize * 12); 2679 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]); 2680 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 2681 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(), 2682 &data[0]); 2683 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); 2684 2685 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2686 2687 glUseProgram(program); 2688 glBindVertexArray(m_vao); 2689 glViewport(0, 0, kSize, kSize); 2690 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 2691 2692 bool status = true; 2693 2694 std::fill(data.begin(), data.end(), T(0)); 2695 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]); 2696 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2697 glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]); 2698 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); 2699 for (int i = 0; i < kSize * kSize * 12; ++i) 2700 { 2701 if (!tcu::allEqual(data[i], expected_value)) 2702 { 2703 status = false; 2704 m_context.getTestContext().getLog() 2705 << tcu::TestLog::Message 2706 << "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i]) 2707 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2708 break; 2709 } 2710 } 2711 2712 glDeleteTextures(1, textures); 2713 glUseProgram(0); 2714 glDeleteProgram(program); 2715 2716 return status; 2717 } 2718 2719 template <typename T> 2720 std::string GenFS(GLenum internalformat, const T& write_value) 2721 { 2722 std::ostringstream os; 2723 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 2724 << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) 2725 << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" 2726 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 2727 << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 2728 << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) 2729 << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" 2730 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 2731 << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 2732 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat) 2733 << ") writeonly uniform " << TypePrefix<T>() 2734 << "image2DArray g_image_2darray;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 2735 " imageStore(g_image_1d, coord.x, " 2736 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2d, coord, " << TypePrefix<T>() 2737 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>() 2738 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>() 2739 << "vec4" << write_value << ");" NL " imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4" 2740 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" 2741 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" 2742 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4" 2743 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4" 2744 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4" 2745 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4" 2746 << write_value << ");" NL " imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4" 2747 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4" 2748 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4" 2749 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" 2750 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" 2751 << write_value << ");" NL " discard;" NL "}"; 2752 return os.str(); 2753 } 2754 2755 template <typename T> 2756 std::string GenFSMS(GLenum internalformat, const T& write_value) 2757 { 2758 std::ostringstream os; 2759 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 2760 << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) 2761 << ") writeonly uniform " << TypePrefix<T>() 2762 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 2763 " imageStore(g_image_2dms, coord, 0, " 2764 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 1, " 2765 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 2, " 2766 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 3, " 2767 << TypePrefix<T>() << "vec4" << write_value 2768 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4" 2769 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>() 2770 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 2, " 2771 << TypePrefix<T>() << "vec4" << write_value 2772 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4" 2773 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>() 2774 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 1, " 2775 << TypePrefix<T>() << "vec4" << write_value 2776 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4" 2777 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>() 2778 << "vec4" << write_value << ");" NL " discard;" NL "}"; 2779 return os.str(); 2780 } 2781 2782 template <typename T> 2783 std::string GenFSMSVal(const T& expected_value) 2784 { 2785 std::ostringstream os; 2786 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>() 2787 << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>() 2788 << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 2789 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (texelFetch(g_sampler_2dms, coord, 0) != " 2790 << TypePrefix<T>() << "vec4" << expected_value 2791 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 1) != " 2792 << TypePrefix<T>() << "vec4" << expected_value 2793 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 2) != " 2794 << TypePrefix<T>() << "vec4" << expected_value 2795 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 3) != " 2796 << TypePrefix<T>() << "vec4" << expected_value 2797 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL 2798 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != " 2799 << TypePrefix<T>() << "vec4" << expected_value 2800 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL 2801 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != " 2802 << TypePrefix<T>() << "vec4" << expected_value 2803 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL 2804 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != " 2805 << TypePrefix<T>() << "vec4" << expected_value 2806 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL 2807 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != " 2808 << TypePrefix<T>() << "vec4" << expected_value 2809 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL 2810 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != " 2811 << TypePrefix<T>() << "vec4" << expected_value 2812 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL 2813 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != " 2814 << TypePrefix<T>() << "vec4" << expected_value 2815 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL 2816 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != " 2817 << TypePrefix<T>() << "vec4" << expected_value 2818 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL 2819 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != " 2820 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}"; 2821 return os.str(); 2822 } 2823 2824 template <typename T> 2825 std::string GenFSCubeArray(GLenum internalformat, const T& write_value) 2826 { 2827 std::ostringstream os; 2828 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 2829 << TypePrefix<T>() 2830 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 2831 " imageStore(g_image_cube_array, ivec3(coord, 0), " 2832 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 1), " 2833 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 2), " 2834 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 3), " 2835 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 4), " 2836 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 5), " 2837 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 6), " 2838 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 7), " 2839 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 8), " 2840 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 9), " 2841 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 10), " 2842 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 11), " 2843 << TypePrefix<T>() << "vec4" << write_value << ");" NL " discard;" NL "}"; 2844 return os.str(); 2845 } 2846}; 2847//----------------------------------------------------------------------------- 2848// 1.3.2.1 BasicAllTargetsLoadNonMS 2849//----------------------------------------------------------------------------- 2850class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase 2851{ 2852 GLuint m_vao; 2853 GLuint m_vbo; 2854 2855 virtual long Setup() 2856 { 2857 m_vao = 0; 2858 m_vbo = 0; 2859 return NO_ERROR; 2860 } 2861 2862 virtual long Run() 2863 { 2864 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 2865 2866 if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f))) 2867 return ERROR; 2868 if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000))) 2869 return ERROR; 2870 if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000))) 2871 return ERROR; 2872 2873 if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f))) 2874 return ERROR; 2875 if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000))) 2876 return ERROR; 2877 if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000))) 2878 return ERROR; 2879 2880 return NO_ERROR; 2881 } 2882 2883 virtual long Cleanup() 2884 { 2885 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 2886 glDeleteVertexArrays(1, &m_vao); 2887 glDeleteBuffers(1, &m_vbo); 2888 return NO_ERROR; 2889 } 2890 2891 template <typename T> 2892 bool Read(GLenum internalformat, const T& value, const T& expected_value) 2893 { 2894 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 2895 " gl_Position = i_position;" NL "}"; 2896 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str()); 2897 GLuint textures[7]; 2898 GLuint buffer; 2899 glGenTextures(7, textures); 2900 glGenBuffers(1, &buffer); 2901 2902 const int kSize = 16; 2903 std::vector<T> data(kSize * kSize * 2, value); 2904 2905 glBindTexture(GL_TEXTURE_1D, textures[0]); 2906 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2907 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2908 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2909 glBindTexture(GL_TEXTURE_1D, 0); 2910 2911 glBindTexture(GL_TEXTURE_2D, textures[1]); 2912 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2913 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2914 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2915 glBindTexture(GL_TEXTURE_2D, 0); 2916 2917 glBindTexture(GL_TEXTURE_3D, textures[2]); 2918 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2919 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2920 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 2921 glBindTexture(GL_TEXTURE_3D, 0); 2922 2923 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]); 2924 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2925 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2926 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2927 glBindTexture(GL_TEXTURE_RECTANGLE, 0); 2928 2929 glBindBuffer(GL_TEXTURE_BUFFER, buffer); 2930 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW); 2931 glBindBuffer(GL_TEXTURE_BUFFER, 0); 2932 glBindTexture(GL_TEXTURE_BUFFER, textures[4]); 2933 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer); 2934 glBindTexture(GL_TEXTURE_BUFFER, 0); 2935 2936 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]); 2937 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2938 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2939 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 2940 glBindTexture(GL_TEXTURE_1D_ARRAY, 0); 2941 2942 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]); 2943 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2944 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2945 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 2946 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 2947 2948 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 2949 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 2950 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 2951 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 2952 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 2953 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 2954 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 2955 2956 glClear(GL_COLOR_BUFFER_BIT); 2957 2958 glUseProgram(program); 2959 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0); 2960 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1); 2961 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2); 2962 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3); 2963 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4); 2964 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5); 2965 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6); 2966 2967 glBindVertexArray(m_vao); 2968 glViewport(0, 0, kSize, kSize); 2969 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 2970 2971 bool status = true; 2972 2973 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 2974 { 2975 status = false; 2976 } 2977 2978 std::map<std::string, GLuint> name_index_map; 2979 GLint uniforms; 2980 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms); 2981 if (uniforms != 7) 2982 { 2983 status = false; 2984 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms 2985 << " should be 7." << tcu::TestLog::EndMessage; 2986 } 2987 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index) 2988 { 2989 GLchar name[32]; 2990 glGetActiveUniformName(program, index, sizeof(name), NULL, name); 2991 name_index_map.insert(std::make_pair(std::string(name), index)); 2992 } 2993 2994 if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D))) 2995 status = false; 2996 if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D))) 2997 status = false; 2998 if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D))) 2999 status = false; 3000 if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE))) 3001 status = false; 3002 if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER))) 3003 status = false; 3004 if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY))) 3005 status = false; 3006 if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY))) 3007 status = false; 3008 3009 glUseProgram(0); 3010 glDeleteProgram(program); 3011 glDeleteTextures(7, textures); 3012 glDeleteBuffers(1, &buffer); 3013 3014 return status; 3015 } 3016 3017 template <typename T> 3018 bool ReadCube(GLenum internalformat, const T& value, const T& expected_value) 3019 { 3020 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 3021 " gl_Position = i_position;" NL "}"; 3022 const GLuint program = 3023 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str()); 3024 GLuint textures[2]; 3025 glGenTextures(2, textures); 3026 3027 const int kSize = 16; 3028 std::vector<T> data(kSize * kSize * 12, value); 3029 3030 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]); 3031 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3032 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3033 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3034 &data[0]); 3035 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3036 &data[0]); 3037 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3038 &data[0]); 3039 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3040 &data[0]); 3041 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3042 &data[0]); 3043 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3044 &data[0]); 3045 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 3046 3047 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]); 3048 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3049 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3050 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(), 3051 &data[0]); 3052 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); 3053 3054 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 3055 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 3056 3057 glClear(GL_COLOR_BUFFER_BIT); 3058 3059 glUseProgram(program); 3060 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0); 3061 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1); 3062 3063 glBindVertexArray(m_vao); 3064 glViewport(0, 0, kSize, kSize); 3065 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3066 3067 bool status = true; 3068 3069 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 3070 { 3071 status = false; 3072 } 3073 3074 std::map<std::string, GLuint> name_index_map; 3075 GLint uniforms; 3076 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms); 3077 if (uniforms != 2) 3078 { 3079 status = false; 3080 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms 3081 << " should be 2." << tcu::TestLog::EndMessage; 3082 } 3083 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index) 3084 { 3085 GLchar name[32]; 3086 glGetActiveUniformName(program, index, sizeof(name), NULL, name); 3087 name_index_map.insert(std::make_pair(std::string(name), index)); 3088 } 3089 3090 if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP))) 3091 status = false; 3092 if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY))) 3093 status = false; 3094 3095 glUseProgram(0); 3096 glDeleteProgram(program); 3097 glDeleteTextures(2, textures); 3098 3099 return status; 3100 } 3101 3102 template <typename T> 3103 std::string GenFS(GLenum internalformat, const T& expected_value) 3104 { 3105 std::ostringstream os; 3106 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 3107 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 3108 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 3109 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) 3110 << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" 3111 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 3112 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 3113 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) 3114 << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" 3115 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 3116 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 3117 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " " 3118 << TypePrefix<T>() 3119 << "vec4 v;" NL " v = imageLoad(g_image_1d, coord.x);" NL " if (v != " << TypePrefix<T>() << "vec4" 3120 << expected_value 3121 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_2d, coord);" NL " if (v != " 3122 << TypePrefix<T>() << "vec4" << expected_value 3123 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL 3124 " if (v != " 3125 << TypePrefix<T>() << "vec4" << expected_value 3126 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL 3127 " if (v != " 3128 << TypePrefix<T>() << "vec4" << expected_value 3129 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_2drect, coord);" NL " if (v != " 3130 << TypePrefix<T>() << "vec4" << expected_value 3131 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_buffer, coord.x);" NL " if (v != " 3132 << TypePrefix<T>() << "vec4" << expected_value 3133 << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL 3134 " if (v != " 3135 << TypePrefix<T>() << "vec4" << expected_value 3136 << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL 3137 " if (v != " 3138 << TypePrefix<T>() << "vec4" << expected_value 3139 << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL 3140 " if (v != " 3141 << TypePrefix<T>() << "vec4" << expected_value 3142 << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL 3143 " if (v != " 3144 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}"; 3145 return os.str(); 3146 } 3147 3148 template <typename T> 3149 std::string GenFSCube(GLenum internalformat, const T& expected_value) 3150 { 3151 std::ostringstream os; 3152 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 3153 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 3154 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 3155 << TypePrefix<T>() 3156 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 3157 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " " 3158 << TypePrefix<T>() 3159 << "vec4 v;" NL " v = imageLoad(g_image_cube, ivec3(coord, 0));" NL " if (v != " << TypePrefix<T>() 3160 << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL 3161 " v = imageLoad(g_image_cube, ivec3(coord, 1));" NL " if (v != " 3162 << TypePrefix<T>() << "vec4" << expected_value 3163 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube, ivec3(coord, 2));" NL 3164 " if (v != " 3165 << TypePrefix<T>() << "vec4" << expected_value 3166 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube, ivec3(coord, 3));" NL 3167 " if (v != " 3168 << TypePrefix<T>() << "vec4" << expected_value 3169 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube, ivec3(coord, 4));" NL 3170 " if (v != " 3171 << TypePrefix<T>() << "vec4" << expected_value 3172 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube, ivec3(coord, 5));" NL 3173 " if (v != " 3174 << TypePrefix<T>() << "vec4" << expected_value 3175 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL 3176 " if (v != " 3177 << TypePrefix<T>() << "vec4" << expected_value 3178 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL 3179 " if (v != " 3180 << TypePrefix<T>() << "vec4" << expected_value 3181 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL 3182 " if (v != " 3183 << TypePrefix<T>() << "vec4" << expected_value 3184 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL 3185 " if (v != " 3186 << TypePrefix<T>() << "vec4" << expected_value 3187 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL 3188 " if (v != " 3189 << TypePrefix<T>() << "vec4" << expected_value 3190 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL 3191 " if (v != " 3192 << TypePrefix<T>() << "vec4" << expected_value 3193 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL 3194 " if (v != " 3195 << TypePrefix<T>() << "vec4" << expected_value 3196 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL 3197 " if (v != " 3198 << TypePrefix<T>() << "vec4" << expected_value 3199 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL 3200 " if (v != " 3201 << TypePrefix<T>() << "vec4" << expected_value 3202 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL 3203 " if (v != " 3204 << TypePrefix<T>() << "vec4" << expected_value 3205 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL 3206 " if (v != " 3207 << TypePrefix<T>() << "vec4" << expected_value 3208 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL 3209 " if (v != " 3210 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}"; 3211 return os.str(); 3212 } 3213}; 3214//----------------------------------------------------------------------------- 3215// 1.3.2.2 BasicAllTargetsLoadMS 3216//----------------------------------------------------------------------------- 3217class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase 3218{ 3219 GLuint m_vao; 3220 GLuint m_vbo; 3221 3222 virtual long Setup() 3223 { 3224 m_vao = 0; 3225 m_vbo = 0; 3226 return NO_ERROR; 3227 } 3228 3229 virtual long Run() 3230 { 3231 if (!SupportedSamples(4)) 3232 return NOT_SUPPORTED; 3233 3234 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 3235 3236 if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f))) 3237 return ERROR; 3238 3239 GLint isamples; 3240 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples); 3241 if (isamples >= 4) 3242 { 3243 if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 3244 return ERROR; 3245 if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 3246 return ERROR; 3247 } 3248 3249 return NO_ERROR; 3250 } 3251 3252 virtual long Cleanup() 3253 { 3254 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 3255 glDeleteVertexArrays(1, &m_vao); 3256 glDeleteBuffers(1, &m_vbo); 3257 return NO_ERROR; 3258 } 3259 3260 template <typename T> 3261 bool ReadMS(GLenum internalformat, const T& value, const T& expected_value) 3262 { 3263 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 3264 " gl_Position = i_position;" NL "}"; 3265 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str()); 3266 GLuint textures[2]; 3267 glGenTextures(2, textures); 3268 3269 const int kSize = 16; 3270 3271 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]); 3272 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE); 3273 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); 3274 3275 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]); 3276 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE); 3277 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0); 3278 3279 GLuint fbo; 3280 glGenFramebuffers(1, &fbo); 3281 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 3282 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0); 3283 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0); 3284 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1); 3285 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; 3286 glDrawBuffers(3, draw_buffers); 3287 ClearBuffer(GL_COLOR, 0, value); 3288 ClearBuffer(GL_COLOR, 1, value); 3289 ClearBuffer(GL_COLOR, 2, value); 3290 glDeleteFramebuffers(1, &fbo); 3291 3292 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 3293 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 3294 3295 glUseProgram(program); 3296 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1); 3297 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4); 3298 3299 glClear(GL_COLOR_BUFFER_BIT); 3300 glBindVertexArray(m_vao); 3301 glViewport(0, 0, kSize, kSize); 3302 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3303 3304 bool status = true; 3305 3306 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 3307 { 3308 status = false; 3309 } 3310 3311 std::map<std::string, GLuint> name_index_map; 3312 GLint uniforms; 3313 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms); 3314 if (uniforms != 2) 3315 { 3316 status = false; 3317 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms 3318 << " should be 2." << tcu::TestLog::EndMessage; 3319 } 3320 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index) 3321 { 3322 GLchar name[32]; 3323 glGetActiveUniformName(program, index, sizeof(name), NULL, name); 3324 name_index_map.insert(std::make_pair(std::string(name), index)); 3325 } 3326 3327 if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE))) 3328 status = false; 3329 if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1, 3330 ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY))) 3331 status = false; 3332 3333 glDeleteTextures(2, textures); 3334 glUseProgram(0); 3335 glDeleteProgram(program); 3336 3337 return status; 3338 } 3339 3340 template <typename T> 3341 std::string GenFSMS(GLenum internalformat, const T& expected_value) 3342 { 3343 std::ostringstream os; 3344 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 3345 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 3346 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 3347 << TypePrefix<T>() 3348 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 3349 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (imageLoad(g_image_2dms, coord, 0) != " 3350 << TypePrefix<T>() << "vec4" << expected_value 3351 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 1) != " 3352 << TypePrefix<T>() << "vec4" << expected_value 3353 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 2) != " 3354 << TypePrefix<T>() << "vec4" << expected_value 3355 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 3) != " 3356 << TypePrefix<T>() << "vec4" << expected_value 3357 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != " 3358 << TypePrefix<T>() << "vec4" << expected_value 3359 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != " 3360 << TypePrefix<T>() << "vec4" << expected_value 3361 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != " 3362 << TypePrefix<T>() << "vec4" << expected_value 3363 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != " 3364 << TypePrefix<T>() << "vec4" << expected_value 3365 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != " 3366 << TypePrefix<T>() << "vec4" << expected_value 3367 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != " 3368 << TypePrefix<T>() << "vec4" << expected_value 3369 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != " 3370 << TypePrefix<T>() << "vec4" << expected_value 3371 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != " 3372 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}"; 3373 return os.str(); 3374 } 3375}; 3376//----------------------------------------------------------------------------- 3377// 1.3.3 BasicAllTargetsAtomic 3378//----------------------------------------------------------------------------- 3379class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase 3380{ 3381 GLuint m_vao; 3382 GLuint m_vbo; 3383 3384 virtual long Setup() 3385 { 3386 m_vao = 0; 3387 m_vbo = 0; 3388 return NO_ERROR; 3389 } 3390 3391 virtual long Run() 3392 { 3393 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 3394 3395 if (!Atomic<GLint>(GL_R32I)) 3396 return ERROR; 3397 if (!Atomic<GLuint>(GL_R32UI)) 3398 return ERROR; 3399 3400 if (!AtomicCube<GLint>(GL_R32I)) 3401 return ERROR; 3402 if (!AtomicCube<GLuint>(GL_R32UI)) 3403 return ERROR; 3404 3405 GLint isamples; 3406 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples); 3407 if (SupportedSamples(4) && isamples >= 4) 3408 { 3409 if (!AtomicMS<GLint>(GL_R32I)) 3410 return ERROR; 3411 if (!AtomicMS<GLuint>(GL_R32UI)) 3412 return ERROR; 3413 } 3414 3415 return NO_ERROR; 3416 } 3417 3418 virtual long Cleanup() 3419 { 3420 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 3421 glDeleteVertexArrays(1, &m_vao); 3422 glDeleteBuffers(1, &m_vbo); 3423 return NO_ERROR; 3424 } 3425 3426 template <typename T> 3427 bool Atomic(GLenum internalformat) 3428 { 3429 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 3430 " gl_Position = i_position;" NL "}"; 3431 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str()); 3432 GLuint textures[7]; 3433 GLuint buffer; 3434 glGenTextures(7, textures); 3435 glGenBuffers(1, &buffer); 3436 3437 const int kSize = 16; 3438 std::vector<T> data(kSize * kSize * 2); 3439 3440 glBindTexture(GL_TEXTURE_1D, textures[0]); 3441 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3442 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3443 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]); 3444 glBindTexture(GL_TEXTURE_1D, 0); 3445 3446 glBindTexture(GL_TEXTURE_2D, textures[1]); 3447 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3448 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3449 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 3450 glBindTexture(GL_TEXTURE_2D, 0); 3451 3452 glBindTexture(GL_TEXTURE_3D, textures[2]); 3453 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3454 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3455 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 3456 glBindTexture(GL_TEXTURE_3D, 0); 3457 3458 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]); 3459 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3460 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3461 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 3462 glBindTexture(GL_TEXTURE_RECTANGLE, 0); 3463 3464 glBindBuffer(GL_TEXTURE_BUFFER, buffer); 3465 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW); 3466 glBindBuffer(GL_TEXTURE_BUFFER, 0); 3467 glBindTexture(GL_TEXTURE_BUFFER, textures[4]); 3468 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer); 3469 glBindTexture(GL_TEXTURE_BUFFER, 0); 3470 3471 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]); 3472 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3473 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3474 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 3475 glBindTexture(GL_TEXTURE_1D_ARRAY, 0); 3476 3477 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]); 3478 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3479 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3480 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 3481 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 3482 3483 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 3484 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 3485 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 3486 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 3487 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 3488 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 3489 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 3490 3491 glClear(GL_COLOR_BUFFER_BIT); 3492 3493 glUseProgram(program); 3494 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0); 3495 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1); 3496 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2); 3497 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3); 3498 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4); 3499 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5); 3500 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6); 3501 3502 glBindVertexArray(m_vao); 3503 glViewport(0, 0, kSize, 1); 3504 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3505 3506 bool status = true; 3507 3508 if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1))) 3509 { 3510 status = false; 3511 } 3512 3513 glUseProgram(0); 3514 glDeleteProgram(program); 3515 glDeleteTextures(7, textures); 3516 glDeleteBuffers(1, &buffer); 3517 3518 return status; 3519 } 3520 3521 template <typename T> 3522 bool AtomicCube(GLenum internalformat) 3523 { 3524 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 3525 " gl_Position = i_position;" NL "}"; 3526 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str()); 3527 GLuint textures[2]; 3528 glGenTextures(2, textures); 3529 3530 const int kSize = 16; 3531 std::vector<T> data(kSize * kSize * 12); 3532 3533 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]); 3534 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3535 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3536 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3537 &data[0]); 3538 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3539 &data[0]); 3540 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3541 &data[0]); 3542 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3543 &data[0]); 3544 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3545 &data[0]); 3546 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3547 &data[0]); 3548 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 3549 3550 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]); 3551 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3552 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3553 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(), 3554 &data[0]); 3555 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); 3556 3557 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 3558 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 3559 3560 glClear(GL_COLOR_BUFFER_BIT); 3561 3562 glUseProgram(program); 3563 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0); 3564 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1); 3565 3566 glBindVertexArray(m_vao); 3567 glViewport(0, 0, kSize, kSize); 3568 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3569 3570 bool status = true; 3571 3572 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 3573 { 3574 status = false; 3575 } 3576 3577 glUseProgram(0); 3578 glDeleteProgram(program); 3579 glDeleteTextures(2, textures); 3580 3581 return status; 3582 } 3583 3584 template <typename T> 3585 bool AtomicMS(GLenum internalformat) 3586 { 3587 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 3588 " gl_Position = i_position;" NL "}"; 3589 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str()); 3590 GLuint textures[2]; 3591 glGenTextures(2, textures); 3592 3593 const int kSize = 16; 3594 3595 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]); 3596 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE); 3597 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); 3598 3599 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]); 3600 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE); 3601 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0); 3602 3603 GLuint fbo; 3604 glGenFramebuffers(1, &fbo); 3605 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 3606 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0); 3607 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0); 3608 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1); 3609 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; 3610 glDrawBuffers(3, draw_buffers); 3611 if (internalformat == GL_R32I) 3612 { 3613 const GLint value[4] = { 0, 0, 0, 0 }; 3614 glClearBufferiv(GL_COLOR, 0, value); 3615 glClearBufferiv(GL_COLOR, 1, value); 3616 glClearBufferiv(GL_COLOR, 2, value); 3617 } 3618 else 3619 { 3620 const GLuint value[4] = { 0, 0, 0, 0 }; 3621 glClearBufferuiv(GL_COLOR, 0, value); 3622 glClearBufferuiv(GL_COLOR, 1, value); 3623 glClearBufferuiv(GL_COLOR, 2, value); 3624 } 3625 glDeleteFramebuffers(1, &fbo); 3626 3627 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 3628 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 3629 3630 glUseProgram(program); 3631 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1); 3632 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4); 3633 3634 glClear(GL_COLOR_BUFFER_BIT); 3635 glBindVertexArray(m_vao); 3636 glViewport(0, 0, kSize, kSize); 3637 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3638 3639 bool status = true; 3640 3641 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 3642 { 3643 status = false; 3644 } 3645 3646 glDeleteTextures(2, textures); 3647 glUseProgram(0); 3648 glDeleteProgram(program); 3649 3650 return status; 3651 } 3652 3653 template <typename T> 3654 std::string GenFS(GLenum internalformat) 3655 { 3656 std::ostringstream os; 3657 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 3658 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 3659 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " 3660 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) 3661 << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" 3662 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 3663 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " 3664 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) 3665 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" 3666 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 3667 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 3668 " ivec2 coord = ivec2(gl_FragCoord.xy);" 3669 3670 NL " if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3671 " if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3672 " if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3673 " if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3674 " if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3675 " if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3676 " if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3677 " if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3678 " if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3679 3680 NL " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3681 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3682 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3683 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3684 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3685 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3686 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3687 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3688 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3689 3690 NL " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3691 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3692 " if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3693 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3694 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3695 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3696 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3697 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, " 3698 "1.0);" NL 3699 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3700 3701 NL " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3702 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3703 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3704 " if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3705 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3706 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3707 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3708 " if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3709 " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3710 3711 NL " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3712 " if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3713 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3714 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3715 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3716 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3717 " if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3718 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3719 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3720 3721 NL 3722 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3723 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3724 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3725 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3726 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3727 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3728 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, " 3729 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = " 3730 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), " 3731 "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3732 3733 NL " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3734 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3735 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3736 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3737 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3738 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3739 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, " 3740 "1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, " 3741 "0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) " 3742 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}"; 3743 return os.str(); 3744 } 3745 3746 template <typename T> 3747 std::string GenFSCube(GLenum internalformat) 3748 { 3749 std::ostringstream os; 3750 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 3751 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 3752 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " 3753 << TypePrefix<T>() 3754 << "imageCube g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 3755 " ivec2 coord = ivec2(gl_FragCoord.xy);" 3756 3757 NL " if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3758 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3759 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3760 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3761 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3762 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3763 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3764 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, " 3765 "1.0);" NL 3766 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3767 3768 NL " if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, " 3769 "1.0);" NL " if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, " 3770 "0.0, 1.0);" NL " if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color " 3771 "= vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicAnd(g_image_cube_array, " 3772 "ivec3(coord, 0), 0) != 4) o_color = " 3773 "vec4(1.0, 0.0, 0.0, 1.0);" NL 3774 " if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3775 " if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, " 3776 "1.0);" NL " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, " 3777 "0.0, 0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != " 3778 "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3779 " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, " 3780 "1.0);" NL "}"; 3781 return os.str(); 3782 } 3783 3784 template <typename T> 3785 std::string GenFSMS(GLenum internalformat) 3786 { 3787 std::ostringstream os; 3788 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 3789 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 3790 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " 3791 << TypePrefix<T>() 3792 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 3793 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 3794 " if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3795 " if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3796 " if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3797 " if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3798 " if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3799 " if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3800 " if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3801 " if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3802 " if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL 3803 " if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, " 3804 "1.0);" NL " if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, " 3805 "0.0, 0.0, 1.0);" NL " if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) " 3806 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3807 " if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, " 3808 "1.0);" NL " if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, " 3809 "0.0, 0.0, 1.0);" NL " if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) " 3810 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3811 " if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, " 3812 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = " 3813 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2dms_array, " 3814 "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, " 3815 "0.0, 1.0);" NL "}"; 3816 return os.str(); 3817 } 3818}; 3819//----------------------------------------------------------------------------- 3820// LoadStoreMachine 3821//----------------------------------------------------------------------------- 3822class LoadStoreMachine : public ShaderImageLoadStoreBase 3823{ 3824 GLuint m_vao; 3825 int m_stage; 3826 3827 virtual long Setup() 3828 { 3829 glGenVertexArrays(1, &m_vao); 3830 return NO_ERROR; 3831 } 3832 3833 virtual long Cleanup() 3834 { 3835 glDisable(GL_RASTERIZER_DISCARD); 3836 glDeleteVertexArrays(1, &m_vao); 3837 return NO_ERROR; 3838 } 3839 3840 template <typename T> 3841 bool Write(GLenum internalformat, const T& write_value, const T& expected_value) 3842 { 3843 const GLenum targets[] = { GL_TEXTURE_1D, GL_TEXTURE_2D, 3844 GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE, 3845 GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY, 3846 GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY }; 3847 const int kTargets = sizeof(targets) / sizeof(targets[0]); 3848 GLuint program_store = 0; 3849 GLuint program_load = 0; 3850 if (m_stage == 0) 3851 { // VS 3852 program_store = 3853 BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL); 3854 program_load = 3855 BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL); 3856 } 3857 else if (m_stage == 1) 3858 { // TCS 3859 const char* const glsl_vs = "#version 420 core" NL "void main() {}"; 3860 const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}"; 3861 program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(), 3862 glsl_tes, NULL, NULL); 3863 program_load = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(), 3864 glsl_tes, NULL, NULL); 3865 } 3866 else if (m_stage == 2) 3867 { // TES 3868 const char* const glsl_vs = "#version 420 core" NL "void main() {}"; 3869 program_store = 3870 BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL); 3871 program_load = 3872 BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL); 3873 } 3874 else if (m_stage == 3) 3875 { // GS 3876 const char* const glsl_vs = "#version 420 core" NL "void main() {}"; 3877 program_store = 3878 BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL); 3879 program_load = 3880 BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL); 3881 } 3882 else if (m_stage == 4) 3883 { // CS 3884 { 3885 std::string source = GenStoreShader(m_stage, internalformat, write_value); 3886 const char* const src = source.c_str(); 3887 GLuint sh = glCreateShader(GL_COMPUTE_SHADER); 3888 glShaderSource(sh, 1, &src, NULL); 3889 glCompileShader(sh); 3890 program_store = glCreateProgram(); 3891 glAttachShader(program_store, sh); 3892 glLinkProgram(program_store); 3893 glDeleteShader(sh); 3894 } 3895 { 3896 std::string source = GenLoadShader(m_stage, internalformat, expected_value); 3897 const char* const src = source.c_str(); 3898 GLuint sh = glCreateShader(GL_COMPUTE_SHADER); 3899 glShaderSource(sh, 1, &src, NULL); 3900 glCompileShader(sh); 3901 program_load = glCreateProgram(); 3902 glAttachShader(program_load, sh); 3903 glLinkProgram(program_load); 3904 glDeleteShader(sh); 3905 } 3906 } 3907 GLuint textures[kTargets], texture_result; 3908 glGenTextures(kTargets, textures); 3909 glGenTextures(1, &texture_result); 3910 3911 glBindTexture(GL_TEXTURE_2D, texture_result); 3912 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3913 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3914 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1); 3915 3916 for (int i = 0; i < kTargets; ++i) 3917 { 3918 glBindTexture(targets[i], textures[i]); 3919 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3920 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3921 3922 if (targets[i] == GL_TEXTURE_1D) 3923 { 3924 glTexStorage1D(targets[i], 1, internalformat, 1); 3925 } 3926 else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE) 3927 { 3928 glTexStorage2D(targets[i], 1, internalformat, 1, 1); 3929 } 3930 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY) 3931 { 3932 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2); 3933 } 3934 else if (targets[i] == GL_TEXTURE_CUBE_MAP) 3935 { 3936 glTexStorage2D(targets[i], 1, internalformat, 1, 1); 3937 } 3938 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY) 3939 { 3940 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12); 3941 } 3942 else if (targets[i] == GL_TEXTURE_1D_ARRAY) 3943 { 3944 glTexStorage2D(targets[i], 1, internalformat, 1, 2); 3945 } 3946 } 3947 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 3948 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 3949 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 3950 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 3951 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 3952 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 3953 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 3954 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 3955 3956 glUseProgram(program_store); 3957 glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0); 3958 glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1); 3959 glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2); 3960 glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3); 3961 glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4); 3962 glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5); 3963 glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6); 3964 glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7); 3965 3966 glBindVertexArray(m_vao); 3967 if (m_stage == 1 || m_stage == 2) 3968 { // TCS or TES 3969 glPatchParameteri(GL_PATCH_VERTICES, 1); 3970 glDrawArrays(GL_PATCHES, 0, 1); 3971 glPatchParameteri(GL_PATCH_VERTICES, 3); 3972 } 3973 else if (m_stage == 4) 3974 { // CS 3975 glDispatchCompute(1, 1, 1); 3976 } 3977 else 3978 { 3979 glDrawArrays(GL_POINTS, 0, 1); 3980 } 3981 3982 bool status = true; 3983 for (int i = 0; i < kTargets; ++i) 3984 { 3985 glBindTexture(targets[i], textures[i]); 3986 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 3987 3988 if (targets[i] == GL_TEXTURE_CUBE_MAP) 3989 { 3990 for (int face = 0; face < 6; ++face) 3991 { 3992 T data; 3993 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]); 3994 if (!Equal(data, expected_value, internalformat)) 3995 { 3996 status = false; 3997 m_context.getTestContext().getLog() 3998 << tcu::TestLog::Message << "Value is: " << ToString(data) 3999 << ". Value should be: " << ToString(expected_value) 4000 << ". Format is: " << FormatEnumToString(internalformat) 4001 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage) 4002 << tcu::TestLog::EndMessage; 4003 } 4004 } 4005 } 4006 else 4007 { 4008 T data[12]; 4009 memset(&data[0], 0, sizeof(data)); 4010 glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]); 4011 4012 int count = 1; 4013 if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY) 4014 count = 2; 4015 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY) 4016 count = 12; 4017 else if (targets[i] == GL_TEXTURE_1D_ARRAY) 4018 count = 2; 4019 4020 for (int j = 0; j < count; ++j) 4021 { 4022 if (!Equal(data[j], expected_value, internalformat)) 4023 { 4024 status = false; 4025 m_context.getTestContext().getLog() 4026 << tcu::TestLog::Message << "Value is: " << ToString(data[j]) 4027 << ". Value should be: " << ToString(expected_value) 4028 << ". Format is: " << FormatEnumToString(internalformat) 4029 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage) 4030 << tcu::TestLog::EndMessage; 4031 } 4032 } 4033 } 4034 } 4035 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 4036 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 4037 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 4038 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 4039 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 4040 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 4041 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 4042 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 4043 4044 glUseProgram(program_load); 4045 glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0); 4046 glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1); 4047 glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2); 4048 glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3); 4049 glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4); 4050 glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5); 4051 glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6); 4052 glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7); 4053 4054 if (m_stage == 1 || m_stage == 2) 4055 { // TCS or TES 4056 glPatchParameteri(GL_PATCH_VERTICES, 1); 4057 glDrawArrays(GL_PATCHES, 0, 1); 4058 glPatchParameteri(GL_PATCH_VERTICES, 3); 4059 } 4060 else if (m_stage == 4) 4061 { // CS 4062 glDispatchCompute(1, 1, 1); 4063 } 4064 else 4065 { 4066 glDrawArrays(GL_POINTS, 0, 1); 4067 } 4068 { 4069 vec4 color; 4070 glBindTexture(GL_TEXTURE_2D, texture_result); 4071 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 4072 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]); 4073 if (!tcu::allEqual(color, vec4(0, 1, 0, 1))) 4074 { 4075 status = false; 4076 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color) 4077 << ". Format is: " << FormatEnumToString(internalformat) 4078 << ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage; 4079 } 4080 } 4081 glUseProgram(0); 4082 glDeleteProgram(program_store); 4083 glDeleteProgram(program_load); 4084 glDeleteTextures(kTargets, textures); 4085 glDeleteTextures(1, &texture_result); 4086 return status; 4087 } 4088 4089 template <typename T> 4090 std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value) 4091 { 4092 std::ostringstream os; 4093 os << "#version 420 core"; 4094 if (stage == 4) 4095 { // CS 4096 os << NL "#extension GL_ARB_compute_shader : require"; 4097 } 4098 os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 4099 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 4100 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) 4101 << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" 4102 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 4103 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 4104 << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) 4105 << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" 4106 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 4107 << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat) 4108 << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform " 4109 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value 4110 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);"; 4111 if (stage == 0) 4112 { // VS 4113 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);"; 4114 } 4115 else if (stage == 1) 4116 { // TCS 4117 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL 4118 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL 4119 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL 4120 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);"; 4121 } 4122 else if (stage == 2) 4123 { // TES 4124 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL 4125 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);"; 4126 } 4127 else if (stage == 3) 4128 { // GS 4129 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL 4130 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);"; 4131 } 4132 else if (stage == 4) 4133 { // CS 4134 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL 4135 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);"; 4136 } 4137 os << NL " imageStore(g_image_1d, coord.x, g_value);" NL " imageStore(g_image_2d, coord, g_value);" NL 4138 " imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL 4139 " imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL 4140 " imageStore(g_image_2drect, coord, g_value);" NL " for (int i = 0; i < 6; ++i) {" NL 4141 " imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL " }" NL 4142 " imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL 4143 " imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL 4144 " imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL 4145 " imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL 4146 " for (int i = 0; i < 6; ++i) {" NL 4147 " imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL " }" NL 4148 " for (int i = 0; i < 6; ++i) {" NL 4149 " imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL " }" NL "}"; 4150 return os.str(); 4151 } 4152 4153 template <typename T> 4154 std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value) 4155 { 4156 std::ostringstream os; 4157 os << "#version 420 core"; 4158 if (stage == 4) 4159 { // CS 4160 os << NL "#extension GL_ARB_compute_shader : require"; 4161 } 4162 os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 4163 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 4164 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) 4165 << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" 4166 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 4167 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 4168 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat) 4169 << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout(" 4170 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 4171 << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL 4172 "uniform " 4173 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value 4174 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);"; 4175 if (stage == 0) 4176 { // VS 4177 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);"; 4178 } 4179 else if (stage == 1) 4180 { // TCS 4181 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL 4182 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL 4183 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL 4184 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);"; 4185 } 4186 else if (stage == 2) 4187 { // TES 4188 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL 4189 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);"; 4190 } 4191 else if (stage == 3) 4192 { // GS 4193 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL 4194 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);"; 4195 } 4196 else if (stage == 4) 4197 { // CS 4198 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL 4199 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);"; 4200 } 4201 os << NL " vec4 r = vec4(0, 1, 0, 1);" NL " " << TypePrefix<T>() 4202 << "vec4 v;" NL " v = imageLoad(g_image_2d, coord);" NL 4203 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL 4204 " v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL 4205 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_2drect, coord);" NL 4206 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL 4207 " v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL 4208 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_1darray, coord);" NL 4209 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL 4210 " v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL 4211 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL 4212 " v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL 4213 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " imageStore(g_image_result, coord, r);" NL "}"; 4214 return os.str(); 4215 } 4216 4217protected: 4218 long RunStage(int stage) 4219 { 4220 if (!SupportedInStage(stage, 8)) 4221 return NOT_SUPPORTED; 4222 4223 glEnable(GL_RASTERIZER_DISCARD); 4224 m_stage = stage; 4225 4226 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 4227 return ERROR; 4228 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 4229 return ERROR; 4230 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 4231 return ERROR; 4232 4233 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 4234 return ERROR; 4235 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 4236 return ERROR; 4237 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 4238 return ERROR; 4239 4240 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 4241 return ERROR; 4242 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 4243 return ERROR; 4244 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 4245 return ERROR; 4246 4247 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f))) 4248 return ERROR; 4249 4250 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 4251 return ERROR; 4252 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 4253 return ERROR; 4254 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 4255 return ERROR; 4256 4257 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 4258 return ERROR; 4259 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 4260 return ERROR; 4261 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 4262 return ERROR; 4263 4264 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 4265 return ERROR; 4266 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 4267 return ERROR; 4268 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 4269 return ERROR; 4270 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 4271 return ERROR; 4272 4273 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 4274 return ERROR; 4275 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 4276 return ERROR; 4277 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 4278 return ERROR; 4279 4280 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 4281 return ERROR; 4282 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 4283 return ERROR; 4284 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 4285 return ERROR; 4286 4287 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f))) 4288 return ERROR; 4289 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f))) 4290 return ERROR; 4291 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 4292 return ERROR; 4293 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 4294 return ERROR; 4295 4296 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 4297 return ERROR; 4298 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 4299 return ERROR; 4300 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 4301 return ERROR; 4302 4303 // 4304 { 4305 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 4306 return ERROR; 4307 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 4308 return ERROR; 4309 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 4310 return ERROR; 4311 4312 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 4313 return ERROR; 4314 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 4315 return ERROR; 4316 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 4317 return ERROR; 4318 } 4319 return NO_ERROR; 4320 } 4321}; 4322//----------------------------------------------------------------------------- 4323// AtomicMachine 4324//----------------------------------------------------------------------------- 4325class AtomicMachine : public ShaderImageLoadStoreBase 4326{ 4327 GLuint m_vao; 4328 4329 virtual long Setup() 4330 { 4331 glEnable(GL_RASTERIZER_DISCARD); 4332 glGenVertexArrays(1, &m_vao); 4333 return NO_ERROR; 4334 } 4335 4336 virtual long Cleanup() 4337 { 4338 glDisable(GL_RASTERIZER_DISCARD); 4339 glDeleteVertexArrays(1, &m_vao); 4340 return NO_ERROR; 4341 } 4342 4343 template <typename T> 4344 bool Atomic(int stage, GLenum internalformat) 4345 { 4346 GLuint program = 0; 4347 if (stage == 0) 4348 { // VS 4349 program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL); 4350 } 4351 else if (stage == 1) 4352 { // TCS 4353 const char* const glsl_vs = "#version 420 core" NL "void main() {}"; 4354 const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}"; 4355 program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL); 4356 } 4357 else if (stage == 2) 4358 { // TES 4359 const char* const glsl_vs = "#version 420 core" NL "void main() {}"; 4360 program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL); 4361 } 4362 else if (stage == 3) 4363 { // GS 4364 const char* const glsl_vs = "#version 420 core" NL "void main() {}"; 4365 program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL); 4366 } 4367 else if (stage == 4) 4368 { // CS 4369 std::string source = GenShader<T>(stage, internalformat); 4370 const char* const src = source.c_str(); 4371 GLuint sh = glCreateShader(GL_COMPUTE_SHADER); 4372 glShaderSource(sh, 1, &src, NULL); 4373 glCompileShader(sh); 4374 program = glCreateProgram(); 4375 glAttachShader(program, sh); 4376 glLinkProgram(program); 4377 glDeleteShader(sh); 4378 } 4379 GLuint texture_result; 4380 glGenTextures(1, &texture_result); 4381 glBindTexture(GL_TEXTURE_2D, texture_result); 4382 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4383 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4384 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1); 4385 4386 const GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP, 4387 GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY }; 4388 const int kTargets = sizeof(targets) / sizeof(targets[0]); 4389 4390 GLuint textures[kTargets]; 4391 GLuint buffer; 4392 glGenTextures(kTargets, textures); 4393 glGenBuffers(1, &buffer); 4394 4395 for (int i = 0; i < kTargets; ++i) 4396 { 4397 glBindTexture(targets[i], textures[i]); 4398 if (targets[i] != GL_TEXTURE_BUFFER) 4399 { 4400 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4401 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4402 } 4403 if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE) 4404 { 4405 glTexStorage2D(targets[i], 1, internalformat, 1, 1); 4406 } 4407 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY) 4408 { 4409 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2); 4410 } 4411 else if (targets[i] == GL_TEXTURE_CUBE_MAP) 4412 { 4413 glTexStorage2D(targets[i], 1, internalformat, 1, 1); 4414 } 4415 else if (targets[i] == GL_TEXTURE_BUFFER) 4416 { 4417 glBindBuffer(GL_TEXTURE_BUFFER, buffer); 4418 glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW); 4419 glBindBuffer(GL_TEXTURE_BUFFER, 0); 4420 glTexBuffer(targets[i], internalformat, buffer); 4421 } 4422 else if (targets[i] == GL_TEXTURE_1D_ARRAY) 4423 { 4424 glTexStorage2D(targets[i], 1, internalformat, 1, 2); 4425 } 4426 } 4427 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 4428 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 4429 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 4430 glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 4431 glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 4432 glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 4433 glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 4434 glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 4435 4436 glUseProgram(program); 4437 glUniform1i(glGetUniformLocation(program, "g_image_result"), 0); 4438 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1); 4439 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2); 4440 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3); 4441 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4); 4442 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5); 4443 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6); 4444 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7); 4445 4446 glBindVertexArray(m_vao); 4447 if (stage == 1 || stage == 2) 4448 { // TCS or TES 4449 glPatchParameteri(GL_PATCH_VERTICES, 1); 4450 glDrawArrays(GL_PATCHES, 0, 1); 4451 glPatchParameteri(GL_PATCH_VERTICES, 3); 4452 } 4453 else if (stage == 4) 4454 { // CS 4455 glDispatchCompute(1, 1, 1); 4456 } 4457 else 4458 { 4459 glDrawArrays(GL_POINTS, 0, 1); 4460 } 4461 4462 bool status = true; 4463 { 4464 vec4 color; 4465 glBindTexture(GL_TEXTURE_2D, texture_result); 4466 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 4467 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]); 4468 if (!tcu::allEqual(color, vec4(0, 1, 0, 1))) 4469 { 4470 status = false; 4471 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color) 4472 << ". Format is: " << FormatEnumToString(internalformat) 4473 << ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage; 4474 } 4475 } 4476 glUseProgram(0); 4477 glDeleteProgram(program); 4478 glDeleteTextures(7, textures); 4479 glDeleteTextures(1, &texture_result); 4480 glDeleteBuffers(1, &buffer); 4481 return status; 4482 } 4483 4484 template <typename T> 4485 std::string GenShader(int stage, GLenum internalformat) 4486 { 4487 std::ostringstream os; 4488 os << "#version 420 core"; 4489 if (stage == 4) 4490 { // CS 4491 os << NL "#extension GL_ARB_compute_shader : require"; 4492 } 4493 os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 4494 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " 4495 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) 4496 << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" 4497 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 4498 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " 4499 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) 4500 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" 4501 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 4502 << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL 4503 "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);"; 4504 if (stage == 0) 4505 { // VS 4506 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_value[0]);"; 4507 } 4508 else if (stage == 1) 4509 { // TCS 4510 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL 4511 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL 4512 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL 4513 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);"; 4514 } 4515 else if (stage == 2) 4516 { // TES 4517 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL 4518 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);"; 4519 } 4520 else if (stage == 3) 4521 { // GS 4522 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL 4523 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);"; 4524 } 4525 else if (stage == 4) 4526 { // CS 4527 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL 4528 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);"; 4529 } 4530 os << NL 4531 " vec4 o_color = vec4(0, 1, 0, 1);" NL " imageAtomicExchange(g_image_2d, coord, 0);" NL 4532 " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4533 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4534 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4535 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4536 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4537 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4538 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4539 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4540 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4541 4542 NL " imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL 4543 " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4544 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4545 " if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4546 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4547 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4548 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4549 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4550 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4551 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4552 4553 NL " imageAtomicExchange(g_image_2drect, coord, 0);" NL 4554 " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4555 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4556 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4557 " if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4558 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4559 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4560 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4561 " if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, " 4562 "1.0);" NL " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4563 4564 NL " imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL " if (imageAtomicAdd(g_image_cube, " 4565 "ivec3(coord, 0), g_value[2]) != 0) " 4566 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4567 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4568 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4569 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4570 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4571 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4572 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4573 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, " 4574 "0.0, 1.0);" NL 4575 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4576 4577 NL " imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL 4578 " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4579 " if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4580 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4581 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4582 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4583 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4584 " if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, " 4585 "1.0);" NL 4586 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4587 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4588 4589 NL " imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL 4590 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4591 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4592 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, " 4593 "1.0);" NL 4594 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4595 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4596 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4597 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, " 4598 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, " 4599 "0.0, 0.0, 1.0);" NL 4600 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4601 4602 NL " imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL 4603 " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4604 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4605 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4606 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4607 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4608 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, " 4609 "1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, " 4610 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) " 4611 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4612 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4613 4614 NL " imageStore(g_image_result, coord, o_color);" NL "}"; 4615 return os.str(); 4616 } 4617 4618protected: 4619 long RunStage(int stage) 4620 { 4621 if (!SupportedInStage(stage, 8)) 4622 return NOT_SUPPORTED; 4623 if (!Atomic<GLint>(stage, GL_R32I)) 4624 return ERROR; 4625 if (!Atomic<GLuint>(stage, GL_R32UI)) 4626 return ERROR; 4627 return NO_ERROR; 4628 } 4629}; 4630//----------------------------------------------------------------------------- 4631// 1.3.4 BasicAllTargetsLoadStoreVS 4632//----------------------------------------------------------------------------- 4633class BasicAllTargetsLoadStoreVS : public LoadStoreMachine 4634{ 4635 virtual long Run() 4636 { 4637 return RunStage(0); 4638 } 4639}; 4640//----------------------------------------------------------------------------- 4641// 1.3.5 BasicAllTargetsLoadStoreTCS 4642//----------------------------------------------------------------------------- 4643class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine 4644{ 4645 virtual long Run() 4646 { 4647 return RunStage(1); 4648 } 4649}; 4650//----------------------------------------------------------------------------- 4651// 1.3.6 BasicAllTargetsLoadStoreTES 4652//----------------------------------------------------------------------------- 4653class BasicAllTargetsLoadStoreTES : public LoadStoreMachine 4654{ 4655 virtual long Run() 4656 { 4657 return RunStage(2); 4658 } 4659}; 4660//----------------------------------------------------------------------------- 4661// 1.3.7 BasicAllTargetsLoadStoreGS 4662//----------------------------------------------------------------------------- 4663class BasicAllTargetsLoadStoreGS : public LoadStoreMachine 4664{ 4665 virtual long Run() 4666 { 4667 return RunStage(3); 4668 } 4669}; 4670//----------------------------------------------------------------------------- 4671// 1.3.8 BasicAllTargetsLoadStoreCS 4672//----------------------------------------------------------------------------- 4673class BasicAllTargetsLoadStoreCS : public LoadStoreMachine 4674{ 4675 virtual long Run() 4676 { 4677 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) 4678 { 4679 m_context.getTestContext().getLog() 4680 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test" 4681 << tcu::TestLog::EndMessage; 4682 return NO_ERROR; 4683 } 4684 4685 return RunStage(4); 4686 } 4687}; 4688//----------------------------------------------------------------------------- 4689// 1.3.9 BasicAllTargetsAtomicVS 4690//----------------------------------------------------------------------------- 4691class BasicAllTargetsAtomicVS : public AtomicMachine 4692{ 4693 virtual long Run() 4694 { 4695 return RunStage(0); 4696 } 4697}; 4698//----------------------------------------------------------------------------- 4699// 1.3.10 BasicAllTargetsAtomicTCS 4700//----------------------------------------------------------------------------- 4701class BasicAllTargetsAtomicTCS : public AtomicMachine 4702{ 4703 virtual long Run() 4704 { 4705 return RunStage(1); 4706 } 4707}; 4708//----------------------------------------------------------------------------- 4709// 1.3.11 BasicAllTargetsAtomicTES 4710//----------------------------------------------------------------------------- 4711class BasicAllTargetsAtomicTES : public AtomicMachine 4712{ 4713 virtual long Run() 4714 { 4715 return RunStage(2); 4716 } 4717}; 4718//----------------------------------------------------------------------------- 4719// 1.3.12 BasicAllTargetsAtomicGS 4720//----------------------------------------------------------------------------- 4721class BasicAllTargetsAtomicGS : public AtomicMachine 4722{ 4723 virtual long Run() 4724 { 4725 return RunStage(3); 4726 } 4727}; 4728//----------------------------------------------------------------------------- 4729// 1.3.13 BasicAllTargetsAtomicCS 4730//----------------------------------------------------------------------------- 4731class BasicAllTargetsAtomicCS : public AtomicMachine 4732{ 4733 virtual long Run() 4734 { 4735 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) 4736 { 4737 m_context.getTestContext().getLog() 4738 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test" 4739 << tcu::TestLog::EndMessage; 4740 return NO_ERROR; 4741 } 4742 4743 return RunStage(4); 4744 } 4745}; 4746//----------------------------------------------------------------------------- 4747// 1.4.1 BasicGLSLMisc 4748//----------------------------------------------------------------------------- 4749class BasicGLSLMisc : public ShaderImageLoadStoreBase 4750{ 4751 GLuint m_texture; 4752 GLuint m_program; 4753 GLuint m_vao, m_vbo; 4754 4755 virtual long Setup() 4756 { 4757 m_texture = 0; 4758 m_program = 0; 4759 m_vao = m_vbo = 0; 4760 return NO_ERROR; 4761 } 4762 4763 virtual long Run() 4764 { 4765 const int kSize = 32; 4766 std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f)); 4767 4768 glGenTextures(1, &m_texture); 4769 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 4770 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 4771 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]); 4772 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 4773 4774 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 4775 " gl_Position = i_position;" NL "}"; 4776 const char* src_fs = 4777 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 4778 "layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL 4779 "layout(rgba32f) volatile uniform image2D g_image_layer1;" NL 4780 "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 4781 " imageStore(g_image_layer0, coord, vec4(1.0));" NL " memoryBarrier();" NL 4782 " imageStore(g_image_layer0, coord, vec4(2.0));" NL " memoryBarrier();" NL 4783 " imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL " memoryBarrier();" NL 4784 " o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}"; 4785 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs); 4786 4787 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 4788 4789 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4790 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F); 4791 4792 glClear(GL_COLOR_BUFFER_BIT); 4793 glViewport(0, 0, kSize, kSize); 4794 4795 glUseProgram(m_program); 4796 glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0); 4797 glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1); 4798 4799 glBindVertexArray(m_vao); 4800 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 4801 4802 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 4803 { 4804 return ERROR; 4805 } 4806 return NO_ERROR; 4807 } 4808 4809 virtual long Cleanup() 4810 { 4811 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 4812 glDeleteTextures(1, &m_texture); 4813 glDeleteVertexArrays(1, &m_vao); 4814 glDeleteBuffers(1, &m_vbo); 4815 glUseProgram(0); 4816 glDeleteProgram(m_program); 4817 return NO_ERROR; 4818 } 4819}; 4820//----------------------------------------------------------------------------- 4821// 1.4.2 BasicGLSLEarlyFragTests 4822//----------------------------------------------------------------------------- 4823class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase 4824{ 4825 GLuint m_texture[2]; 4826 GLuint m_program[2]; 4827 GLuint m_vao, m_vbo; 4828 4829 virtual long Setup() 4830 { 4831 m_texture[0] = m_texture[1] = 0; 4832 m_program[0] = m_program[1] = 0; 4833 m_vao = m_vbo = 0; 4834 return NO_ERROR; 4835 } 4836 4837 virtual long Run() 4838 { 4839 int ds = m_context.getRenderContext().getRenderTarget().getDepthBits(); 4840 4841 const int kSize = 32; 4842 std::vector<vec4> data(kSize * kSize); 4843 4844 glGenTextures(2, m_texture); 4845 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 4846 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 4847 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]); 4848 glBindTexture(GL_TEXTURE_2D, 0); 4849 4850 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 4851 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 4852 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]); 4853 glBindTexture(GL_TEXTURE_2D, 0); 4854 4855 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 4856 " gl_Position = i_position;" NL "}"; 4857 const char* glsl_early_frag_tests_fs = 4858 "#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL 4859 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL 4860 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL 4861 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}"; 4862 const char* glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 4863 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL 4864 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL 4865 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}"; 4866 m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs); 4867 m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 4868 4869 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 4870 4871 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4872 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4873 4874 glViewport(0, 0, kSize, kSize); 4875 glBindVertexArray(m_vao); 4876 4877 glEnable(GL_DEPTH_TEST); 4878 glClearColor(0.0, 1.0f, 0.0, 1.0f); 4879 glClearDepthf(0.0f); 4880 4881 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 4882 glUseProgram(m_program[0]); 4883 glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0); 4884 4885 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 4886 4887 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 4888 glUseProgram(m_program[1]); 4889 glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1); 4890 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 4891 4892 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 4893 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 4894 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]); 4895 for (int i = 0; i < kSize * kSize; ++i) 4896 { 4897 if (IsEqual(data[i], vec4(1.0f)) && ds != 0) 4898 return ERROR; 4899 } 4900 4901 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 4902 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 4903 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]); 4904 for (int i = 0; i < kSize * kSize; ++i) 4905 { 4906 if (!IsEqual(data[i], vec4(1.0f)) && ds != 0) 4907 return ERROR; 4908 } 4909 4910 return NO_ERROR; 4911 } 4912 4913 virtual long Cleanup() 4914 { 4915 glDisable(GL_DEPTH_TEST); 4916 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 4917 glClearDepthf(1.0f); 4918 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 4919 glDeleteTextures(2, m_texture); 4920 glDeleteVertexArrays(1, &m_vao); 4921 glDeleteBuffers(1, &m_vbo); 4922 glUseProgram(0); 4923 glDeleteProgram(m_program[0]); 4924 glDeleteProgram(m_program[1]); 4925 return NO_ERROR; 4926 } 4927}; 4928//----------------------------------------------------------------------------- 4929// 1.4.3 BasicGLSLConst 4930//----------------------------------------------------------------------------- 4931class BasicGLSLConst : public ShaderImageLoadStoreBase 4932{ 4933 GLuint m_program; 4934 GLuint m_vao, m_vbo; 4935 4936 virtual long Setup() 4937 { 4938 m_program = 0; 4939 m_vao = m_vbo = 0; 4940 return NO_ERROR; 4941 } 4942 4943 virtual long Run() 4944 { 4945 bool isAtLeast44Context = 4946 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4)); 4947 4948 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 4949 " gl_Position = i_position;" NL "}"; 4950 std::ostringstream src_fs; 4951 src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core"; 4952 src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL 4953 "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL 4954 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL 4955 "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL 4956 "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL 4957 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 4958 " if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);"; 4959 if (isAtLeast44Context) 4960 src_fs << NL " if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = " 4961 "vec4(0.2, 0.0, 0.0, 0.2);"; 4962 else 4963 src_fs << NL " if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) " 4964 "o_color = vec4(0.2, 0.0, 0.0, 0.2);"; 4965 src_fs << NL 4966 " if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL 4967 " if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL 4968 " if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, " 4969 "0.5);" NL " if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, " 4970 "0.0, 0.0, 0.6);" NL 4971 " if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL 4972 " if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL 4973 " if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}"; 4974 4975 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str()); 4976 glUseProgram(m_program); 4977 4978 GLint i; 4979 glGetIntegerv(GL_MAX_IMAGE_UNITS, &i); 4980 glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i); 4981 4982 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i); 4983 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i); 4984 4985 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i); 4986 glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i); 4987 4988 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i); 4989 glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i); 4990 4991 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i); 4992 glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i); 4993 4994 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i); 4995 glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i); 4996 4997 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i); 4998 glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i); 4999 5000 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i); 5001 glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i); 5002 5003 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i); 5004 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i); 5005 5006 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 5007 5008 glClear(GL_COLOR_BUFFER_BIT); 5009 glBindVertexArray(m_vao); 5010 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5011 5012 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 5013 { 5014 return ERROR; 5015 } 5016 return NO_ERROR; 5017 } 5018 5019 virtual long Cleanup() 5020 { 5021 glDeleteVertexArrays(1, &m_vao); 5022 glDeleteBuffers(1, &m_vbo); 5023 glUseProgram(0); 5024 glDeleteProgram(m_program); 5025 return NO_ERROR; 5026 } 5027}; 5028//----------------------------------------------------------------------------- 5029// 2.1.1 AdvancedSyncImageAccess 5030//----------------------------------------------------------------------------- 5031class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase 5032{ 5033 GLuint m_buffer; 5034 GLuint m_buffer_tex; 5035 GLuint m_store_program; 5036 GLuint m_draw_program; 5037 GLuint m_attribless_vao; 5038 5039 virtual long Setup() 5040 { 5041 m_buffer = 0; 5042 m_buffer_tex = 0; 5043 m_store_program = 0; 5044 m_draw_program = 0; 5045 m_attribless_vao = 0; 5046 return NO_ERROR; 5047 } 5048 5049 virtual long Run() 5050 { 5051 if (!SupportedInVS(1)) 5052 return NOT_SUPPORTED; 5053 const char* const glsl_store_vs = 5054 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL 5055 " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL 5056 " imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}"; 5057 const char* const glsl_draw_vs = 5058 "#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL 5059 "uniform samplerBuffer g_sampler;" NL "void main() {" NL " vec4 pi = imageLoad(g_image, gl_VertexID);" NL 5060 " vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL 5061 " if (pi != ps) vs_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " else vs_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 5062 " gl_Position = pi;" NL "}"; 5063 const char* const glsl_draw_fs = 5064 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL 5065 " o_color = vs_color;" NL "}"; 5066 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL); 5067 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs); 5068 5069 glGenVertexArrays(1, &m_attribless_vao); 5070 glBindVertexArray(m_attribless_vao); 5071 5072 glGenBuffers(1, &m_buffer); 5073 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5074 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW); 5075 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5076 5077 glGenTextures(1, &m_buffer_tex); 5078 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex); 5079 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer); 5080 5081 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F); 5082 5083 glEnable(GL_RASTERIZER_DISCARD); 5084 glUseProgram(m_store_program); 5085 glDrawArrays(GL_POINTS, 0, 4); 5086 5087 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT); 5088 5089 glDisable(GL_RASTERIZER_DISCARD); 5090 glClear(GL_COLOR_BUFFER_BIT); 5091 glUseProgram(m_draw_program); 5092 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5093 5094 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 5095 { 5096 return ERROR; 5097 } 5098 return NO_ERROR; 5099 } 5100 5101 virtual long Cleanup() 5102 { 5103 glUseProgram(0); 5104 glDeleteBuffers(1, &m_buffer); 5105 glDeleteTextures(1, &m_buffer_tex); 5106 glDeleteProgram(m_store_program); 5107 glDeleteProgram(m_draw_program); 5108 glDeleteVertexArrays(1, &m_attribless_vao); 5109 return NO_ERROR; 5110 } 5111}; 5112//----------------------------------------------------------------------------- 5113// 2.1.2 AdvancedSyncVertexArray 5114//----------------------------------------------------------------------------- 5115class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase 5116{ 5117 GLuint m_position_buffer; 5118 GLuint m_color_buffer; 5119 GLuint m_element_buffer; 5120 GLuint m_position_buffer_tex; 5121 GLuint m_color_buffer_tex; 5122 GLuint m_element_buffer_tex; 5123 GLuint m_store_program; 5124 GLuint m_draw_program; 5125 GLuint m_attribless_vao; 5126 GLuint m_draw_vao; 5127 5128 virtual long Setup() 5129 { 5130 m_position_buffer = 0; 5131 m_color_buffer = 0; 5132 m_element_buffer = 0; 5133 m_position_buffer_tex = 0; 5134 m_color_buffer_tex = 0; 5135 m_element_buffer_tex = 0; 5136 m_store_program = 0; 5137 m_draw_program = 0; 5138 m_attribless_vao = 0; 5139 m_draw_vao = 0; 5140 return NO_ERROR; 5141 } 5142 5143 virtual long Run() 5144 { 5145 if (!SupportedInVS(3)) 5146 return NOT_SUPPORTED; 5147 const char* const glsl_store_vs = 5148 "#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL 5149 "layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL 5150 "layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL 5151 "void main() {" NL " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL 5152 " imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL 5153 " imageStore(g_color_buffer, gl_VertexID, g_color);" NL 5154 " imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}"; 5155 const char* const glsl_draw_vs = 5156 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 5157 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL 5158 " gl_Position = i_position;" NL " vs_color = i_color;" NL "}"; 5159 const char* const glsl_draw_fs = 5160 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL 5161 " o_color = vs_color;" NL "}"; 5162 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL); 5163 glUseProgram(m_store_program); 5164 glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0); 5165 glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1); 5166 glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2); 5167 glUseProgram(0); 5168 5169 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs); 5170 5171 glGenBuffers(1, &m_position_buffer); 5172 glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer); 5173 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW); 5174 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5175 5176 glGenBuffers(1, &m_color_buffer); 5177 glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer); 5178 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW); 5179 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5180 5181 glGenBuffers(1, &m_element_buffer); 5182 glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer); 5183 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW); 5184 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5185 5186 glGenTextures(1, &m_position_buffer_tex); 5187 glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex); 5188 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer); 5189 glBindTexture(GL_TEXTURE_BUFFER, 0); 5190 5191 glGenTextures(1, &m_color_buffer_tex); 5192 glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex); 5193 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer); 5194 glBindTexture(GL_TEXTURE_BUFFER, 0); 5195 5196 glGenTextures(1, &m_element_buffer_tex); 5197 glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex); 5198 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer); 5199 glBindTexture(GL_TEXTURE_BUFFER, 0); 5200 5201 glGenVertexArrays(1, &m_attribless_vao); 5202 5203 glGenVertexArrays(1, &m_draw_vao); 5204 glBindVertexArray(m_draw_vao); 5205 glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer); 5206 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); 5207 glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer); 5208 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); 5209 glBindBuffer(GL_ARRAY_BUFFER, 0); 5210 glEnableVertexAttribArray(0); 5211 glEnableVertexAttribArray(1); 5212 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer); 5213 glBindVertexArray(0); 5214 5215 glEnable(GL_RASTERIZER_DISCARD); 5216 glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F); 5217 glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 5218 glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI); 5219 glUseProgram(m_store_program); 5220 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f); 5221 glBindVertexArray(m_attribless_vao); 5222 glDrawArrays(GL_POINTS, 0, 4); 5223 5224 glDisable(GL_RASTERIZER_DISCARD); 5225 glClear(GL_COLOR_BUFFER_BIT); 5226 glUseProgram(m_draw_program); 5227 glBindVertexArray(m_draw_vao); 5228 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT); 5229 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0); 5230 5231 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 5232 { 5233 return ERROR; 5234 } 5235 5236 glEnable(GL_RASTERIZER_DISCARD); 5237 glUseProgram(m_store_program); 5238 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f); 5239 glBindVertexArray(m_attribless_vao); 5240 glDrawArrays(GL_POINTS, 0, 4); 5241 5242 glDisable(GL_RASTERIZER_DISCARD); 5243 glClear(GL_COLOR_BUFFER_BIT); 5244 glUseProgram(m_draw_program); 5245 glBindVertexArray(m_draw_vao); 5246 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT); 5247 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0); 5248 5249 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1))) 5250 { 5251 return ERROR; 5252 } 5253 return NO_ERROR; 5254 } 5255 5256 virtual long Cleanup() 5257 { 5258 glDisable(GL_RASTERIZER_DISCARD); 5259 glUseProgram(0); 5260 glDeleteBuffers(1, &m_position_buffer); 5261 glDeleteBuffers(1, &m_color_buffer); 5262 glDeleteBuffers(1, &m_element_buffer); 5263 glDeleteTextures(1, &m_position_buffer_tex); 5264 glDeleteTextures(1, &m_color_buffer_tex); 5265 glDeleteTextures(1, &m_element_buffer_tex); 5266 glDeleteProgram(m_store_program); 5267 glDeleteProgram(m_draw_program); 5268 glDeleteVertexArrays(1, &m_attribless_vao); 5269 glDeleteVertexArrays(1, &m_draw_vao); 5270 return NO_ERROR; 5271 } 5272}; 5273 5274//----------------------------------------------------------------------------- 5275// 2.1.4 AdvancedSyncDrawIndirect 5276//----------------------------------------------------------------------------- 5277class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase 5278{ 5279 GLuint m_draw_command_buffer; 5280 GLuint m_draw_command_buffer_tex; 5281 GLuint m_store_program; 5282 GLuint m_draw_program; 5283 GLuint m_attribless_vao; 5284 GLuint m_draw_vao; 5285 GLuint m_draw_vbo; 5286 5287 virtual long Setup() 5288 { 5289 m_draw_command_buffer = 0; 5290 m_draw_command_buffer_tex = 0; 5291 m_store_program = 0; 5292 m_draw_program = 0; 5293 m_attribless_vao = 0; 5294 m_draw_vao = 0; 5295 m_draw_vbo = 0; 5296 return NO_ERROR; 5297 } 5298 5299 virtual long Run() 5300 { 5301 if (!SupportedInVS(1)) 5302 return NOT_SUPPORTED; 5303 const char* const glsl_store_vs = 5304 "#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL 5305 " imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}"; 5306 const char* const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 5307 "void main() {" NL " gl_Position = i_position;" NL "}"; 5308 const char* const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 5309 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}"; 5310 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL); 5311 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs); 5312 5313 glGenBuffers(1, &m_draw_command_buffer); 5314 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer); 5315 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW); 5316 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); 5317 5318 glGenTextures(1, &m_draw_command_buffer_tex); 5319 glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex); 5320 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer); 5321 glBindTexture(GL_TEXTURE_BUFFER, 0); 5322 5323 glGenVertexArrays(1, &m_attribless_vao); 5324 CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL); 5325 5326 glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); 5327 5328 glEnable(GL_RASTERIZER_DISCARD); 5329 glUseProgram(m_store_program); 5330 glBindVertexArray(m_attribless_vao); 5331 glDrawArrays(GL_POINTS, 0, 1); 5332 5333 glDisable(GL_RASTERIZER_DISCARD); 5334 glClear(GL_COLOR_BUFFER_BIT); 5335 glUseProgram(m_draw_program); 5336 glBindVertexArray(m_draw_vao); 5337 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer); 5338 glMemoryBarrier(GL_COMMAND_BARRIER_BIT); 5339 glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0); 5340 5341 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 5342 { 5343 return ERROR; 5344 } 5345 return NO_ERROR; 5346 } 5347 5348 virtual long Cleanup() 5349 { 5350 glUseProgram(0); 5351 glDeleteBuffers(1, &m_draw_command_buffer); 5352 glDeleteTextures(1, &m_draw_command_buffer_tex); 5353 glDeleteProgram(m_store_program); 5354 glDeleteProgram(m_draw_program); 5355 glDeleteVertexArrays(1, &m_attribless_vao); 5356 glDeleteVertexArrays(1, &m_draw_vao); 5357 glDeleteBuffers(1, &m_draw_vbo); 5358 return NO_ERROR; 5359 } 5360}; 5361//----------------------------------------------------------------------------- 5362// 2.1.5 AdvancedSyncTextureUpdate 5363//----------------------------------------------------------------------------- 5364class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase 5365{ 5366 GLuint m_texture; 5367 GLuint m_store_program; 5368 GLuint m_draw_program; 5369 GLuint m_vao; 5370 GLuint m_vbo; 5371 GLuint m_pbo; 5372 5373 virtual long Setup() 5374 { 5375 m_texture = 0; 5376 m_store_program = 0; 5377 m_draw_program = 0; 5378 m_vao = 0; 5379 m_vbo = 0; 5380 m_pbo = 0; 5381 return NO_ERROR; 5382 } 5383 5384 virtual long Run() 5385 { 5386 const char* const glsl_vs = 5387 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL 5388 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}"; 5389 const char* const glsl_store_fs = 5390 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL 5391 " imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL " discard;" NL "}"; 5392 const char* const glsl_draw_fs = 5393 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL 5394 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}"; 5395 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs); 5396 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs); 5397 5398 std::vector<vec4> data(16 * 16, vec4(1.0f)); 5399 glGenBuffers(1, &m_pbo); 5400 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo); 5401 glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ); 5402 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 5403 5404 glGenTextures(1, &m_texture); 5405 glBindTexture(GL_TEXTURE_2D, m_texture); 5406 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 5407 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL); 5408 glBindTexture(GL_TEXTURE_2D, 0); 5409 5410 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 5411 5412 glViewport(0, 0, 16, 16); 5413 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 5414 glUseProgram(m_store_program); 5415 glBindVertexArray(m_vao); 5416 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5417 5418 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo); 5419 glBindTexture(GL_TEXTURE_2D, m_texture); 5420 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 5421 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0); 5422 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 5423 5424 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 5425 glClear(GL_COLOR_BUFFER_BIT); 5426 glUseProgram(m_draw_program); 5427 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5428 5429 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1))) 5430 { 5431 return ERROR; 5432 } 5433 return NO_ERROR; 5434 } 5435 5436 virtual long Cleanup() 5437 { 5438 glUseProgram(0); 5439 glDeleteBuffers(1, &m_vbo); 5440 glDeleteBuffers(1, &m_pbo); 5441 glDeleteTextures(1, &m_texture); 5442 glDeleteProgram(m_store_program); 5443 glDeleteProgram(m_draw_program); 5444 glDeleteVertexArrays(1, &m_vao); 5445 return NO_ERROR; 5446 } 5447}; 5448//----------------------------------------------------------------------------- 5449// 2.1.6 AdvancedSyncImageAccess2 5450//----------------------------------------------------------------------------- 5451class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase 5452{ 5453 GLuint m_texture; 5454 GLuint m_store_program; 5455 GLuint m_draw_program; 5456 GLuint m_vao; 5457 GLuint m_vbo; 5458 5459 virtual long Setup() 5460 { 5461 m_texture = 0; 5462 m_store_program = 0; 5463 m_draw_program = 0; 5464 m_vao = 0; 5465 m_vbo = 0; 5466 return NO_ERROR; 5467 } 5468 5469 virtual long Run() 5470 { 5471 const char* const glsl_vs = 5472 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL 5473 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}"; 5474 const char* const glsl_store_fs = 5475 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL 5476 " imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL " discard;" NL "}"; 5477 const char* const glsl_draw_fs = 5478 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL 5479 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}"; 5480 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs); 5481 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs); 5482 5483 glGenTextures(1, &m_texture); 5484 glBindTexture(GL_TEXTURE_2D, m_texture); 5485 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 5486 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_FLOAT, NULL); 5487 glBindTexture(GL_TEXTURE_2D, 0); 5488 5489 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 5490 5491 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 5492 glUseProgram(m_store_program); 5493 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f); 5494 glBindVertexArray(m_vao); 5495 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5496 5497 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 5498 5499 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f); 5500 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5501 5502 glClear(GL_COLOR_BUFFER_BIT); 5503 glBindTexture(GL_TEXTURE_2D, m_texture); 5504 glUseProgram(m_draw_program); 5505 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5506 5507 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 5508 { 5509 return ERROR; 5510 } 5511 return NO_ERROR; 5512 } 5513 5514 virtual long Cleanup() 5515 { 5516 glUseProgram(0); 5517 glDeleteBuffers(1, &m_vbo); 5518 glDeleteTextures(1, &m_texture); 5519 glDeleteProgram(m_store_program); 5520 glDeleteProgram(m_draw_program); 5521 glDeleteVertexArrays(1, &m_vao); 5522 return NO_ERROR; 5523 } 5524}; 5525//----------------------------------------------------------------------------- 5526// 2.1.7 AdvancedSyncBufferUpdate 5527//----------------------------------------------------------------------------- 5528class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase 5529{ 5530 GLuint m_buffer; 5531 GLuint m_buffer_tex; 5532 GLuint m_store_program; 5533 GLuint m_attribless_vao; 5534 5535 virtual long Setup() 5536 { 5537 m_buffer = 0; 5538 m_buffer_tex = 0; 5539 m_store_program = 0; 5540 m_attribless_vao = 0; 5541 return NO_ERROR; 5542 } 5543 5544 virtual long Run() 5545 { 5546 if (!SupportedInVS(1)) 5547 return NOT_SUPPORTED; 5548 const char* const glsl_store_vs = 5549 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL 5550 " imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}"; 5551 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL); 5552 5553 glGenVertexArrays(1, &m_attribless_vao); 5554 glBindVertexArray(m_attribless_vao); 5555 5556 glGenBuffers(1, &m_buffer); 5557 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5558 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW); 5559 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5560 5561 glGenTextures(1, &m_buffer_tex); 5562 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex); 5563 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer); 5564 5565 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 5566 5567 glEnable(GL_RASTERIZER_DISCARD); 5568 glUseProgram(m_store_program); 5569 glDrawArrays(GL_POINTS, 0, 1000); 5570 5571 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 5572 5573 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5574 vec4* ptr = 5575 reinterpret_cast<vec4*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT)); 5576 for (int i = 0; i < 1000; ++i) 5577 { 5578 if (!IsEqual(ptr[i], vec4(static_cast<float>(i)))) 5579 { 5580 m_context.getTestContext().getLog() 5581 << tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage; 5582 return ERROR; 5583 } 5584 } 5585 return NO_ERROR; 5586 } 5587 5588 virtual long Cleanup() 5589 { 5590 glDisable(GL_RASTERIZER_DISCARD); 5591 glUseProgram(0); 5592 glDeleteBuffers(1, &m_buffer); 5593 glDeleteTextures(1, &m_buffer_tex); 5594 glDeleteProgram(m_store_program); 5595 glDeleteVertexArrays(1, &m_attribless_vao); 5596 return NO_ERROR; 5597 } 5598}; 5599//----------------------------------------------------------------------------- 5600// 2.2.1 AdvancedAllStagesOneImage 5601//----------------------------------------------------------------------------- 5602class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase 5603{ 5604 GLuint m_program; 5605 GLuint m_vao; 5606 GLuint m_vbo; 5607 GLuint m_ebo; 5608 GLuint m_buffer; 5609 GLuint m_buffer_tex; 5610 GLuint m_texture; 5611 5612 virtual long Setup() 5613 { 5614 m_program = 0; 5615 m_vao = 0; 5616 m_vbo = 0; 5617 m_ebo = 0; 5618 m_buffer = 0; 5619 m_buffer_tex = 0; 5620 m_texture = 0; 5621 return NO_ERROR; 5622 } 5623 5624 virtual long Run() 5625 { 5626 if (!SupportedInGeomStages(2)) 5627 return NOT_SUPPORTED; 5628 const char* const glsl_vs = 5629 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 5630 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL 5631 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL 5632 " gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL " imageAtomicAdd(g_buffer, 0, 1);" NL 5633 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}"; 5634 const char* const glsl_tcs = 5635 "#version 420 core" NL "layout(vertices = 1) out;" NL 5636 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL 5637 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL 5638 " gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL " gl_TessLevelInner[0] = 1.0;" NL 5639 " gl_TessLevelInner[1] = 1.0;" NL " gl_TessLevelOuter[0] = 1.0;" NL " gl_TessLevelOuter[1] = 1.0;" NL 5640 " gl_TessLevelOuter[2] = 1.0;" NL " gl_TessLevelOuter[3] = 1.0;" NL " imageAtomicAdd(g_buffer, 0, 1);" NL 5641 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}"; 5642 const char* const glsl_tes = 5643 "#version 420 core" NL "layout(triangles, point_mode) in;" NL 5644 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL 5645 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL 5646 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL 5647 " gl_Position = gl_in[0].gl_Position;" NL "}"; 5648 const char* const glsl_gs = 5649 "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL 5650 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL 5651 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL 5652 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL 5653 " gl_Position = gl_in[0].gl_Position;" NL " EmitVertex();" NL "}"; 5654 const char* const glsl_fs = 5655 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 5656 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL 5657 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL 5658 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL 5659 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}"; 5660 m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs); 5661 glUseProgram(m_program); 5662 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0); 5663 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1); 5664 5665 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 5666 5667 GLint i32 = 0; 5668 glGenBuffers(1, &m_buffer); 5669 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5670 glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW); 5671 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5672 5673 glGenTextures(1, &m_buffer_tex); 5674 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex); 5675 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer); 5676 glBindTexture(GL_TEXTURE_BUFFER, 0); 5677 5678 GLuint ui32 = 0; 5679 glGenTextures(1, &m_texture); 5680 glBindTexture(GL_TEXTURE_2D, m_texture); 5681 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 5682 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 5683 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32); 5684 glBindTexture(GL_TEXTURE_2D, 0); 5685 5686 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I); 5687 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); 5688 5689 glBindVertexArray(m_vao); 5690 glPatchParameteri(GL_PATCH_VERTICES, 1); 5691 5692 glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0); 5693 glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1); 5694 5695 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 5696 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5697 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32); 5698 if (i32 < 20 || i32 > 50) 5699 { 5700 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32 5701 << " should be in the range [20;50]" << tcu::TestLog::EndMessage; 5702 return ERROR; 5703 } 5704 5705 glBindTexture(GL_TEXTURE_2D, m_texture); 5706 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32); 5707 if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32)) 5708 { 5709 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be " 5710 << (2 * i32) << tcu::TestLog::EndMessage; 5711 return ERROR; 5712 } 5713 5714 return NO_ERROR; 5715 } 5716 5717 virtual long Cleanup() 5718 { 5719 glPatchParameteri(GL_PATCH_VERTICES, 3); 5720 glUseProgram(0); 5721 glDeleteBuffers(1, &m_buffer); 5722 glDeleteBuffers(1, &m_vbo); 5723 glDeleteBuffers(1, &m_ebo); 5724 glDeleteTextures(1, &m_buffer_tex); 5725 glDeleteTextures(1, &m_texture); 5726 glDeleteProgram(m_program); 5727 glDeleteVertexArrays(1, &m_vao); 5728 return NO_ERROR; 5729 } 5730}; 5731//----------------------------------------------------------------------------- 5732// 2.3.1 AdvancedMemoryDependentInvocation 5733//----------------------------------------------------------------------------- 5734class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase 5735{ 5736 GLuint m_buffer; 5737 GLuint m_buffer_tex; 5738 GLuint m_texture; 5739 GLuint m_program; 5740 GLuint m_vao; 5741 GLuint m_vbo; 5742 5743 virtual long Setup() 5744 { 5745 m_buffer = 0; 5746 m_buffer_tex = 0; 5747 m_texture = 0; 5748 m_program = 0; 5749 m_vao = 0; 5750 m_vbo = 0; 5751 return NO_ERROR; 5752 } 5753 5754 virtual long Run() 5755 { 5756 if (!SupportedInVS(2)) 5757 return NOT_SUPPORTED; 5758 const char* const glsl_vs = 5759 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 5760 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL 5761 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL 5762 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " gl_Position = i_position;" NL 5763 " vs_color = i_color;" NL " imageStore(g_buffer, 0, vec4(1.0));" NL 5764 " imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL " memoryBarrier();" NL "}"; 5765 const char* const glsl_fs = 5766 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL 5767 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL 5768 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL 5769 " if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL 5770 " if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}"; 5771 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 5772 glUseProgram(m_program); 5773 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0); 5774 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1); 5775 5776 vec4 zero(0); 5777 glGenBuffers(1, &m_buffer); 5778 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5779 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW); 5780 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5781 5782 glGenTextures(1, &m_buffer_tex); 5783 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex); 5784 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer); 5785 glBindTexture(GL_TEXTURE_BUFFER, 0); 5786 5787 glGenTextures(1, &m_texture); 5788 glBindTexture(GL_TEXTURE_2D, m_texture); 5789 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 5790 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero); 5791 glBindTexture(GL_TEXTURE_2D, 0); 5792 5793 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 5794 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 5795 5796 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 5797 5798 glClear(GL_COLOR_BUFFER_BIT); 5799 glBindVertexArray(m_vao); 5800 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0); 5801 5802 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 5803 { 5804 return ERROR; 5805 } 5806 return NO_ERROR; 5807 } 5808 5809 virtual long Cleanup() 5810 { 5811 glUseProgram(0); 5812 glDeleteBuffers(1, &m_vbo); 5813 glDeleteBuffers(1, &m_buffer); 5814 glDeleteTextures(1, &m_texture); 5815 glDeleteTextures(1, &m_buffer_tex); 5816 glDeleteProgram(m_program); 5817 glDeleteVertexArrays(1, &m_vao); 5818 return NO_ERROR; 5819 } 5820}; 5821//----------------------------------------------------------------------------- 5822// 2.3.2 AdvancedMemoryOrder 5823//----------------------------------------------------------------------------- 5824class AdvancedMemoryOrder : public ShaderImageLoadStoreBase 5825{ 5826 GLuint m_buffer; 5827 GLuint m_buffer_tex; 5828 GLuint m_texture; 5829 GLuint m_program; 5830 GLuint m_vao; 5831 GLuint m_vbo; 5832 5833 virtual long Setup() 5834 { 5835 m_buffer = 0; 5836 m_buffer_tex = 0; 5837 m_texture = 0; 5838 m_program = 0; 5839 m_vao = 0; 5840 m_vbo = 0; 5841 return NO_ERROR; 5842 } 5843 5844 virtual long Run() 5845 { 5846 if (!SupportedInVS(1)) 5847 return NOT_SUPPORTED; 5848 const char* const glsl_vs = 5849 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL 5850 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL 5851 " gl_Position = i_position;" NL " vs_color = vec4(0, 1, 0, 1);" NL 5852 " imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL " imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL 5853 " imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL 5854 " if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}"; 5855 const char* const glsl_fs = 5856 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL 5857 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL 5858 " ivec2 coord = ivec2(gl_FragCoord);" NL " for (int i = 0; i < 3; ++i) {" NL 5859 " imageStore(g_image, coord, vec4(i));" NL " vec4 v = imageLoad(g_image, coord);" NL 5860 " if (v != vec4(i)) {" NL " o_color = vec4(v.xyz, 0.0);" NL " break;" NL " }" NL " }" NL 5861 "}"; 5862 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 5863 glUseProgram(m_program); 5864 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0); 5865 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1); 5866 5867 glGenBuffers(1, &m_buffer); 5868 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5869 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW); 5870 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5871 5872 glGenTextures(1, &m_buffer_tex); 5873 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex); 5874 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer); 5875 glBindTexture(GL_TEXTURE_BUFFER, 0); 5876 5877 std::vector<vec4> data(getWindowWidth() * getWindowHeight()); 5878 glGenTextures(1, &m_texture); 5879 glBindTexture(GL_TEXTURE_2D, m_texture); 5880 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 5881 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_FLOAT, &data[0]); 5882 glBindTexture(GL_TEXTURE_2D, 0); 5883 5884 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 5885 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 5886 5887 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 5888 5889 glClear(GL_COLOR_BUFFER_BIT); 5890 glBindVertexArray(m_vao); 5891 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0); 5892 5893 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 5894 { 5895 return ERROR; 5896 } 5897 return NO_ERROR; 5898 } 5899 5900 virtual long Cleanup() 5901 { 5902 glUseProgram(0); 5903 glDeleteBuffers(1, &m_vbo); 5904 glDeleteBuffers(1, &m_buffer); 5905 glDeleteTextures(1, &m_texture); 5906 glDeleteTextures(1, &m_buffer_tex); 5907 glDeleteProgram(m_program); 5908 glDeleteVertexArrays(1, &m_vao); 5909 return NO_ERROR; 5910 } 5911}; 5912//----------------------------------------------------------------------------- 5913// 2.4.1 AdvancedSSOSimple 5914//----------------------------------------------------------------------------- 5915class AdvancedSSOSimple : public ShaderImageLoadStoreBase 5916{ 5917 GLuint m_texture; 5918 GLuint m_pipeline[2]; 5919 GLuint m_vsp, m_fsp0, m_fsp1; 5920 GLuint m_vao, m_vbo; 5921 5922 virtual long Setup() 5923 { 5924 glGenTextures(1, &m_texture); 5925 glGenProgramPipelines(2, m_pipeline); 5926 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 5927 5928 const char* const glsl_vs = 5929 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL 5930 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 5931 const char* const glsl_fs0 = 5932 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL 5933 " for (int i = 0; i < g_image.length(); ++i) {" NL 5934 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL " }" NL " discard;" NL "}"; 5935 const char* const glsl_fs1 = 5936 "#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL 5937 " for (int i = 0; i < g_image.length(); ++i) {" NL 5938 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL " }" NL " discard;" NL "}"; 5939 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs); 5940 m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0); 5941 m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1); 5942 5943 return NO_ERROR; 5944 } 5945 5946 virtual long Run() 5947 { 5948 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0); 5949 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2); 5950 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4); 5951 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6); 5952 5953 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1); 5954 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3); 5955 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5); 5956 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7); 5957 5958 glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp); 5959 glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0); 5960 5961 glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp); 5962 glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1); 5963 5964 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 5965 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 5966 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 8, 0, GL_RGBA, GL_FLOAT, 5967 NULL); 5968 5969 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 5970 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F); 5971 glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F); 5972 glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F); 5973 glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F); 5974 glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F); 5975 glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F); 5976 glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F); 5977 5978 glBindVertexArray(m_vao); 5979 5980 glBindProgramPipeline(m_pipeline[0]); 5981 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0); 5982 5983 glBindProgramPipeline(m_pipeline[1]); 5984 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5985 5986 std::vector<vec4> data(getWindowWidth() * getWindowHeight() * 8); 5987 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]); 5988 5989 for (int layer = 0; layer < 8; ++layer) 5990 { 5991 for (int h = 0; h < getWindowHeight(); ++h) 5992 { 5993 for (int w = 0; w < getWindowWidth(); ++w) 5994 { 5995 const vec4 c = data[layer * getWindowWidth() * getWindowHeight() + h * getWindowWidth() + w]; 5996 if (layer % 2) 5997 { 5998 if (!IsEqual(c, vec4(2.0f))) 5999 { 6000 return ERROR; 6001 } 6002 } 6003 else 6004 { 6005 if (!IsEqual(c, vec4(1.0f))) 6006 { 6007 return ERROR; 6008 } 6009 } 6010 } 6011 } 6012 } 6013 return NO_ERROR; 6014 } 6015 6016 virtual long Cleanup() 6017 { 6018 glDeleteBuffers(1, &m_vbo); 6019 glDeleteTextures(1, &m_texture); 6020 glDeleteProgram(m_vsp); 6021 glDeleteProgram(m_fsp0); 6022 glDeleteProgram(m_fsp1); 6023 glDeleteVertexArrays(1, &m_vao); 6024 glDeleteProgramPipelines(2, m_pipeline); 6025 return NO_ERROR; 6026 } 6027}; 6028//----------------------------------------------------------------------------- 6029// 2.4.2 AdvancedSSOAtomicCounters 6030//----------------------------------------------------------------------------- 6031class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase 6032{ 6033 GLuint m_buffer, m_buffer_tex; 6034 GLuint m_counter_buffer; 6035 GLuint m_transform_buffer; 6036 GLuint m_pipeline; 6037 GLuint m_vao, m_vbo; 6038 GLuint m_vsp, m_fsp; 6039 6040 virtual long Setup() 6041 { 6042 m_vao = 0; 6043 m_vbo = 0; 6044 m_vsp = 0; 6045 m_fsp = 0; 6046 glGenBuffers(1, &m_buffer); 6047 glGenTextures(1, &m_buffer_tex); 6048 glGenBuffers(1, &m_counter_buffer); 6049 glGenBuffers(1, &m_transform_buffer); 6050 glGenProgramPipelines(1, &m_pipeline); 6051 return NO_ERROR; 6052 } 6053 6054 virtual long Run() 6055 { 6056 if (!SupportedInVS(1)) 6057 return NOT_SUPPORTED; 6058 6059 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 6060 const char* const glsl_vs = 6061 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 6062 "layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL 6063 "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL 6064 " mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL 6065 "layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL 6066 " gl_Position = g_transform.mvp * i_position;" NL " o_color = i_color;" NL 6067 " const uint index = atomicCounterIncrement(g_counter);" NL 6068 " imageStore(g_buffer, int(index), gl_Position);" NL "}"; 6069 const char* const glsl_fs = 6070 "#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL 6071 "layout(location = 0) out vec4 o_color;" NL "void main() {" NL " o_color = i_color;" NL "}"; 6072 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs); 6073 m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs); 6074 6075 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp); 6076 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp); 6077 6078 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 6079 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW); 6080 6081 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex); 6082 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer); 6083 6084 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer); 6085 vec4 zero(0); 6086 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW); 6087 6088 glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer); 6089 mat4 identity(1); 6090 glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW); 6091 6092 glClear(GL_COLOR_BUFFER_BIT); 6093 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer); 6094 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer); 6095 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6096 glBindVertexArray(m_vao); 6097 glBindProgramPipeline(m_pipeline); 6098 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0); 6099 6100 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 6101 { 6102 return ERROR; 6103 } 6104 6105 std::vector<vec4> data(4); 6106 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 6107 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]); 6108 6109 for (int i = 0; i < 4; ++i) 6110 { 6111 if (!IsEqual(data[i], vec4(-1.0f, -1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, -1.0f, 0.0f, 1.0f)) && 6112 !IsEqual(data[i], vec4(-1.0f, 1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, 1.0f, 0.0f, 1.0f))) 6113 { 6114 return ERROR; 6115 } 6116 } 6117 6118 return NO_ERROR; 6119 } 6120 6121 virtual long Cleanup() 6122 { 6123 glDeleteBuffers(1, &m_buffer); 6124 glDeleteBuffers(1, &m_vbo); 6125 glDeleteBuffers(1, &m_counter_buffer); 6126 glDeleteBuffers(1, &m_transform_buffer); 6127 glDeleteTextures(1, &m_buffer_tex); 6128 glDeleteProgram(m_vsp); 6129 glDeleteProgram(m_fsp); 6130 glDeleteVertexArrays(1, &m_vao); 6131 glDeleteProgramPipelines(1, &m_pipeline); 6132 return NO_ERROR; 6133 } 6134}; 6135//----------------------------------------------------------------------------- 6136// 2.4.3 AdvancedSSOSubroutine 6137//----------------------------------------------------------------------------- 6138class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase 6139{ 6140 GLuint m_texture; 6141 GLuint m_attribless_vao; 6142 GLuint m_program; 6143 GLint m_draw_buffer; 6144 6145 virtual long Setup() 6146 { 6147 glGenTextures(1, &m_texture); 6148 glGenVertexArrays(1, &m_attribless_vao); 6149 6150 const char* const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL 6151 "const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL 6152 "void main() {" NL " gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}"; 6153 const char* const glsl_fs = 6154 "#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL 6155 "writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL 6156 "subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL 6157 " imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL 6158 " imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL 6159 " imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL 6160 "subroutine(Brush) void Brush1(ivec2 coord) {" NL 6161 " imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL 6162 " imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL 6163 " imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL 6164 " g_brush(ivec2(gl_FragCoord));" NL "}"; 6165 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 6166 6167 return NO_ERROR; 6168 } 6169 6170 virtual long Run() 6171 { 6172 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1); 6173 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1); 6174 6175 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 6176 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 6177 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 3, 0, GL_RGBA, GL_FLOAT, 6178 NULL); 6179 6180 glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer); 6181 6182 glDrawBuffer(GL_NONE); 6183 glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F); 6184 glUseProgram(m_program); 6185 glBindVertexArray(m_attribless_vao); 6186 6187 const GLuint indices[2] = { glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"), 6188 glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1") }; 6189 6190 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]); 6191 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0); 6192 6193 std::vector<vec4> data(getWindowWidth() * getWindowHeight() * 3); 6194 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 6195 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]); 6196 6197 for (int layer = 0; layer < 3; ++layer) 6198 { 6199 for (int h = 0; h < getWindowHeight(); ++h) 6200 { 6201 for (int w = 0; w < getWindowWidth(); ++w) 6202 { 6203 const vec4 c = data[layer * getWindowWidth() * getWindowHeight() + h * getWindowWidth() + w]; 6204 if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f))) 6205 { 6206 m_context.getTestContext().getLog() 6207 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6208 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage; 6209 return ERROR; 6210 } 6211 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f))) 6212 { 6213 m_context.getTestContext().getLog() 6214 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6215 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage; 6216 return ERROR; 6217 } 6218 else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f))) 6219 { 6220 m_context.getTestContext().getLog() 6221 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6222 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage; 6223 return ERROR; 6224 } 6225 } 6226 } 6227 } 6228 6229 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]); 6230 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0); 6231 6232 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 6233 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]); 6234 6235 for (int layer = 0; layer < 3; ++layer) 6236 { 6237 for (int h = 0; h < getWindowHeight(); ++h) 6238 { 6239 for (int w = 0; w < getWindowWidth(); ++w) 6240 { 6241 const vec4 c = data[layer * getWindowWidth() * getWindowHeight() + h * getWindowWidth() + w]; 6242 if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f))) 6243 { 6244 m_context.getTestContext().getLog() 6245 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6246 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage; 6247 return ERROR; 6248 } 6249 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f))) 6250 { 6251 m_context.getTestContext().getLog() 6252 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6253 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage; 6254 return ERROR; 6255 } 6256 else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f))) 6257 { 6258 m_context.getTestContext().getLog() 6259 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6260 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage; 6261 return ERROR; 6262 } 6263 } 6264 } 6265 } 6266 return NO_ERROR; 6267 } 6268 6269 virtual long Cleanup() 6270 { 6271 glDrawBuffer(m_draw_buffer); 6272 glDeleteTextures(1, &m_texture); 6273 glUseProgram(0); 6274 glDeleteProgram(m_program); 6275 glDeleteVertexArrays(1, &m_attribless_vao); 6276 return NO_ERROR; 6277 } 6278}; 6279//----------------------------------------------------------------------------- 6280// 2.4.4 AdvancedSSOPerSample 6281//----------------------------------------------------------------------------- 6282class AdvancedSSOPerSample : public ShaderImageLoadStoreBase 6283{ 6284 GLuint m_texture; 6285 GLuint m_pipeline; 6286 GLuint m_vao, m_vbo, m_ebo; 6287 GLuint m_vsp, m_store_fsp, m_load_fsp; 6288 6289 virtual long Setup() 6290 { 6291 m_vao = 0; 6292 m_vbo = 0; 6293 m_ebo = 0; 6294 m_vsp = 0; 6295 m_store_fsp = 0; 6296 m_load_fsp = 0; 6297 glGenTextures(1, &m_texture); 6298 glGenProgramPipelines(1, &m_pipeline); 6299 6300 return NO_ERROR; 6301 } 6302 6303 virtual long Run() 6304 { 6305 if (!SupportedSamples(4)) 6306 return NOT_SUPPORTED; 6307 6308 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 6309 6310 const char* const glsl_vs = 6311 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL 6312 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 6313 const char* const glsl_store_fs = 6314 "#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL 6315 " imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}"; 6316 const char* const glsl_load_fs = 6317 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 6318 "layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL 6319 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != " 6320 "vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}"; 6321 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs); 6322 m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs); 6323 m_load_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs); 6324 6325 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture); 6326 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 6327 GL_FALSE); 6328 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); 6329 6330 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp); 6331 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp); 6332 6333 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6334 6335 glClear(GL_COLOR_BUFFER_BIT); 6336 glBindVertexArray(m_vao); 6337 glBindProgramPipeline(m_pipeline); 6338 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0); 6339 6340 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 6341 6342 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp); 6343 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0); 6344 6345 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 6346 { 6347 return ERROR; 6348 } 6349 return NO_ERROR; 6350 } 6351 6352 virtual long Cleanup() 6353 { 6354 glDeleteBuffers(1, &m_vbo); 6355 glDeleteBuffers(1, &m_ebo); 6356 glDeleteTextures(1, &m_texture); 6357 glDeleteProgram(m_vsp); 6358 glDeleteProgram(m_store_fsp); 6359 glDeleteProgram(m_load_fsp); 6360 glDeleteVertexArrays(1, &m_vao); 6361 glDeleteProgramPipelines(1, &m_pipeline); 6362 return NO_ERROR; 6363 } 6364}; 6365 6366//----------------------------------------------------------------------------- 6367// 2.5 AdvancedCopyImage 6368//----------------------------------------------------------------------------- 6369class AdvancedCopyImage : public ShaderImageLoadStoreBase 6370{ 6371 GLuint m_texture[2]; 6372 GLuint m_program; 6373 GLuint m_vao, m_vbo, m_ebo; 6374 6375 virtual long Setup() 6376 { 6377 glGenTextures(2, m_texture); 6378 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 6379 6380 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 6381 "void main() {" NL " gl_Position = i_position;" NL "}"; 6382 const char* const glsl_fs = 6383 "#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL 6384 "layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL 6385 " ivec2 coord = ivec2(gl_FragCoord);" NL 6386 " imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL " discard;" NL "}"; 6387 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 6388 6389 return NO_ERROR; 6390 } 6391 6392 virtual long Run() 6393 { 6394 glUseProgram(m_program); 6395 glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0); 6396 glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1); 6397 6398 std::vector<vec4> data(getWindowWidth() * getWindowHeight(), vec4(7.0f)); 6399 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 6400 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 6401 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_FLOAT, &data[0]); 6402 6403 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 6404 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 6405 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_FLOAT, NULL); 6406 6407 glBindTexture(GL_TEXTURE_2D, 0); 6408 6409 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); 6410 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 6411 6412 glClear(GL_COLOR_BUFFER_BIT); 6413 glBindVertexArray(m_vao); 6414 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0); 6415 6416 std::vector<vec4> rdata(getWindowWidth() * getWindowHeight()); 6417 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 6418 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]); 6419 6420 for (int h = 0; h < getWindowHeight(); ++h) 6421 { 6422 for (int w = 0; w < getWindowWidth(); ++w) 6423 { 6424 if (!IsEqual(rdata[h * getWindowWidth() + w], vec4(7.0f))) 6425 { 6426 return ERROR; 6427 } 6428 } 6429 } 6430 return NO_ERROR; 6431 } 6432 6433 virtual long Cleanup() 6434 { 6435 glUseProgram(0); 6436 glDeleteBuffers(1, &m_vbo); 6437 glDeleteBuffers(1, &m_ebo); 6438 glDeleteTextures(2, m_texture); 6439 glDeleteProgram(m_program); 6440 glDeleteVertexArrays(1, &m_vao); 6441 return NO_ERROR; 6442 } 6443}; 6444//----------------------------------------------------------------------------- 6445// 2.6 AdvancedAllMips 6446//----------------------------------------------------------------------------- 6447class AdvancedAllMips : public ShaderImageLoadStoreBase 6448{ 6449 GLuint m_texture; 6450 GLuint m_store_program, m_load_program; 6451 GLuint m_vao, m_vbo, m_ebo; 6452 6453 virtual long Setup() 6454 { 6455 glGenTextures(1, &m_texture); 6456 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 6457 6458 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 6459 "void main() {" NL " gl_Position = i_position;" NL "}"; 6460 const char* const glsl_store_fs = 6461 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL 6462 " for (int i = 0; i < 6; ++i) {" NL " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL " }" NL 6463 " discard;" NL "}"; 6464 const char* const glsl_load_fs = 6465 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 6466 "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL 6467 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " for (int i = 0; i < 6; ++i) {" NL 6468 " const ivec2 coord = ivec2(gl_FragCoord);" NL " const vec4 c = imageLoad(g_image[i], coord);" NL 6469 " if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " }" NL "}"; 6470 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs); 6471 m_load_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs); 6472 6473 return NO_ERROR; 6474 } 6475 6476 virtual long Run() 6477 { 6478 glUseProgram(m_store_program); 6479 glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0); 6480 glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1); 6481 glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2); 6482 glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3); 6483 glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4); 6484 glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5); 6485 glUseProgram(0); 6486 6487 glUseProgram(m_load_program); 6488 glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0); 6489 glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1); 6490 glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2); 6491 glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3); 6492 glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4); 6493 glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5); 6494 glUseProgram(0); 6495 6496 glBindTexture(GL_TEXTURE_2D, m_texture); 6497 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL); 6498 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL); 6499 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL); 6500 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL); 6501 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL); 6502 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL); 6503 glBindTexture(GL_TEXTURE_2D, 0); 6504 6505 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6506 glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6507 glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6508 glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6509 glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6510 glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6511 6512 glViewport(0, 0, 32, 32); 6513 glBindVertexArray(m_vao); 6514 6515 glClear(GL_COLOR_BUFFER_BIT); 6516 glUseProgram(m_store_program); 6517 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0); 6518 6519 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 6520 6521 glUseProgram(m_load_program); 6522 glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0); 6523 6524 if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1))) 6525 { 6526 return ERROR; 6527 } 6528 return NO_ERROR; 6529 } 6530 6531 virtual long Cleanup() 6532 { 6533 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 6534 glUseProgram(0); 6535 glDeleteBuffers(1, &m_vbo); 6536 glDeleteBuffers(1, &m_ebo); 6537 glDeleteTextures(1, &m_texture); 6538 glDeleteProgram(m_store_program); 6539 glDeleteProgram(m_load_program); 6540 glDeleteVertexArrays(1, &m_vao); 6541 return NO_ERROR; 6542 } 6543}; 6544//----------------------------------------------------------------------------- 6545// 2.7 AdvancedCast 6546//----------------------------------------------------------------------------- 6547class AdvancedCast : public ShaderImageLoadStoreBase 6548{ 6549 GLuint m_texture[2]; 6550 GLuint m_program; 6551 GLuint m_vao, m_vbo, m_ebo; 6552 6553 virtual long Setup() 6554 { 6555 glGenTextures(2, m_texture); 6556 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 6557 6558 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 6559 "void main() {" NL " gl_Position = i_position;" NL "}"; 6560 const char* const glsl_fs = 6561 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 6562 "layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL 6563 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " ivec2 coord = ivec2(gl_FragCoord);" NL 6564 " if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 6565 " if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 6566 " if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 6567 " if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}"; 6568 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 6569 6570 return NO_ERROR; 6571 } 6572 6573 virtual long Run() 6574 { 6575 glUseProgram(m_program); 6576 glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0); 6577 glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1); 6578 6579 { 6580 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4); 6581 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 6582 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 6583 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 6584 &data[0]); 6585 6586 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 6587 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 6588 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 6589 &data[0]); 6590 6591 glBindTexture(GL_TEXTURE_2D, 0); 6592 } 6593 6594 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I); 6595 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); 6596 6597 glClear(GL_COLOR_BUFFER_BIT); 6598 glBindVertexArray(m_vao); 6599 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0); 6600 6601 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4); 6602 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 6603 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 6604 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); 6605 6606 for (int h = 0; h < getWindowHeight(); ++h) 6607 { 6608 for (int w = 0; w < getWindowWidth(); ++w) 6609 { 6610 const GLubyte c[4] = { 6611 data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1], 6612 data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3], 6613 }; 6614 if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0) 6615 { 6616 m_context.getTestContext().getLog() 6617 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6618 << ") should be (1 0 0 0)" << tcu::TestLog::EndMessage; 6619 return ERROR; 6620 } 6621 } 6622 } 6623 6624 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 6625 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); 6626 6627 for (int h = 0; h < getWindowHeight(); ++h) 6628 { 6629 for (int w = 0; w < getWindowWidth(); ++w) 6630 { 6631 const GLubyte c[4] = { 6632 data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1], 6633 data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3], 6634 }; 6635 if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0) 6636 { 6637 m_context.getTestContext().getLog() 6638 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6639 << ") should be (3 0 0 0)" << tcu::TestLog::EndMessage; 6640 return ERROR; 6641 } 6642 } 6643 } 6644 6645 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 6646 { 6647 return ERROR; 6648 } 6649 return NO_ERROR; 6650 } 6651 6652 virtual long Cleanup() 6653 { 6654 glUseProgram(0); 6655 glDeleteBuffers(1, &m_vbo); 6656 glDeleteBuffers(1, &m_ebo); 6657 glDeleteTextures(2, m_texture); 6658 glDeleteProgram(m_program); 6659 glDeleteVertexArrays(1, &m_vao); 6660 return NO_ERROR; 6661 } 6662}; 6663 6664/** Test "imageLoad() and imageStore() for single-byte data alignment" description follows. 6665 * 6666 * Steps: 6667 * - create two textures: "source" and "destination". Fill "source" 6668 * texture with unique values. Fill "destination" texture with zeros, 6669 * - prepare a program object that will read texel from "source" image at given 6670 * coordinates and write its value to "destination" image at same 6671 * coordinates, 6672 * - bind "source" and "destination" textures as "source" and "destination" 6673 * image uniforms, 6674 * - render "full screen" quad (left bottom corner at -1,-1 and right top 6675 * corner at 1,1), 6676 * - verify that texel values in "destination" texture match those in 6677 * "source" texture (use glGetTexImage). 6678 * 6679 * Test with 2D R8UI textures with following dimensions: 6680 * - 16x16, 6681 * - 16x17, 6682 * - 17x16, 6683 * - 17x17, 6684 * - 16x18, 6685 * - 18x16, 6686 * - 18x18, 6687 * - 19x16, 6688 * - 16x19, 6689 * - 19x19. 6690 * 6691 * Note that default data alignment should cause problems with packing/ 6692 * /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters 6693 * of pixel storage mode have to be changed to one byte alignment. 6694 * 6695 * Program should consist of vertex and fragment shader. Vertex shader should 6696 * pass vertex position through. Fragment shader should do imageLoad() and 6697 * imageStore() operations at coordinates gl_FragCoord. 6698 **/ 6699class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase 6700{ 6701private: 6702 /* Structures */ 6703 struct TextureDimensions 6704 { 6705 GLuint m_width; 6706 GLuint m_height; 6707 6708 TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height) 6709 { 6710 } 6711 }; 6712 6713 /* Typedefs */ 6714 typedef std::deque<TextureDimensions> TextureDimensionsList; 6715 6716 /* Fields */ 6717 GLuint m_destination_texture_id; 6718 GLuint m_program_id; 6719 TextureDimensionsList m_texture_dimensions; 6720 GLuint m_source_texture_id; 6721 GLuint m_vertex_array_object_id; 6722 GLuint m_vertex_buffer_id; 6723 6724public: 6725 /* Constructor */ 6726 ImageLoadStoreDataAlignmentTest() 6727 : m_destination_texture_id(0) 6728 , m_program_id(0) 6729 , m_source_texture_id(0) 6730 , m_vertex_array_object_id(0) 6731 , m_vertex_buffer_id(0) 6732 { 6733 /* Nothing to be done here */ 6734 } 6735 6736 /* Methods inherited from SubcaseBase */ 6737 virtual long Setup() 6738 { 6739 /* Shaders code */ 6740 const char* const vertex_shader_code = "#version 400 core\n" 6741 "#extension GL_ARB_shader_image_load_store : require\n" 6742 "\n" 6743 "precision highp float;\n" 6744 "\n" 6745 "in vec4 vs_in_position;\n" 6746 "\n" 6747 "void main()\n" 6748 "{\n" 6749 " gl_Position = vs_in_position;\n" 6750 "}\n"; 6751 6752 const char* const fragment_shader_code = 6753 "#version 400 core\n" 6754 "#extension GL_ARB_shader_image_load_store : require\n" 6755 "\n" 6756 "precision highp float;\n" 6757 "\n" 6758 "layout(r8ui) writeonly uniform uimage2D u_destination_image;\n" 6759 "layout(r8ui) readonly uniform uimage2D u_source_image;\n" 6760 "\n" 6761 "void main()\n" 6762 "{\n" 6763 " uvec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n" 6764 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n" 6765 "\n" 6766 " discard;\n" 6767 "}\n"; 6768 6769 /* Vertex postions for "full screen" quad, made with triangle strip */ 6770 static const GLfloat m_vertex_buffer_data[] = { 6771 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */ 6772 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */ 6773 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */ 6774 1.0f, 1.0f, 0.0f, 1.0f, /* right top */ 6775 }; 6776 6777 /* Result of BuildProgram operation */ 6778 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */ 6779 6780 /* Add all tested texture dimensions */ 6781 m_texture_dimensions.push_back(TextureDimensions(16, 16)); 6782 m_texture_dimensions.push_back(TextureDimensions(16, 17)); 6783 m_texture_dimensions.push_back(TextureDimensions(17, 16)); 6784 m_texture_dimensions.push_back(TextureDimensions(17, 17)); 6785 m_texture_dimensions.push_back(TextureDimensions(16, 18)); 6786 m_texture_dimensions.push_back(TextureDimensions(18, 16)); 6787 m_texture_dimensions.push_back(TextureDimensions(18, 18)); 6788 m_texture_dimensions.push_back(TextureDimensions(16, 19)); 6789 m_texture_dimensions.push_back(TextureDimensions(19, 16)); 6790 m_texture_dimensions.push_back(TextureDimensions(19, 19)); 6791 6792 /* Clean previous error */ 6793 glGetError(); 6794 6795 /* Set single-byte data alignment */ 6796 glPixelStorei(GL_PACK_ALIGNMENT, 1); 6797 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 6798 GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei"); 6799 6800 /* Prepare buffer with vertex positions of "full screen" quad" */ 6801 glGenBuffers(1, &m_vertex_buffer_id); 6802 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers"); 6803 6804 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id); 6805 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer"); 6806 6807 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW); 6808 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData"); 6809 6810 /* Generate vertex array object */ 6811 glGenVertexArrays(1, &m_vertex_array_object_id); 6812 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays"); 6813 6814 /* Prepare program object */ 6815 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */, 6816 fragment_shader_code, &is_program_correct); 6817 if (false == is_program_correct) 6818 { 6819 return ERROR; 6820 } 6821 6822 /* Done */ 6823 return NO_ERROR; 6824 } 6825 6826 virtual long Cleanup() 6827 { 6828 /* Reset OpenGL state */ 6829 glBindBuffer(GL_ARRAY_BUFFER, 0); 6830 glBindTexture(GL_TEXTURE_2D, 0); 6831 glBindVertexArray(0); 6832 glUseProgram(0); 6833 6834 /* Delete program */ 6835 if (0 != m_program_id) 6836 { 6837 glDeleteProgram(m_program_id); 6838 m_program_id = 0; 6839 } 6840 6841 /* Delete textures */ 6842 if (0 != m_destination_texture_id) 6843 { 6844 glDeleteTextures(1, &m_destination_texture_id); 6845 m_destination_texture_id = 0; 6846 } 6847 6848 if (0 != m_source_texture_id) 6849 { 6850 glDeleteTextures(1, &m_source_texture_id); 6851 m_source_texture_id = 0; 6852 } 6853 6854 /* Delete vertex array object */ 6855 if (0 != m_vertex_array_object_id) 6856 { 6857 glDeleteVertexArrays(1, &m_vertex_array_object_id); 6858 m_vertex_array_object_id = 0; 6859 } 6860 6861 /* Delete buffer */ 6862 if (0 != m_vertex_buffer_id) 6863 { 6864 glDeleteBuffers(1, &m_vertex_buffer_id); 6865 m_vertex_buffer_id = 0; 6866 } 6867 6868 /* Done */ 6869 return NO_ERROR; 6870 } 6871 6872 virtual long Run() 6873 { 6874 bool result = true; 6875 6876 /* For each dimension */ 6877 for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it; 6878 ++it) 6879 { 6880 /* Prepare "source" and "destination" textures */ 6881 GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id), 6882 "Create2DR8UIDestinationTexture"); 6883 GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id), 6884 "Create2DR8UISourceTexture"); 6885 6886 /* Copy texture data with imageLoad() and imageStore() operations */ 6887 Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id); 6888 6889 /* Compare "source" and "destination" textures */ 6890 if (false == 6891 Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height)) 6892 { 6893 m_context.getTestContext().getLog() 6894 << tcu::TestLog::Message 6895 << "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height 6896 << ". Source and destination textures are different" << tcu::TestLog::EndMessage; 6897 6898 result = false; 6899 } 6900 6901 /* Destroy "source" and "destination" textures */ 6902 glDeleteTextures(1, &m_destination_texture_id); 6903 glDeleteTextures(1, &m_source_texture_id); 6904 6905 m_destination_texture_id = 0; 6906 m_source_texture_id = 0; 6907 } 6908 6909 if (false == result) 6910 { 6911 return ERROR; 6912 } 6913 6914 /* Done */ 6915 return NO_ERROR; 6916 } 6917 6918private: 6919 /* Private methods */ 6920 6921 /** Binds a texture to user-specified image unit and updates relevant sampler uniform 6922 * 6923 * @param program_id Program object id 6924 * @param texture_id Texture id 6925 * @param image_unit Index of image unit 6926 * @param uniform_name Name of image uniform 6927 **/ 6928 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char* uniform_name) 6929 { 6930 /* Uniform location and invalid value */ 6931 static const GLint invalid_uniform_location = -1; 6932 GLint image_uniform_location = 0; 6933 6934 /* Get uniform location */ 6935 image_uniform_location = glGetUniformLocation(program_id, uniform_name); 6936 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation"); 6937 if (invalid_uniform_location == image_uniform_location) 6938 { 6939 throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__); 6940 } 6941 6942 /* Bind texture to image unit */ 6943 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI); 6944 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture"); 6945 6946 /* Set uniform to image unit */ 6947 glUniform1i(image_uniform_location, image_unit); 6948 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 6949 } 6950 6951 /** Compare two 2D R8UI textures 6952 * 6953 * @param left_texture_id Id of "left" texture object 6954 * @param right_texture_id Id of "right" texture object 6955 * @param width Width of the textures 6956 * @param height Height of the textures 6957 * 6958 * @return true when texture data is identical, false otherwise 6959 **/ 6960 bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height) 6961 { 6962 /* Size of textures */ 6963 const GLuint texture_data_size = width * height; 6964 6965 /* Storage for texture data */ 6966 std::vector<GLubyte> left_texture_data; 6967 std::vector<GLubyte> right_texture_data; 6968 6969 /* Alocate memory for texture data */ 6970 left_texture_data.resize(texture_data_size); 6971 right_texture_data.resize(texture_data_size); 6972 6973 /* Get "left" texture data */ 6974 glBindTexture(GL_TEXTURE_2D, left_texture_id); 6975 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 6976 6977 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]); 6978 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 6979 6980 /* Get "right" texture data */ 6981 glBindTexture(GL_TEXTURE_2D, right_texture_id); 6982 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 6983 6984 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]); 6985 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 6986 6987 /* Compare texels */ 6988 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size)); 6989 } 6990 6991 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations 6992 * 6993 * @param destination_texture_id Id of "destination" texture object 6994 * @param source_texture_id Id of "source" texture object 6995 **/ 6996 void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id) 6997 { 6998 /* Uniform names */ 6999 static const char* const destination_image_uniform_name = "u_destination_image"; 7000 static const char* const source_image_uniform_name = "u_source_image"; 7001 7002 /* Attribute name */ 7003 static const char* const position_attribute_name = "vs_in_position"; 7004 7005 /* Attribute location and invalid value */ 7006 static const GLint invalid_attribute_location = -1; 7007 GLint position_attribute_location = 0; 7008 7009 /* Set current program */ 7010 glUseProgram(m_program_id); 7011 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram"); 7012 7013 /* Bind vertex array object */ 7014 glBindVertexArray(m_vertex_array_object_id); 7015 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray"); 7016 7017 /* Bind buffer with quad vertex positions */ 7018 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id); 7019 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer"); 7020 7021 /* Set up position attribute */ 7022 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name); 7023 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation"); 7024 if (invalid_attribute_location == position_attribute_location) 7025 { 7026 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__, 7027 __LINE__); 7028 } 7029 7030 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */, 7031 0 /* stride */, 0); 7032 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer"); 7033 7034 glEnableVertexAttribArray(position_attribute_location); 7035 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray"); 7036 7037 /* Set up textures as source and destination images */ 7038 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name); 7039 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name); 7040 7041 /* Execute draw */ 7042 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */); 7043 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 7044 } 7045 7046 /** Create 2D R8UI texture and fills it with zeros 7047 * 7048 * @param width Width of created texture 7049 * @param height Height of created texture 7050 * @param out_texture_id Id of created texture, not modified if operation fails 7051 * 7052 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 7053 **/ 7054 GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint& out_texture_id) 7055 { 7056 /* Texture size */ 7057 const GLuint texture_size = width * height; 7058 7059 /* Prepare storage for texture data */ 7060 std::vector<GLubyte> texture_data; 7061 texture_data.resize(texture_size); 7062 7063 /* Set all texels */ 7064 for (GLuint i = 0; i < texture_size; ++i) 7065 { 7066 texture_data[i] = 0; 7067 } 7068 7069 /* Create texture */ 7070 return Create2DR8UITexture(width, height, texture_data, out_texture_id); 7071 } 7072 7073 /** Create 2D R8UI texture and fills it with increasing values, starting from 0 7074 * 7075 * @param width Width of created texture 7076 * @param height Height of created texture 7077 * @param out_texture_id Id of created texture, not modified if operation fails 7078 * 7079 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 7080 **/ 7081 GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint& out_texture_id) 7082 { 7083 /* Texture size */ 7084 const GLuint texture_size = width * height; 7085 7086 /* Value of texel */ 7087 GLubyte texel_value = 0; 7088 7089 /* Prepare storage for texture data */ 7090 std::vector<GLubyte> texture_data; 7091 texture_data.resize(texture_size); 7092 7093 /* Set all texels */ 7094 for (GLuint i = 0; i < texture_size; ++i) 7095 { 7096 texture_data[i] = texel_value++; 7097 } 7098 7099 /* Create texture */ 7100 return Create2DR8UITexture(width, height, texture_data, out_texture_id); 7101 } 7102 7103 /** Create 2D R8UI texture and fills it with user-provided data 7104 * 7105 * @param width Width of created texture 7106 * @param height Height of created texture 7107 * @param texture_data Texture data 7108 * @param out_texture_id Id of created texture, not modified if operation fails 7109 * 7110 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 7111 **/ 7112 GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte>& texture_data, 7113 GLuint& out_texture_id) 7114 { 7115 GLenum err = 0; 7116 GLuint texture_id = 0; 7117 7118 /* Generate texture */ 7119 glGenTextures(1, &texture_id); 7120 err = glGetError(); 7121 if (GL_NO_ERROR != err) 7122 { 7123 return err; 7124 } 7125 7126 /* Bind texture */ 7127 glBindTexture(GL_TEXTURE_2D, texture_id); 7128 err = glGetError(); 7129 if (GL_NO_ERROR != err) 7130 { 7131 glDeleteTextures(1, &texture_id); 7132 return err; 7133 } 7134 7135 /* Allocate storage and fill texture */ 7136 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER, 7137 GL_UNSIGNED_BYTE, &texture_data[0]); 7138 err = glGetError(); 7139 if (GL_NO_ERROR != err) 7140 { 7141 glDeleteTextures(1, &texture_id); 7142 return err; 7143 } 7144 7145 /* Make texture complete */ 7146 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 7147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 7148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 7149 err = glGetError(); 7150 if (GL_NO_ERROR != err) 7151 { 7152 glDeleteTextures(1, &texture_id); 7153 return err; 7154 } 7155 7156 /* Set out_texture_id */ 7157 out_texture_id = texture_id; 7158 7159 /* Done */ 7160 return GL_NO_ERROR; 7161 } 7162}; 7163 7164/** Test "imageLoad() and imageStore() for non-layered image bindings" description follows. 7165 * 7166 * Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest). 7167 * 7168 * Test non-layered image bindings (BindImageTexture <layered>: false) with: 7169 * | Type | Dimensions | 7170 * | 2D_ARRAY | 64x64x6 | 7171 * | 3D | 64x64x6 | 7172 * | CUBE_MAP | 64 | 7173 * | CUBE_MAP_ARRAY | 64x3 | 7174 * 7175 * Use RGBA8 format. All layers shall be tested. 7176 * 7177 * Program should consist of vertex and fragment shader. Vertex shader should 7178 * pass vertex position through. Fragment shader should do imageLoad() and 7179 * imageStore() operations at coordinates gl_FragCoord. Fragment shader should 7180 * use image2D as image type. 7181 **/ 7182class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase 7183{ 7184private: 7185 /* Structures */ 7186 struct TextureShapeDefinition 7187 { 7188 GLuint m_edge; 7189 GLuint m_n_elements; 7190 GLenum m_type; 7191 7192 TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type) 7193 : m_edge(edge), m_n_elements(n_elements), m_type(type) 7194 { 7195 } 7196 }; 7197 7198 /* Typedefs */ 7199 typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList; 7200 7201 /* Fields */ 7202 GLuint m_destination_texture_id; 7203 GLuint m_program_id; 7204 TextureShapeDefinitionList m_texture_shape_definitions; 7205 GLuint m_source_texture_id; 7206 GLuint m_vertex_array_object_id; 7207 GLuint m_vertex_buffer_id; 7208 7209public: 7210 /* Constructor */ 7211 ImageLoadStoreNonLayeredBindingTest() 7212 : m_destination_texture_id(0) 7213 , m_program_id(0) 7214 , m_source_texture_id(0) 7215 , m_vertex_array_object_id(0) 7216 , m_vertex_buffer_id(0) 7217 { 7218 /* Nothing to be done here */ 7219 } 7220 7221 /* Methods inherited from SubcaseBase */ 7222 virtual long Setup() 7223 { 7224 /* Shaders code */ 7225 const char* const vertex_shader_code = "#version 400 core\n" 7226 "#extension GL_ARB_shader_image_load_store : require\n" 7227 "\n" 7228 "precision highp float;\n" 7229 "\n" 7230 "in vec4 vs_in_position;\n" 7231 "\n" 7232 "void main()\n" 7233 "{\n" 7234 " gl_Position = vs_in_position;\n" 7235 "}\n"; 7236 7237 const char* const fragment_shader_code = 7238 "#version 400 core\n" 7239 "#extension GL_ARB_shader_image_load_store : require\n" 7240 "\n" 7241 "precision highp float;\n" 7242 "\n" 7243 "layout(rgba8) writeonly uniform image2D u_destination_image;\n" 7244 "layout(rgba8) readonly uniform image2D u_source_image;\n" 7245 "\n" 7246 "void main()\n" 7247 "{\n" 7248 " vec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n" 7249 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n" 7250 "\n" 7251 " discard;\n" 7252 "}\n"; 7253 7254 /* Vertex postions for "full screen" quad, defined as a triangle strip */ 7255 static const GLfloat m_vertex_buffer_data[] = { 7256 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */ 7257 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */ 7258 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */ 7259 1.0f, 1.0f, 0.0f, 1.0f, /* right top */ 7260 }; 7261 7262 /* Result of BuildProgram operation */ 7263 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */ 7264 7265 /* Add all tested texture shapes */ 7266 int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth())); 7267 m_texture_shape_definitions.push_back( 7268 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY)); 7269 m_texture_shape_definitions.push_back( 7270 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D)); 7271 m_texture_shape_definitions.push_back( 7272 TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP)); 7273 m_texture_shape_definitions.push_back( 7274 TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY)); 7275 7276 /* Prepare buffer with vertex positions of "full screen" quad" */ 7277 glGenBuffers(1, &m_vertex_buffer_id); 7278 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers"); 7279 7280 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id); 7281 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer"); 7282 7283 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW); 7284 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData"); 7285 7286 /* Generate vertex array object */ 7287 glGenVertexArrays(1, &m_vertex_array_object_id); 7288 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays"); 7289 7290 /* Prepare program object */ 7291 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */, 7292 fragment_shader_code, &is_program_correct); 7293 if (false == is_program_correct) 7294 { 7295 return ERROR; 7296 } 7297 7298 /* Done */ 7299 return NO_ERROR; 7300 } 7301 7302 virtual long Cleanup() 7303 { 7304 /* Reset OpenGL state */ 7305 glBindBuffer(GL_ARRAY_BUFFER, 0); 7306 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 7307 glBindTexture(GL_TEXTURE_3D, 0); 7308 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 7309 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); 7310 glBindVertexArray(0); 7311 glUseProgram(0); 7312 7313 /* Delete program */ 7314 if (0 != m_program_id) 7315 { 7316 glDeleteProgram(m_program_id); 7317 m_program_id = 0; 7318 } 7319 7320 /* Delete textures */ 7321 if (0 != m_destination_texture_id) 7322 { 7323 glDeleteTextures(1, &m_destination_texture_id); 7324 m_destination_texture_id = 0; 7325 } 7326 7327 if (0 != m_source_texture_id) 7328 { 7329 glDeleteTextures(1, &m_source_texture_id); 7330 m_source_texture_id = 0; 7331 } 7332 7333 /* Delete vertex array object */ 7334 if (0 != m_vertex_array_object_id) 7335 { 7336 glDeleteVertexArrays(1, &m_vertex_array_object_id); 7337 m_vertex_array_object_id = 0; 7338 } 7339 7340 /* Delete buffer */ 7341 if (0 != m_vertex_buffer_id) 7342 { 7343 glDeleteBuffers(1, &m_vertex_buffer_id); 7344 m_vertex_buffer_id = 0; 7345 } 7346 7347 /* Done */ 7348 return NO_ERROR; 7349 } 7350 7351 virtual long Run() 7352 { 7353 bool result = true; 7354 7355 /* For each shape */ 7356 for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin(); 7357 m_texture_shape_definitions.end() != it; ++it) 7358 { 7359 const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type); 7360 7361 /* Prepare "source" and "destination" textures */ 7362 GLU_EXPECT_NO_ERROR( 7363 CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id), 7364 "Create2DR8UIDestinationTexture"); 7365 GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id), 7366 "Create2DR8UISourceTexture"); 7367 7368 /* Copy texture data with imageLoad() and imageStore() operations */ 7369 CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers); 7370 7371 /* Compare "source" and "destination" textures */ 7372 if (false == 7373 CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type)) 7374 { 7375 const char* texture_type = ""; 7376 switch (it->m_type) 7377 { 7378 case GL_TEXTURE_2D_ARRAY: 7379 texture_type = "2d array"; 7380 break; 7381 case GL_TEXTURE_3D: 7382 texture_type = "3d"; 7383 break; 7384 case GL_TEXTURE_CUBE_MAP: 7385 texture_type = "Cube map"; 7386 break; 7387 case GL_TEXTURE_CUBE_MAP_ARRAY: 7388 texture_type = "Cube map array"; 7389 break; 7390 } 7391 7392 m_context.getTestContext().getLog() 7393 << tcu::TestLog::Message 7394 << "Copy with imageLoad and imageStore failed for texture type: " << texture_type 7395 << ". Source and destination textures are different" << tcu::TestLog::EndMessage; 7396 7397 result = false; 7398 } 7399 7400 /* Destroy "source" and "destination" textures */ 7401 glDeleteTextures(1, &m_destination_texture_id); 7402 glDeleteTextures(1, &m_source_texture_id); 7403 7404 m_destination_texture_id = 0; 7405 m_source_texture_id = 0; 7406 } 7407 7408 if (false == result) 7409 { 7410 return ERROR; 7411 } 7412 7413 /* Done */ 7414 return NO_ERROR; 7415 } 7416 7417private: 7418 /* Private methods */ 7419 7420 /** Binds a texture to user-specified image unit and update relevant sampler uniform 7421 * 7422 * @param program_id Program object id 7423 * @param texture_id Texture id 7424 * @param image_unit Index of image unit 7425 * @param layer Index of layer bound to unit 7426 * @param uniform_name Name of image uniform 7427 **/ 7428 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer, 7429 const char* uniform_name) 7430 { 7431 static const GLint invalid_uniform_location = -1; 7432 GLint image_uniform_location = 0; 7433 7434 /* Get uniform location */ 7435 image_uniform_location = glGetUniformLocation(program_id, uniform_name); 7436 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation"); 7437 if (invalid_uniform_location == image_uniform_location) 7438 { 7439 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__); 7440 } 7441 7442 /* Bind texture to image unit */ 7443 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE, 7444 GL_RGBA8); 7445 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture"); 7446 7447 /* Set uniform to image unit */ 7448 glUniform1i(image_uniform_location, image_unit); 7449 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 7450 } 7451 7452 /** Compare two 2D R8UI textures 7453 * 7454 * @param left_texture_id Id of "left" texture object 7455 * @param right_texture_id Id of "right" texture object 7456 * @param edge Length of texture edge 7457 * @param n_layers Number of layers to compare 7458 * @param type Type of texture 7459 * 7460 * @return true when texture data is found identical, false otherwise 7461 **/ 7462 bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers, 7463 GLenum type) 7464 { 7465 static const GLuint n_components = 4; /* RGBA */ 7466 const GLuint texture_data_size = edge * edge * n_layers * n_components; 7467 7468 /* Storage for texture data */ 7469 std::vector<GLubyte> left_texture_data; 7470 std::vector<GLubyte> right_texture_data; 7471 7472 ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data); 7473 ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data); 7474 7475 /* Compare texels */ 7476 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size)); 7477 } 7478 7479 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations 7480 * 7481 * @param destination_texture_id Id of "destination" texture object 7482 * @param source_texture_id Id of "source" texture object 7483 * @param n_layers Number of layers 7484 **/ 7485 void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers) 7486 { 7487 for (GLuint layer = 0; layer < n_layers; ++layer) 7488 { 7489 CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer); 7490 } 7491 } 7492 7493 /** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations 7494 * 7495 * @param destination_texture_id Id of "destination" texture object 7496 * @param source_texture_id Id of "source" texture object 7497 * @param layer Index of layer 7498 **/ 7499 void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer) 7500 { 7501 /* Uniform names */ 7502 static const char* const destination_image_uniform_name = "u_destination_image"; 7503 static const char* const source_image_uniform_name = "u_source_image"; 7504 7505 /* Attribute name */ 7506 static const char* const position_attribute_name = "vs_in_position"; 7507 7508 /* Attribute location and invalid value */ 7509 static const GLint invalid_attribute_location = -1; 7510 GLint position_attribute_location = 0; 7511 7512 /* Set current program */ 7513 glUseProgram(m_program_id); 7514 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram"); 7515 7516 /* Bind vertex array object */ 7517 glBindVertexArray(m_vertex_array_object_id); 7518 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray"); 7519 7520 /* Bind buffer with quad vertex positions */ 7521 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id); 7522 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer"); 7523 7524 /* Set up vertex attribute array for position attribute */ 7525 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name); 7526 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation"); 7527 if (invalid_attribute_location == position_attribute_location) 7528 { 7529 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__, 7530 __LINE__); 7531 } 7532 7533 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */, 7534 0 /* stride */, 0 /* pointer */); 7535 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer"); 7536 7537 glEnableVertexAttribArray(position_attribute_location); 7538 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray"); 7539 7540 /* Set up textures as source and destination image samplers */ 7541 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer, 7542 destination_image_uniform_name); 7543 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name); 7544 7545 /* Execute draw */ 7546 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */); 7547 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 7548 } 7549 7550 /** Creates RGBA8 texture of given type and fills it with zeros 7551 * 7552 * @param edge Edge of created texture 7553 * @param n_elements Number of elements in texture array 7554 * @param target Target of created texture 7555 * @param out_texture_id Id of created texture, not modified if operation fails 7556 * 7557 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 7558 **/ 7559 GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id) 7560 { 7561 /* Constasts to calculate texture size */ 7562 static const GLuint n_components = 4; /* RGBA */ 7563 const GLuint layer_size = edge * edge * n_components; 7564 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target); 7565 const GLuint texture_size = layer_size * n_layers; 7566 7567 /* Prepare storage for texture data */ 7568 std::vector<GLubyte> texture_data; 7569 texture_data.resize(texture_size); 7570 7571 /* Set all texels */ 7572 for (GLuint i = 0; i < texture_size; ++i) 7573 { 7574 texture_data[i] = 0; 7575 } 7576 7577 /* Create texture */ 7578 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id); 7579 } 7580 7581 /** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa] 7582 * 7583 * @param edge Edge of created texture 7584 * @param n_elements Number of elements in texture array 7585 * @param target Target of created texture 7586 * @param out_texture_id Id of created texture, not modified if operation fails 7587 * 7588 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 7589 **/ 7590 GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id) 7591 { 7592 /* Constants to calculate texture size */ 7593 static const GLuint n_components = 4; /* RGBA */ 7594 const GLuint layer_size = edge * edge * n_components; 7595 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target); 7596 const GLuint texture_size = layer_size * n_layers; 7597 7598 /* Value of texel */ 7599 GLubyte texel[4] = { 0, 0, 0, 0xaa }; 7600 7601 /* Prepare storage for texture data */ 7602 std::vector<GLubyte> texture_data; 7603 texture_data.resize(texture_size); 7604 7605 /* Set all texels */ 7606 for (GLuint layer = 0; layer < n_layers; ++layer) 7607 { 7608 const GLuint layer_offset = layer_size * layer; 7609 7610 texel[2] = static_cast<GLubyte>(layer); 7611 7612 for (GLuint y = 0; y < edge; ++y) 7613 { 7614 const GLuint line_offset = y * edge * n_components + layer_offset; 7615 7616 texel[1] = static_cast<GLubyte>(y); 7617 7618 for (GLuint x = 0; x < edge; ++x) 7619 { 7620 const GLuint texel_offset = x * n_components + line_offset; 7621 texel[0] = static_cast<GLubyte>(x); 7622 7623 for (GLuint component = 0; component < n_components; ++component) 7624 { 7625 texture_data[texel_offset + component] = texel[component]; 7626 } 7627 } 7628 } 7629 } 7630 7631 /* Create texture */ 7632 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id); 7633 } 7634 7635 /** Creates RGBA8 texture of given type and fills it provided data 7636 * 7637 * @param edge Edge of created texture 7638 * @param n_elements Number of elements in texture array 7639 * @param target Target of created texture 7640 * @param texture_data Texture data 7641 * @param out_texture_id Id of created texture, not modified if operation fails 7642 * 7643 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 7644 **/ 7645 GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte>& texture_data, 7646 GLuint& out_texture_id) 7647 { 7648 GLenum err = 0; 7649 GLuint texture_id = 0; 7650 7651 /* Generate texture */ 7652 glGenTextures(1, &texture_id); 7653 err = glGetError(); 7654 if (GL_NO_ERROR != err) 7655 { 7656 return err; 7657 } 7658 7659 /* Bind texture */ 7660 glBindTexture(target, texture_id); 7661 err = glGetError(); 7662 if (GL_NO_ERROR != err) 7663 { 7664 glDeleteTextures(1, &texture_id); 7665 return err; 7666 } 7667 7668 /* Allocate storage and fill texture */ 7669 if (GL_TEXTURE_CUBE_MAP != target) 7670 { 7671 glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA, 7672 GL_UNSIGNED_BYTE, &texture_data[0]); 7673 } 7674 else 7675 { 7676 const GLuint n_components = 4; 7677 const GLuint layer_size = edge * edge * n_components; 7678 7679 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA, 7680 GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]); 7681 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA, 7682 GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]); 7683 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA, 7684 GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]); 7685 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA, 7686 GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]); 7687 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA, 7688 GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]); 7689 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA, 7690 GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]); 7691 } 7692 err = glGetError(); 7693 if (GL_NO_ERROR != err) 7694 { 7695 glDeleteTextures(1, &texture_id); 7696 return err; 7697 } 7698 7699 /* Make texture complete */ 7700 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0); 7701 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0); 7702 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 7703 err = glGetError(); 7704 if (GL_NO_ERROR != err) 7705 { 7706 glDeleteTextures(1, &texture_id); 7707 return err; 7708 } 7709 7710 /* Set out_texture_id */ 7711 out_texture_id = texture_id; 7712 7713 /* Done */ 7714 return GL_NO_ERROR; 7715 } 7716 7717 /** Extracts texture data 7718 * 7719 * @param texture_id Id of texture object 7720 * @param edge Length of texture edge 7721 * @param n_layers Number of layers 7722 * @param target Target of texture 7723 * @param texture_data Extracted texture data 7724 **/ 7725 void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target, 7726 std::vector<GLubyte>& texture_data) 7727 { 7728 static const GLuint n_components = 4; /* RGBA */ 7729 const GLuint texture_data_size = edge * edge * n_layers * n_components; 7730 7731 /* Alocate memory for texture data */ 7732 texture_data.resize(texture_data_size); 7733 7734 /* Bind texture */ 7735 glBindTexture(target, texture_id); 7736 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 7737 7738 /* Get data */ 7739 if (GL_TEXTURE_CUBE_MAP != target) 7740 { 7741 glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); 7742 } 7743 else 7744 { 7745 const GLuint layer_size = edge * edge * n_components; 7746 7747 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]); 7748 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]); 7749 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]); 7750 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]); 7751 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]); 7752 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]); 7753 } 7754 7755 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 7756 } 7757 7758 /** Get number of layers per single element for given type of texture 7759 * 7760 * @param target Target of texture 7761 * 7762 * @return Number of layers 7763 **/ 7764 GLuint GetLayersPerElement(GLenum target) 7765 { 7766 switch (target) 7767 { 7768 case GL_TEXTURE_2D_ARRAY: 7769 case GL_TEXTURE_3D: 7770 return 1; 7771 break; 7772 case GL_TEXTURE_CUBE_MAP: 7773 case GL_TEXTURE_CUBE_MAP_ARRAY: 7774 return 6; 7775 break; 7776 default: 7777 throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__); 7778 break; 7779 } 7780 } 7781 7782 /** Get total number of layers in texture of given type and number of array elements 7783 * 7784 * @param n_elements Number of elements in texture array 7785 * @param target Target of texture 7786 * 7787 * @return Number of layers 7788 **/ 7789 GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target) 7790 { 7791 return GetLayersPerElement(target) * n_elements; 7792 } 7793}; 7794 7795/** Test "imageLoad() and imageStore() for incomplete textures" description follows. 7796 * 7797 * Load from incomplete textures should return 0. 7798 * Store to incomplete textures should be ignored. 7799 * 7800 * Steps: 7801 * - create two incomplete textures: "incomplete_source" and 7802 * "incomplete_destination", 7803 * - create two complete textures: "complete_source" and 7804 * "complete_destination", 7805 * - fill all textures with unique values, 7806 * - prepare program that will: 7807 * * load texel from "incomplete_source" and store its value to 7808 * "complete_destination", 7809 * * load texel from "complete_source" and store its value to 7810 * "incomplete_destination". 7811 * - bind textures to corresponding image uniforms 7812 * - execute program for all texels, 7813 * - verify that "incomplete_destination" was not modified and 7814 * "complete_destination" is filled with zeros. 7815 * 7816 * Texture is considered incomplete when it has enabled mipmaping (see below) 7817 * and does not have all mipmap levels defined. But for the case of Image 7818 * accessing, it is considered invalid if it is mipmap-incomplete and the 7819 * level is different to the base level (base-incomplete). 7820 * 7821 * Creation of incomplete texture: 7822 * - generate and bind texture object id, 7823 * - call TexImage2D with <level>: 0, 7824 * - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make 7825 * sure, it should be initial value), 7826 * - set GL_TEXTURE_BASE_LEVEL parameter to 0. 7827 * - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width, 7828 * height)). 7829 * 7830 * Creation of complete texture: 7831 * - generate and bind texture object id, 7832 * - call TexImage2D with <level>: 0, 7833 * - set GL_TEXTURE_BASE_LEVEL parameter to 0. 7834 * - set GL_TEXTURE_MAX_LEVEL parameter to 0. 7835 * 7836 * Binding: 7837 * - Set level == base_level for complete destinations. 7838 * - Set level != base_level for incomplete destinations that are using 7839 * mipmap-incomplete textures. 7840 * 7841 * Test with 2D 64x64 RGBA8 textures. 7842 * 7843 * Program should consist of vertex and fragment shader. Vertex shader should 7844 * pass vertex position through. Fragment shader should do imageLoad() and 7845 * imageStore() operations at coordinates gl_FragCoord. 7846 **/ 7847class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase 7848{ 7849private: 7850 /* Constants */ 7851 /* Magic numbers that will identify textures, which will be used as their 7852 * texel value. 7853 */ 7854 static const GLubyte m_complete_destination_magic_number = 0x11; 7855 static const GLubyte m_complete_source_magic_number = 0x22; 7856 static const GLubyte m_incomplete_destination_magic_number = 0x33; 7857 static const GLubyte m_incomplete_source_magic_number = 0x44; 7858 7859 /* Texture edge */ 7860 GLuint m_texture_edge; 7861 7862 /* Fields */ 7863 GLuint m_complete_destination_texture_id; 7864 GLuint m_complete_source_texture_id; 7865 GLuint m_incomplete_destination_texture_id; 7866 GLuint m_incomplete_source_texture_id; 7867 GLuint m_program_id; 7868 GLuint m_vertex_array_object_id; 7869 GLuint m_vertex_buffer_id; 7870 7871public: 7872 /* Constructor */ 7873 ImageLoadStoreIncompleteTexturesTest() 7874 : m_texture_edge(0) 7875 , m_complete_destination_texture_id(0) 7876 , m_complete_source_texture_id(0) 7877 , m_incomplete_destination_texture_id(0) 7878 , m_incomplete_source_texture_id(0) 7879 , m_program_id(0) 7880 , m_vertex_array_object_id(0) 7881 , m_vertex_buffer_id(0) 7882 { 7883 /* Nothing to be done here */ 7884 } 7885 7886 /* Methods inherited from SubcaseBase */ 7887 virtual long Setup() 7888 { 7889 /* Shaders code */ 7890 const char* const vertex_shader_code = "#version 400 core\n" 7891 "#extension GL_ARB_shader_image_load_store : require\n" 7892 "\n" 7893 "precision highp float;\n" 7894 "\n" 7895 "in vec4 vs_in_position;\n" 7896 "\n" 7897 "void main()\n" 7898 "{\n" 7899 " gl_Position = vs_in_position;\n" 7900 "}\n"; 7901 7902 const char* const fragment_shader_code = 7903 "#version 400 core\n" 7904 "#extension GL_ARB_shader_image_load_store : require\n" 7905 "\n" 7906 "precision highp float;\n" 7907 "\n" 7908 "layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n" 7909 "layout(rgba8) readonly uniform image2D u_complete_source_image;\n" 7910 "layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n" 7911 "layout(rgba8) readonly uniform image2D u_incomplete_source_image;\n" 7912 "\n" 7913 "void main()\n" 7914 "{\n" 7915 " vec4 complete_loaded_color = imageLoad (u_complete_source_image, ivec2(gl_FragCoord));\n" 7916 " vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n" 7917 7918 " imageStore(u_complete_destination_image,\n" 7919 " ivec2(gl_FragCoord),\n" 7920 " incomplete_loaded_color);\n" 7921 " imageStore(u_incomplete_destination_image,\n" 7922 " ivec2(gl_FragCoord),\n" 7923 " complete_loaded_color);\n" 7924 "\n" 7925 " discard;\n" 7926 "}\n"; 7927 7928 /* Vertex postions for "full screen" quad, made with triangle strip */ 7929 static const GLfloat m_vertex_buffer_data[] = { 7930 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */ 7931 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */ 7932 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */ 7933 1.0f, 1.0f, 0.0f, 1.0f, /* right top */ 7934 }; 7935 7936 /* Result of BuildProgram operation */ 7937 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */ 7938 7939 /* Clean previous error */ 7940 glGetError(); 7941 7942 m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth())); 7943 7944 /* Prepare textures */ 7945 GLU_EXPECT_NO_ERROR( 7946 Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id), 7947 "Create2DRGBA8CompleteTexture"); 7948 GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id), 7949 "Create2DRGBA8CompleteTexture"); 7950 GLU_EXPECT_NO_ERROR( 7951 Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id), 7952 "Create2DRGBA8IncompleteTexture"); 7953 GLU_EXPECT_NO_ERROR( 7954 Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id), 7955 "Create2DRGBA8IncompleteTexture"); 7956 7957 /* Prepare buffer with vertex positions of "full screen" quad" */ 7958 glGenBuffers(1, &m_vertex_buffer_id); 7959 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers"); 7960 7961 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id); 7962 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer"); 7963 7964 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW); 7965 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData"); 7966 7967 /* Generate vertex array object */ 7968 glGenVertexArrays(1, &m_vertex_array_object_id); 7969 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays"); 7970 7971 /* Prepare program object */ 7972 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */, 7973 fragment_shader_code, &is_program_correct); 7974 7975 if (false == is_program_correct) 7976 { 7977 return ERROR; 7978 } 7979 7980 /* Done */ 7981 return NO_ERROR; 7982 } 7983 7984 virtual long Cleanup() 7985 { 7986 /* Reset OpenGL state */ 7987 glBindBuffer(GL_ARRAY_BUFFER, 0); 7988 glBindTexture(GL_TEXTURE_2D, 0); 7989 glBindVertexArray(0); 7990 glUseProgram(0); 7991 7992 /* Delete program */ 7993 if (0 != m_program_id) 7994 { 7995 glDeleteProgram(m_program_id); 7996 m_program_id = 0; 7997 } 7998 7999 /* Delete textures */ 8000 if (0 != m_complete_destination_texture_id) 8001 { 8002 glDeleteTextures(1, &m_complete_destination_texture_id); 8003 m_complete_destination_texture_id = 0; 8004 } 8005 8006 if (0 != m_complete_source_texture_id) 8007 { 8008 glDeleteTextures(1, &m_complete_source_texture_id); 8009 m_complete_source_texture_id = 0; 8010 } 8011 8012 if (0 != m_incomplete_destination_texture_id) 8013 { 8014 glDeleteTextures(1, &m_incomplete_destination_texture_id); 8015 m_incomplete_destination_texture_id = 0; 8016 } 8017 8018 if (0 != m_incomplete_source_texture_id) 8019 { 8020 glDeleteTextures(1, &m_incomplete_source_texture_id); 8021 m_incomplete_source_texture_id = 0; 8022 } 8023 8024 /* Delete vertex array object */ 8025 if (0 != m_vertex_array_object_id) 8026 { 8027 glDeleteVertexArrays(1, &m_vertex_array_object_id); 8028 m_vertex_array_object_id = 0; 8029 } 8030 8031 /* Delete buffer */ 8032 if (0 != m_vertex_buffer_id) 8033 { 8034 glDeleteBuffers(1, &m_vertex_buffer_id); 8035 m_vertex_buffer_id = 0; 8036 } 8037 8038 /* Done */ 8039 return NO_ERROR; 8040 } 8041 8042 virtual long Run() 8043 { 8044 bool result = true; 8045 8046 /* Copy textures data with imageLoad() and imageStore() operations */ 8047 Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id, 8048 m_complete_source_texture_id, m_incomplete_source_texture_id); 8049 8050 glMemoryBarrier(GL_ALL_BARRIER_BITS); 8051 8052 /* Verify that store to "incomplete destination" was ignored */ 8053 if (true == 8054 CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number)) 8055 { 8056 m_context.getTestContext().getLog() 8057 << tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture" 8058 << tcu::TestLog::EndMessage; 8059 8060 result = false; 8061 } 8062 8063 /* Verify that load from "incomplete source" returned 0 */ 8064 if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id)) 8065 { 8066 m_context.getTestContext().getLog() 8067 << tcu::TestLog::Message 8068 << "Problem with imageLoad, operation returned non 0 result for incomplete texture" 8069 << tcu::TestLog::EndMessage; 8070 8071 result = false; 8072 } 8073 8074 if (false == result) 8075 { 8076 return ERROR; 8077 } 8078 8079 /* Done */ 8080 return NO_ERROR; 8081 } 8082 8083private: 8084 /* Private methods */ 8085 8086 /** Bind texture to image unit and sets image uniform to that unit 8087 * 8088 * @param program_id Program object id 8089 * @param texture_id Texture id 8090 * @param level Texture level 8091 * @param image_unit Index of image unit 8092 * @param uniform_name Name of image uniform 8093 **/ 8094 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit, const char* uniform_name) 8095 { 8096 /* Uniform location and invalid value */ 8097 static const GLint invalid_uniform_location = -1; 8098 GLint image_uniform_location = 0; 8099 8100 /* Get uniform location */ 8101 image_uniform_location = glGetUniformLocation(program_id, uniform_name); 8102 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation"); 8103 if (invalid_uniform_location == image_uniform_location) 8104 { 8105 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__); 8106 } 8107 8108 /* Bind texture to image unit */ 8109 glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8); 8110 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture"); 8111 8112 /* Set uniform to image unit */ 8113 glUniform1i(image_uniform_location, image_unit); 8114 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 8115 } 8116 8117 /** Check if texture is filled with black color, zeros 8118 * 8119 * @param texture_id Id of texture object 8120 * 8121 * @return true when texture is fully black, false otherwise 8122 **/ 8123 bool CheckIfTextureIsBlack(GLuint texture_id) 8124 { 8125 /* Constants to calculate size of texture */ 8126 static const GLuint n_components = 4; /* RGBA */ 8127 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components; 8128 8129 /* Storage for texture data */ 8130 std::vector<GLubyte> black_texture_data; 8131 std::vector<GLubyte> texture_data; 8132 8133 /* Allocate memory */ 8134 black_texture_data.resize(texture_data_size); 8135 texture_data.resize(texture_data_size); 8136 8137 /* Set all texels to black */ 8138 for (GLuint i = 0; i < texture_data_size; ++i) 8139 { 8140 black_texture_data[i] = 0; 8141 } 8142 8143 /* Bind texture */ 8144 glBindTexture(GL_TEXTURE_2D, texture_id); 8145 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 8146 8147 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); 8148 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 8149 8150 /* Compare texels */ 8151 return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size)); 8152 } 8153 8154 /** Check if texture was modified 8155 * 8156 * @param texture_id Id of texture object 8157 * @param nagic_number Magic number that was to create texture 8158 * 8159 * @return true if texture contents match expected values, false otherwise 8160 **/ 8161 bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number) 8162 { 8163 /* Constants to calculate size of texture */ 8164 static const GLuint n_components = 4; /* RGBA */ 8165 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components; 8166 8167 /* Storage for texture data */ 8168 std::vector<GLubyte> expected_texture_data; 8169 std::vector<GLubyte> texture_data; 8170 8171 /* Allocate memory */ 8172 expected_texture_data.resize(texture_data_size); 8173 texture_data.resize(texture_data_size); 8174 8175 /* Prepare expected texels */ 8176 for (GLuint y = 0; y < m_texture_edge; ++y) 8177 { 8178 const GLuint line_offset = y * m_texture_edge * n_components; 8179 8180 for (GLuint x = 0; x < m_texture_edge; ++x) 8181 { 8182 const GLuint texel_offset = x * n_components + line_offset; 8183 8184 SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), 8185 magic_number); 8186 } 8187 } 8188 8189 /* Bind texture */ 8190 glBindTexture(GL_TEXTURE_2D, texture_id); 8191 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 8192 8193 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); 8194 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 8195 8196 /* Compare texels, true when textures are different */ 8197 return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size)); 8198 } 8199 8200 /** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations 8201 * 8202 * @param complete_destination_texture_id Id of "complete destination" texture object 8203 * @param incomplete_destination_texture_id Id of "incomplete destination" texture object 8204 * @param complete_source_texture_id Id of "complete source" texture object 8205 * @param incomplete_source_texture_id Id of "incomplete source" texture object 8206 **/ 8207 void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id, 8208 GLuint complete_source_texture_id, GLuint incomplete_source_texture_id) 8209 { 8210 /* Uniform names */ 8211 static const char* const complete_destination_image_uniform_name = "u_complete_destination_image"; 8212 static const char* const complete_source_image_uniform_name = "u_complete_source_image"; 8213 static const char* const incomplete_destination_image_uniform_name = "u_incomplete_destination_image"; 8214 static const char* const incomplete_source_image_uniform_name = "u_incomplete_source_image"; 8215 8216 /* Attribute name */ 8217 static const char* const position_attribute_name = "vs_in_position"; 8218 8219 /* Attribute location and invalid value */ 8220 static const GLint invalid_attribute_location = -1; 8221 GLint position_attribute_location = 0; 8222 8223 /* Set current program */ 8224 glUseProgram(m_program_id); 8225 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram"); 8226 8227 /* Bind vertex array object */ 8228 glBindVertexArray(m_vertex_array_object_id); 8229 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray"); 8230 8231 /* Bind buffer with quad vertex positions */ 8232 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id); 8233 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer"); 8234 8235 /* Setup position attribute */ 8236 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name); 8237 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation"); 8238 if (invalid_attribute_location == position_attribute_location) 8239 { 8240 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__, 8241 __LINE__); 8242 } 8243 8244 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0); 8245 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer"); 8246 8247 glEnableVertexAttribArray(position_attribute_location); 8248 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray"); 8249 8250 /* Setup textures as source and destination images */ 8251 BindTextureToImage(m_program_id, complete_destination_texture_id, 8252 0 /* texture level */, 0 /* image_unit */, 8253 complete_destination_image_uniform_name); 8254 BindTextureToImage(m_program_id, complete_source_texture_id, 8255 0 /* texture level */, 1 /* image_unit */, 8256 complete_source_image_uniform_name); 8257 BindTextureToImage(m_program_id, incomplete_destination_texture_id, 8258 2 /* texture level */, 2 /* image_unit */, 8259 incomplete_destination_image_uniform_name); 8260 BindTextureToImage(m_program_id, incomplete_source_texture_id, 8261 2 /* texture level */, 3 /* image_unit */, 8262 incomplete_source_image_uniform_name); 8263 8264 /* Execute draw */ 8265 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */); 8266 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 8267 } 8268 8269 /** Create complete 2D RGBA8 texture. 8270 * 8271 * @param magic_number Magic number of texture 8272 * @param out_texture_id Id of created texture, not modified if operation fails 8273 * 8274 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 8275 **/ 8276 GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint& out_texture_id) 8277 { 8278 /* Constants to calculate size of texture */ 8279 static const GLuint n_components = 4; /* RGBA */ 8280 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components; 8281 8282 /* Error code */ 8283 GLenum err = 0; 8284 8285 /* Texture id */ 8286 GLuint texture_id = 0; 8287 8288 /* Prepare storage for texture data */ 8289 std::vector<GLubyte> texture_data; 8290 texture_data.resize(texture_data_size); 8291 8292 /* Prepare texture data */ 8293 for (GLuint y = 0; y < m_texture_edge; ++y) 8294 { 8295 const GLuint line_offset = y * m_texture_edge * n_components; 8296 8297 for (GLuint x = 0; x < m_texture_edge; ++x) 8298 { 8299 const GLuint texel_offset = x * n_components + line_offset; 8300 8301 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number); 8302 } 8303 } 8304 8305 /* Generate texture */ 8306 glGenTextures(1, &texture_id); 8307 err = glGetError(); 8308 if (GL_NO_ERROR != err) 8309 { 8310 return err; 8311 } 8312 8313 /* Bind texture */ 8314 glBindTexture(GL_TEXTURE_2D, texture_id); 8315 err = glGetError(); 8316 if (GL_NO_ERROR != err) 8317 { 8318 glDeleteTextures(1, &texture_id); 8319 return err; 8320 } 8321 8322 /* Allocate storage and fill texture */ 8323 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA, 8324 GL_UNSIGNED_BYTE, &texture_data[0]); 8325 err = glGetError(); 8326 if (GL_NO_ERROR != err) 8327 { 8328 glDeleteTextures(1, &texture_id); 8329 return err; 8330 } 8331 8332 /* Make texture complete */ 8333 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 8334 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 8335 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 8336 err = glGetError(); 8337 if (GL_NO_ERROR != err) 8338 { 8339 glDeleteTextures(1, &texture_id); 8340 return err; 8341 } 8342 8343 /* Set out_texture_id */ 8344 out_texture_id = texture_id; 8345 8346 /* Done */ 8347 return GL_NO_ERROR; 8348 } 8349 8350 /** Create incomplete 2D RGBA8 texture 8351 * 8352 * @param magic_number Magic number of texture 8353 * @param out_texture_id Id of created texture, not modified if operation fails 8354 * 8355 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 8356 **/ 8357 GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint& out_texture_id) 8358 { 8359 /* Constants to calculate size of texture */ 8360 static const GLuint n_components = 4; /* RGBA */ 8361 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components; 8362 8363 /* Error code */ 8364 GLenum err = 0; 8365 8366 /* Texture id */ 8367 GLuint texture_id = 0; 8368 8369 /* Prepare storage for texture data */ 8370 std::vector<GLubyte> texture_data; 8371 texture_data.resize(texture_data_size); 8372 8373 /* Prepare texture data */ 8374 for (GLuint y = 0; y < m_texture_edge; ++y) 8375 { 8376 const GLuint line_offset = y * m_texture_edge * n_components; 8377 8378 for (GLuint x = 0; x < m_texture_edge; ++x) 8379 { 8380 const GLuint texel_offset = x * n_components + line_offset; 8381 8382 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number); 8383 } 8384 } 8385 8386 /* Generate texture */ 8387 glGenTextures(1, &texture_id); 8388 err = glGetError(); 8389 if (GL_NO_ERROR != err) 8390 { 8391 return err; 8392 } 8393 8394 /* Bind texture */ 8395 glBindTexture(GL_TEXTURE_2D, texture_id); 8396 err = glGetError(); 8397 if (GL_NO_ERROR != err) 8398 { 8399 glDeleteTextures(1, &texture_id); 8400 return err; 8401 } 8402 8403 /* Allocate storage and fill texture */ 8404 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA, 8405 GL_UNSIGNED_BYTE, &texture_data[0]); 8406 err = glGetError(); 8407 if (GL_NO_ERROR != err) 8408 { 8409 glDeleteTextures(1, &texture_id); 8410 return err; 8411 } 8412 8413 /* Make texture incomplete */ 8414 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 8415 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7); 8416 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); 8417 err = glGetError(); 8418 if (GL_NO_ERROR != err) 8419 { 8420 glDeleteTextures(1, &texture_id); 8421 return err; 8422 } 8423 8424 /* Set out_texture_id */ 8425 out_texture_id = texture_id; 8426 8427 /* Done */ 8428 return GL_NO_ERROR; 8429 } 8430 8431 /** Prepare "unique" texels. 8432 * Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc]. 8433 * 8434 * @param texel Storage of texel 8435 * @param x_coordinate X coordiante of texel 8436 * @param y_coordinate Y coordinate of texel 8437 * @param magic_number Magic number of texture 8438 **/ 8439 void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number) 8440 { 8441 texel[0] = x_coordinate; 8442 texel[1] = y_coordinate; 8443 texel[2] = magic_number; 8444 texel[3] = 0xcc; 8445 } 8446}; 8447 8448/** Test "Refer to the same image unit using multiple uniforms", description follows. 8449 * 8450 * Steps: 8451 * - prepare program object, see details below, 8452 * - prepare 2D R32I texture, width should be equal to the number of image 8453 * uniforms used by program object, height should be 2, fill first row with 8454 * unique values, fill second row with zeros, 8455 * - bind texture to first image unit, 8456 * - set all image uniforms to first image unit, 8457 * - execute program for a single vertex, 8458 * - verify that: 8459 * - values in first row were negated, 8460 * - values from first row were copied to second row, 8461 * 8462 * Repeat steps to test all shader stages that support at least 2 image 8463 * uniforms. 8464 * 8465 * Program has to contain all necessary shader stages. Use boilerplate shaders 8466 * for shader stages that are not important for the test. 8467 * 8468 * Tested shader stage should: 8469 * - Use as many different image formats as possible, image formats compatible 8470 * with R32I: 8471 * * rg16f 8472 * * r11f_g11f_b10f 8473 * * r32f 8474 * * rgb10_a2ui 8475 * * rgba8ui 8476 * * rg16ui 8477 * * r32ui 8478 * * rgba8i 8479 * * rg16i 8480 * * r32i 8481 * * rgb10_a2 8482 * * rgba8 8483 * * rg16 8484 * * rgba8_snorm 8485 * * rg16_snorm. 8486 * - Declare maximum allowed number of image uniforms, 8487 * 8488 * layout(format) uniform gimage2D u_image; 8489 * 8490 * where <format> is selected image format, <gimage2D> is type of 2D image 8491 * compatible with <format> and <u_image> is unique name of uniform. 8492 * Note that image uniforms cannot be declared as array, due to different image 8493 * formats. Therefore separate uniforms have to be used. 8494 * - Include following code snippet: 8495 * for (int i = 0; i < gl_Max*ImageUniforms; ++i) 8496 * { 8497 * vec row_1_coord(i,0); 8498 * vec row_2_coord(i,1); 8499 * 8500 * row_1_value = imageLoad(u_image[i], row_1_coord); 8501 * imageStore(u_image[i], row_1_coord, -row_1_value); 8502 * imageStore(u_image[i], row_2_coord, row_1_value); 8503 * } 8504 * where gl_Max*ImageUniforms is the constant corresponding to tested shader 8505 * stage. 8506 **/ 8507class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase 8508{ 8509private: 8510 /* Types */ 8511 /** Details of image format 8512 * 8513 **/ 8514 struct imageFormatDetails 8515 { 8516 typedef bool (*verificationRoutine)(GLint, GLint, GLint); 8517 8518 const char* m_image_format; 8519 const char* m_image_type; 8520 const char* m_color_type; 8521 GLenum m_image_unit_format; 8522 verificationRoutine m_verification_routine; 8523 }; 8524 8525 template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)> 8526 struct Masks 8527 { 8528 /** Get mask of bits used to store in bit-field 8529 * 8530 * @return Mask 8531 **/ 8532 static inline T RawMask() 8533 { 8534 static const T mask = ValueMask() << OFFSET; 8535 8536 return mask; 8537 } 8538 8539 /** Get mask of bits used to store value. 8540 * 8541 * @return Mask 8542 **/ 8543 static inline T ValueMask() 8544 { 8545 static const T mask = (1 << SIZE) - 1; 8546 8547 return mask; 8548 } 8549 8550 /** Get offset. 8551 * 8552 * @return offset 8553 **/ 8554 static inline T Offset() 8555 { 8556 return OFFSET; 8557 } 8558 }; 8559 8560 template <typename T, GLuint SIZE, GLuint OFFSET> 8561 struct Masks<T, SIZE, OFFSET, false> 8562 { 8563 /** Get mask of bits used to store in bit-field 8564 * 8565 * @return Mask 8566 **/ 8567 static inline T RawMask() 8568 { 8569 DE_ASSERT(DE_FALSE && "Shouldn't be called"); 8570 return 0; 8571 } 8572 8573 /** Get mask of bits used to store value. 8574 * 8575 * @return Mask 8576 **/ 8577 static inline T ValueMask() 8578 { 8579 DE_ASSERT(DE_FALSE && "Shouldn't be called"); 8580 return 0; 8581 } 8582 8583 /** Get offset. 8584 * 8585 * @return offset 8586 **/ 8587 static inline T Offset() 8588 { 8589 DE_ASSERT(DE_FALSE && "Shouldn't be called"); 8590 return 0; 8591 } 8592 }; 8593 8594 /** Template class for accessing integer values stored in bit-fields 8595 * 8596 **/ 8597 template <typename T, GLuint SIZE, GLuint OFFSET> 8598 class Integer 8599 { 8600 public: 8601 /** Constructor 8602 * 8603 **/ 8604 Integer(T raw) : m_raw(raw) 8605 { 8606 } 8607 8608 /** Extract value from bit-field 8609 * 8610 * @return Value 8611 **/ 8612 T Get() const 8613 { 8614 const T mask = Masks<T, SIZE, OFFSET>::RawMask(); 8615 8616 const T bits = m_raw & mask; 8617 const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset(); 8618 8619 return result; 8620 } 8621 8622 /** Extract value from bit-field and negate it 8623 * 8624 * @return Negated value 8625 **/ 8626 T GetNegated() const 8627 { 8628 const T mask = Masks<T, SIZE, OFFSET>::ValueMask(); 8629 const T value = Get(); 8630 8631 return Clamp((~value) + 1) & mask; 8632 } 8633 8634 T Clamp(T n) const 8635 { 8636 const bool isUnsigned = (T(0) < T(-1)); 8637 const T min = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1))); 8638 const T max = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L); 8639 const T x = n > max ? max : n; 8640 return x < min ? min : x; 8641 } 8642 8643 private: 8644 T m_raw; 8645 }; 8646 8647 /* Enums */ 8648 /** Shader stage identification 8649 * 8650 **/ 8651 enum shaderStage 8652 { 8653 fragmentShaderStage = 2, 8654 geometryShaderStage = 4, 8655 tesselationControlShaderStage = 8, 8656 tesselationEvalutaionShaderStage = 16, 8657 vertexShaderStage = 32, 8658 }; 8659 8660 /** Test result 8661 * 8662 **/ 8663 enum testResult 8664 { 8665 testFailed = -1, 8666 testNotSupported = 1, 8667 testPassed = 0 8668 }; 8669 8670 /* Constants */ 8671 static const GLint m_min_required_image_uniforms = 2; 8672 8673 /* Fields */ 8674 GLuint m_program_to_test_fs_stage_id; 8675 GLuint m_program_to_test_gs_stage_id; 8676 GLuint m_program_to_test_tcs_stage_id; 8677 GLuint m_program_to_test_tes_stage_id; 8678 GLuint m_program_to_test_vs_stage_id; 8679 GLuint m_texture_to_test_fs_stage_id; 8680 GLuint m_texture_to_test_gs_stage_id; 8681 GLuint m_texture_to_test_tcs_stage_id; 8682 GLuint m_texture_to_test_tes_stage_id; 8683 GLuint m_texture_to_test_vs_stage_id; 8684 GLuint m_vertex_array_object_id; 8685 8686public: 8687 /* Constructor */ 8688 ImageLoadStoreMultipleUniformsTest() 8689 : m_program_to_test_fs_stage_id(0) 8690 , m_program_to_test_gs_stage_id(0) 8691 , m_program_to_test_tcs_stage_id(0) 8692 , m_program_to_test_tes_stage_id(0) 8693 , m_program_to_test_vs_stage_id(0) 8694 , m_texture_to_test_fs_stage_id(0) 8695 , m_texture_to_test_gs_stage_id(0) 8696 , m_texture_to_test_tcs_stage_id(0) 8697 , m_texture_to_test_tes_stage_id(0) 8698 , m_texture_to_test_vs_stage_id(0) 8699 , m_vertex_array_object_id(0) 8700 { 8701 /* Nothing to be done here */ 8702 } 8703 8704 /* Methods inherited from SubcaseBase */ 8705 virtual long Setup() 8706 { 8707 /* Prepare programs */ 8708 m_program_to_test_fs_stage_id = buildProgramToTestShaderStage(fragmentShaderStage); 8709 m_program_to_test_gs_stage_id = buildProgramToTestShaderStage(geometryShaderStage); 8710 m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage); 8711 m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage); 8712 m_program_to_test_vs_stage_id = buildProgramToTestShaderStage(vertexShaderStage); 8713 8714 /* Prepare textures */ 8715 m_texture_to_test_fs_stage_id = createTextureToTestShaderStage(fragmentShaderStage); 8716 m_texture_to_test_gs_stage_id = createTextureToTestShaderStage(geometryShaderStage); 8717 m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage); 8718 m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage); 8719 m_texture_to_test_vs_stage_id = createTextureToTestShaderStage(vertexShaderStage); 8720 8721 /* Generate vertex array object */ 8722 glGenVertexArrays(1, &m_vertex_array_object_id); 8723 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays"); 8724 8725 /* Bind vertex array object */ 8726 glBindVertexArray(m_vertex_array_object_id); 8727 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray"); 8728 8729 /* Set vertices number for patches */ 8730 glPatchParameteri(GL_PATCH_VERTICES, 1); 8731 8732 /* Done */ 8733 return NO_ERROR; 8734 } 8735 8736 virtual long Cleanup() 8737 { 8738 glUseProgram(0); 8739 8740 /* Delete programs */ 8741 if (0 != m_program_to_test_fs_stage_id) 8742 { 8743 glDeleteProgram(m_program_to_test_fs_stage_id); 8744 m_program_to_test_fs_stage_id = 0; 8745 } 8746 8747 if (0 != m_program_to_test_gs_stage_id) 8748 { 8749 glDeleteProgram(m_program_to_test_gs_stage_id); 8750 m_program_to_test_gs_stage_id = 0; 8751 } 8752 8753 if (0 != m_program_to_test_tcs_stage_id) 8754 { 8755 glDeleteProgram(m_program_to_test_tcs_stage_id); 8756 m_program_to_test_tcs_stage_id = 0; 8757 } 8758 8759 if (0 != m_program_to_test_tes_stage_id) 8760 { 8761 glDeleteProgram(m_program_to_test_tes_stage_id); 8762 m_program_to_test_tes_stage_id = 0; 8763 } 8764 8765 if (0 != m_program_to_test_vs_stage_id) 8766 { 8767 glDeleteProgram(m_program_to_test_vs_stage_id); 8768 m_program_to_test_vs_stage_id = 0; 8769 } 8770 8771 /* Delete textures */ 8772 if (0 != m_texture_to_test_fs_stage_id) 8773 { 8774 glDeleteTextures(1, &m_texture_to_test_fs_stage_id); 8775 m_texture_to_test_fs_stage_id = 0; 8776 } 8777 8778 if (0 != m_texture_to_test_gs_stage_id) 8779 { 8780 glDeleteTextures(1, &m_texture_to_test_gs_stage_id); 8781 m_texture_to_test_gs_stage_id = 0; 8782 } 8783 8784 if (0 != m_texture_to_test_tcs_stage_id) 8785 { 8786 glDeleteTextures(1, &m_texture_to_test_tcs_stage_id); 8787 m_texture_to_test_tcs_stage_id = 0; 8788 } 8789 8790 if (0 != m_texture_to_test_tes_stage_id) 8791 { 8792 glDeleteTextures(1, &m_texture_to_test_tes_stage_id); 8793 m_texture_to_test_tes_stage_id = 0; 8794 } 8795 8796 if (0 != m_texture_to_test_vs_stage_id) 8797 { 8798 glDeleteTextures(1, &m_texture_to_test_vs_stage_id); 8799 m_texture_to_test_vs_stage_id = 0; 8800 } 8801 8802 /* Delete vertex array object id */ 8803 if (0 != m_vertex_array_object_id) 8804 { 8805 glDeleteVertexArrays(1, &m_vertex_array_object_id); 8806 m_vertex_array_object_id = 0; 8807 } 8808 8809 /* Done */ 8810 return NO_ERROR; 8811 } 8812 8813 virtual long Run() 8814 { 8815 bool result = true; 8816 8817 if (testFailed == testShaderStage(fragmentShaderStage)) 8818 { 8819 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with fragment shader stage!" 8820 << tcu::TestLog::EndMessage; 8821 8822 result = false; 8823 } 8824 8825 if (testFailed == testShaderStage(geometryShaderStage)) 8826 { 8827 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with geometry shader stage!" 8828 << tcu::TestLog::EndMessage; 8829 8830 result = false; 8831 } 8832 8833 if (testFailed == testShaderStage(tesselationControlShaderStage)) 8834 { 8835 m_context.getTestContext().getLog() << tcu::TestLog::Message 8836 << "Problems with tesselation control shader stage!" 8837 << tcu::TestLog::EndMessage; 8838 8839 result = false; 8840 } 8841 8842 if (testFailed == testShaderStage(tesselationEvalutaionShaderStage)) 8843 { 8844 m_context.getTestContext().getLog() << tcu::TestLog::Message 8845 << "Problems with tesselation evaluation shader stage!" 8846 << tcu::TestLog::EndMessage; 8847 8848 result = false; 8849 } 8850 8851 if (testFailed == testShaderStage(vertexShaderStage)) 8852 { 8853 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with vertex shader stage!" 8854 << tcu::TestLog::EndMessage; 8855 8856 result = false; 8857 } 8858 8859 if (false == result) 8860 { 8861 return ERROR; 8862 } 8863 8864 /* Done */ 8865 return NO_ERROR; 8866 } 8867 8868private: 8869 /* Static routines */ 8870 /** Provide image format details for given index 8871 * 8872 * @param index Index 8873 * @param out_details Image format detail instance 8874 **/ 8875 static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails& out_details) 8876 { 8877 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = { 8878 "r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger 8879 }; 8880 8881 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = { 8882 { "rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort> }, 8883 { "r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F, 8884 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> }, 8885 { "r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint> }, 8886 { "rgb10_a2", "image2D", "vec4", GL_RGB10_A2, 8887 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> }, 8888 { "rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> }, 8889 { "rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> }, 8890 { "rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM, 8891 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte> }, 8892 { "rg16_snorm", "image2D", "vec4", GL_RG16_SNORM, 8893 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort> }, 8894 { "rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI, 8895 ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint> }, 8896 { "rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI, 8897 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint> }, 8898 { "rg16ui", "uimage2D", "uvec4", GL_RG16UI, 8899 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint> }, 8900 { "r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger }, 8901 { "rgba8i", "iimage2D", "ivec4", GL_RGBA8I, 8902 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint> }, 8903 { "rg16i", "iimage2D", "ivec4", GL_RG16I, 8904 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint> } 8905 }; 8906 8907 static const GLuint n_imageUniformFormatDetails = 8908 sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails); 8909 8910 if (n_imageUniformFormatDetails <= index) 8911 { 8912 out_details = default_format_details; 8913 } 8914 else 8915 { 8916 out_details = format_details[index]; 8917 } 8918 } 8919 8920 /** Write name of image uniform at given index to output stream 8921 * 8922 * @param stream Output stream 8923 * @param index Index 8924 **/ 8925 static void writeImageUniformNameToStream(std::ostream& stream, GLuint index) 8926 { 8927 /* u_image_0 */ 8928 stream << "u_image_" << index; 8929 } 8930 8931 /** Write name of variable used to store value loaded from image at given index to output stream 8932 * 8933 * @param stream Output stream 8934 * @param index Index 8935 **/ 8936 static void writeLoadedValueVariableNameToStream(std::ostream& stream, GLuint index) 8937 { 8938 /* loaded_value_0 */ 8939 stream << "loaded_value_" << index; 8940 } 8941 8942 /** Write name of variable used to store coordinate of texel at given row to output stream 8943 * 8944 * @param stream Output stream 8945 * @param index Index of image uniform 8946 * @param row Row of image 8947 **/ 8948 static void writeCoordinatesVariableNameToStream(std::ostream& stream, GLuint index, GLuint row) 8949 { 8950 /* row_0_coordinates_0 */ 8951 stream << "row_" << row << "_coordinates_" << index; 8952 } 8953 8954 struct imageUniformDeclaration 8955 { 8956 imageUniformDeclaration(GLuint index) : m_index(index) 8957 { 8958 } 8959 8960 GLuint m_index; 8961 }; 8962 8963 /** Write declaration of image uniform at given index to output stream 8964 * 8965 * @param stream Output stream 8966 * @param imageUniformDeclaration Declaration details 8967 * 8968 * @return stream 8969 **/ 8970 friend std::ostream& operator<<(std::ostream& stream, const imageUniformDeclaration& declaration) 8971 { 8972 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details; 8973 getImageUniformDeclarationDetails(declaration.m_index, format_details); 8974 8975 /* layout(r32f) uniform image2D u_image_0; */ 8976 stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " "; 8977 8978 ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index); 8979 8980 stream << ";"; 8981 8982 return stream; 8983 } 8984 8985 struct imageLoadCall 8986 { 8987 imageLoadCall(GLuint index) : m_index(index) 8988 { 8989 } 8990 8991 GLuint m_index; 8992 }; 8993 8994 /* Stream operators */ 8995 /** Write code that execute imageLoad routine for image at given index to output stream 8996 * 8997 * @param stream Output stream 8998 * @param load imageLoad call details 8999 * 9000 * @return stream 9001 **/ 9002 friend std::ostream& operator<<(std::ostream& stream, const imageLoadCall& load) 9003 { 9004 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details; 9005 getImageUniformDeclarationDetails(load.m_index, format_details); 9006 9007 /* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */ 9008 stream << format_details.m_color_type << " "; 9009 9010 writeLoadedValueVariableNameToStream(stream, load.m_index); 9011 9012 stream << " = imageLoad("; 9013 9014 writeImageUniformNameToStream(stream, load.m_index); 9015 9016 stream << ", "; 9017 9018 writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */); 9019 9020 stream << ");"; 9021 9022 return stream; 9023 } 9024 9025 struct imageStoreCall 9026 { 9027 imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row) 9028 { 9029 } 9030 9031 GLuint m_index; 9032 GLuint m_row; 9033 }; 9034 9035 /** Write code that execute imageStore to image at given index to output stream 9036 * 9037 * @param stream Output stream 9038 * @param store imageStore call details 9039 * 9040 * @return stream 9041 **/ 9042 friend std::ostream& operator<<(std::ostream& stream, const imageStoreCall& store) 9043 { 9044 /* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */ 9045 stream << "imageStore("; 9046 9047 writeImageUniformNameToStream(stream, store.m_index); 9048 9049 stream << ", "; 9050 9051 writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row); 9052 9053 if (0 == store.m_row) 9054 { 9055 stream << ", -"; 9056 } 9057 else 9058 { 9059 stream << ", "; 9060 } 9061 9062 writeLoadedValueVariableNameToStream(stream, store.m_index); 9063 stream << ");"; 9064 9065 return stream; 9066 } 9067 9068 struct coordinatesVariableDeclaration 9069 { 9070 coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row) 9071 { 9072 } 9073 GLuint m_index; 9074 GLuint m_row; 9075 }; 9076 9077 /** Write declaration of variable for coordinate at given row to output stream 9078 * 9079 * @param stream Output stream 9080 * @param declaration Declaration details 9081 * 9082 * @return stream 9083 **/ 9084 friend std::ostream& operator<<(std::ostream& stream, const coordinatesVariableDeclaration& declaration) 9085 { 9086 stream << "const ivec2 "; 9087 9088 writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row); 9089 9090 stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");"; 9091 9092 return stream; 9093 } 9094 9095 /* Methods */ 9096 /** Build program to test specified shader stage 9097 * 9098 * Throws exception in case of any failure 9099 * 9100 * @param stage Stage id 9101 * 9102 * @return Program id 9103 **/ 9104 GLuint buildProgramToTestShaderStage(shaderStage stage) 9105 { 9106 static const char* const boilerplate_fragment_shader_code = 9107 "#version 400 core\n" 9108 "#extension GL_ARB_shader_image_load_store : require\n" 9109 "\n" 9110 "precision highp float;\n" 9111 "\n" 9112 "void main()\n" 9113 "{\n" 9114 " discard;\n" 9115 "}\n"; 9116 9117 static const char* const boilerplate_tesselation_evaluation_shader_code = 9118 "#version 400 core\n" 9119 "#extension GL_ARB_shader_image_load_store : require\n" 9120 "\n" 9121 "precision highp float;\n" 9122 "\n" 9123 "layout(quads, equal_spacing, ccw) in;\n" 9124 "\n" 9125 "void main()\n" 9126 "{\n" 9127 "\n" 9128 "}\n"; 9129 9130 static const char* const boilerplate_vertex_shader_code = 9131 "#version 400 core\n" 9132 "#extension GL_ARB_shader_image_load_store : require\n" 9133 "\n" 9134 "precision highp float;\n" 9135 "\n" 9136 "layout(location = 0) in vec4 i_position;\n" 9137 "\n" 9138 "void main()\n" 9139 "{\n" 9140 " gl_Position = i_position;\n" 9141 "}\n"; 9142 9143 const char* fragment_shader_code = boilerplate_fragment_shader_code; 9144 const char* geometry_shader_code = 0; 9145 bool is_program_built = true; 9146 GLuint program_object_id = 0; 9147 const char* tesselation_control_shader_code = 0; 9148 const char* tesselation_evaluation_shader_code = 0; 9149 std::string tested_shader_stage_code; 9150 const char* vertex_shader_code = boilerplate_vertex_shader_code; 9151 9152 /* Get source code for tested shader stage */ 9153 prepareShaderForTestedShaderStage(stage, tested_shader_stage_code); 9154 9155 if (true == tested_shader_stage_code.empty()) 9156 { 9157 return 0; 9158 } 9159 9160 /* Set up source code for all required stages */ 9161 switch (stage) 9162 { 9163 case fragmentShaderStage: 9164 fragment_shader_code = tested_shader_stage_code.c_str(); 9165 break; 9166 9167 case geometryShaderStage: 9168 geometry_shader_code = tested_shader_stage_code.c_str(); 9169 break; 9170 9171 case tesselationControlShaderStage: 9172 tesselation_control_shader_code = tested_shader_stage_code.c_str(); 9173 tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code; 9174 break; 9175 9176 case tesselationEvalutaionShaderStage: 9177 tesselation_evaluation_shader_code = tested_shader_stage_code.c_str(); 9178 break; 9179 9180 case vertexShaderStage: 9181 vertex_shader_code = tested_shader_stage_code.c_str(); 9182 break; 9183 9184 default: 9185 TCU_FAIL("Invalid shader stage"); 9186 } 9187 9188 /* Build program */ 9189 program_object_id = 9190 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code, 9191 geometry_shader_code, fragment_shader_code, &is_program_built); 9192 9193 /* Check if program was built */ 9194 if (false == is_program_built) 9195 { 9196 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__); 9197 } 9198 9199 /* Done */ 9200 return program_object_id; 9201 } 9202 9203 /** Create texture to test given shader stage 9204 * 9205 * Throws exception in case of any failure 9206 * 9207 * @param stage Stage id 9208 * 9209 * @return Texture id 9210 **/ 9211 GLuint createTextureToTestShaderStage(shaderStage stage) 9212 { 9213 GLenum error = glGetError(); 9214 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage); 9215 GLuint texture_id = 0; 9216 std::vector<GLint> texture_data; 9217 9218 const GLsizei height = 2; 9219 const GLsizei width = max_image_uniforms; 9220 9221 if (m_min_required_image_uniforms > max_image_uniforms) 9222 { 9223 return 0; 9224 } 9225 9226 /* Generate texture id */ 9227 glGenTextures(1, &texture_id); 9228 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures"); 9229 9230 /* Bind texture */ 9231 glBindTexture(GL_TEXTURE_2D, texture_id); 9232 error = glGetError(); 9233 if (GL_NO_ERROR != error) 9234 { 9235 glDeleteTextures(1, &texture_id); 9236 GLU_EXPECT_NO_ERROR(error, "BindTexture"); 9237 } 9238 9239 /* Prepare storage for texture data */ 9240 texture_data.resize(width * height); 9241 for (GLint i = 0; i < max_image_uniforms; ++i) 9242 { 9243 texture_data[i] = getExpectedValue(i); 9244 texture_data[i + width] = 0; 9245 } 9246 9247 /* Create first level of texture */ 9248 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT, 9249 &texture_data[0]); 9250 error = glGetError(); 9251 if (GL_NO_ERROR != error) 9252 { 9253 glDeleteTextures(1, &texture_id); 9254 GLU_EXPECT_NO_ERROR(error, "TexImage2D"); 9255 } 9256 9257 /* Make texture complete */ 9258 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 9259 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 9260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 9261 error = glGetError(); 9262 if (GL_NO_ERROR != error) 9263 { 9264 glDeleteTextures(1, &texture_id); 9265 GLU_EXPECT_NO_ERROR(error, "TexParameteri"); 9266 } 9267 9268 /* Done */ 9269 return texture_id; 9270 } 9271 9272 /** Get value of texel for image at given index 9273 * 9274 * @param index Index of image uniform 9275 * 9276 * @return Value of texel 9277 **/ 9278 GLint getExpectedValue(GLint index) 9279 { 9280 // To fix denorm issues with r32f, rg16f and r11f_g11f_b10f 9281 // we set one bit in the exponent of each component of those pixel format 9282 return 0x40104200 + index; 9283 } 9284 9285 /** Get name of uniform at given index 9286 * 9287 * @param index Index of uniform 9288 * @param out_name Name of uniform 9289 **/ 9290 void getImageUniformName(GLuint index, std::string& out_name) 9291 { 9292 std::stringstream stream; 9293 9294 writeImageUniformNameToStream(stream, index); 9295 9296 out_name = stream.str(); 9297 } 9298 9299 /** Get maximum number of image uniforms allowed for given shader stage 9300 * 9301 * @param stage Stage id 9302 * 9303 * @return Maximum allowed image uniforms 9304 **/ 9305 GLint getMaximumImageUniformsForStage(shaderStage stage) 9306 { 9307 GLint max_image_uniforms = 0; 9308 GLenum pname = 0; 9309 9310 switch (stage) 9311 { 9312 case fragmentShaderStage: 9313 pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS; 9314 break; 9315 9316 case geometryShaderStage: 9317 pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS; 9318 break; 9319 9320 case tesselationControlShaderStage: 9321 pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS; 9322 break; 9323 9324 case tesselationEvalutaionShaderStage: 9325 pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS; 9326 break; 9327 9328 case vertexShaderStage: 9329 pname = GL_MAX_VERTEX_IMAGE_UNIFORMS; 9330 break; 9331 9332 default: 9333 TCU_FAIL("Invalid shader stage"); 9334 } 9335 9336 glGetIntegerv(pname, &max_image_uniforms); 9337 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv"); 9338 9339 return max_image_uniforms; 9340 } 9341 9342 /** Prepare source for tested shader stage 9343 * 9344 * @param stage Stage id 9345 * @param out_code Source code 9346 **/ 9347 void prepareShaderForTestedShaderStage(shaderStage stage, std::string& out_code) 9348 { 9349 GLint max_image_uniforms = getMaximumImageUniformsForStage(stage); 9350 const char* stage_specific_layout = ""; 9351 const char* stage_specific_predicate = "true"; 9352 std::stringstream stream; 9353 9354 if (m_min_required_image_uniforms > max_image_uniforms) 9355 { 9356 return; 9357 } 9358 9359 /* Expected result follows 9360 * 9361 * #version 400 core 9362 * #extension GL_ARB_shader_image_load_store : require 9363 * 9364 * precision highp float; 9365 * 9366 * stage_specific_layout goes here 9367 * 9368 * Uniform declarations go here 9369 * 9370 * void main() 9371 * { 9372 * const ivec2 row_0_coordinates(0, 0); 9373 * const ivec2 row_1_coordinates(0, 1); 9374 * 9375 * For each index <0, GL_MAX_*_IMAGE_UNIFORMS> 9376 * 9377 * vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates); 9378 * 9379 * imageStore(u_image_0, row_0_coordinates, -loaded_value_0); 9380 * imageStore(u_image_0, row_1_coordinates, loaded_value_0); 9381 * } 9382 */ 9383 9384 /* Get piece of code specific for stage */ 9385 switch (stage) 9386 { 9387 case fragmentShaderStage: 9388 break; 9389 9390 case geometryShaderStage: 9391 stage_specific_layout = "layout(points) in;\n" 9392 "layout(points, max_vertices = 1) out;\n" 9393 "\n"; 9394 break; 9395 9396 case tesselationControlShaderStage: 9397 stage_specific_layout = "layout(vertices = 4) out;\n" 9398 "\n"; 9399 stage_specific_predicate = "gl_InvocationID == 0"; 9400 break; 9401 9402 case tesselationEvalutaionShaderStage: 9403 stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n" 9404 "\n"; 9405 break; 9406 9407 case vertexShaderStage: 9408 break; 9409 9410 default: 9411 TCU_FAIL("Invalid shader stage"); 9412 } 9413 9414 /* Preamble */ 9415 stream << "#version 400 core\n" 9416 "#extension GL_ARB_shader_image_load_store : require\n" 9417 "\n" 9418 "precision highp float;\n" 9419 "\n" 9420 << stage_specific_layout; 9421 9422 /* Image uniforms declarations */ 9423 for (GLint i = 0; i < max_image_uniforms; ++i) 9424 { 9425 stream << imageUniformDeclaration(i) << "\n"; 9426 } 9427 9428 /* Main opening */ 9429 stream << "\n" 9430 "void main()\n" 9431 "{\n"; 9432 9433 stream << " if (" << stage_specific_predicate << ")\n"; 9434 stream << " {\n"; 9435 9436 /* imageLoad and imageStores for each uniform */ 9437 for (GLint i = 0; i < max_image_uniforms; ++i) 9438 { 9439 stream << " " << coordinatesVariableDeclaration(i, 0) << "\n" 9440 << " " << coordinatesVariableDeclaration(i, 1) << "\n" 9441 << "\n" 9442 << " " << imageLoadCall(i) << "\n" 9443 << "\n" 9444 << " " << imageStoreCall(i, 0) << "\n" 9445 << " " << imageStoreCall(i, 1) << "\n"; 9446 9447 if (max_image_uniforms > i + 1) 9448 { 9449 stream << "\n"; 9450 } 9451 } 9452 9453 stream << " }\n"; 9454 9455 /* Main closing */ 9456 stream << "}\n\n"; 9457 9458 /* Done */ 9459 out_code = stream.str(); 9460 } 9461 9462 /** Test given shader stage 9463 * 9464 * @param stage Stage id 9465 * 9466 * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms; 9467 * testFailed when test result is negative; 9468 * m_test_passed when test result is positive; 9469 **/ 9470 testResult testShaderStage(shaderStage stage) 9471 { 9472 std::string image_uniform_name; 9473 static const GLint invalid_uniform_location = -1; 9474 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage); 9475 GLenum primitive_mode = GL_POINTS; 9476 GLuint program_id = 0; 9477 testResult result = testPassed; 9478 std::vector<GLint> texture_data; 9479 GLuint texture_id = 0; 9480 9481 static const GLuint height = 2; 9482 const GLuint width = max_image_uniforms; 9483 9484 const GLuint positive_value_index = width; 9485 static const GLuint negated_value_index = 0; 9486 9487 if (m_min_required_image_uniforms > max_image_uniforms) 9488 { 9489 return testNotSupported; 9490 } 9491 9492 /* Select program and texture ids for given stage */ 9493 switch (stage) 9494 { 9495 case fragmentShaderStage: 9496 program_id = m_program_to_test_fs_stage_id; 9497 texture_id = m_texture_to_test_fs_stage_id; 9498 break; 9499 9500 case geometryShaderStage: 9501 program_id = m_program_to_test_gs_stage_id; 9502 texture_id = m_texture_to_test_gs_stage_id; 9503 break; 9504 9505 case tesselationControlShaderStage: 9506 primitive_mode = GL_PATCHES; 9507 program_id = m_program_to_test_tcs_stage_id; 9508 texture_id = m_texture_to_test_tcs_stage_id; 9509 break; 9510 9511 case tesselationEvalutaionShaderStage: 9512 primitive_mode = GL_PATCHES; 9513 program_id = m_program_to_test_tes_stage_id; 9514 texture_id = m_texture_to_test_tes_stage_id; 9515 break; 9516 9517 case vertexShaderStage: 9518 program_id = m_program_to_test_vs_stage_id; 9519 texture_id = m_texture_to_test_vs_stage_id; 9520 break; 9521 9522 default: 9523 TCU_FAIL("Invalid shader stage"); 9524 } 9525 9526 /* Set program */ 9527 glUseProgram(program_id); 9528 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram"); 9529 9530 /* Bind texture to image units */ 9531 for (GLint i = 0; i < max_image_uniforms; ++i) 9532 { 9533 imageFormatDetails format_details; 9534 getImageUniformDeclarationDetails(i, format_details); 9535 9536 glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */, 9537 GL_READ_WRITE, format_details.m_image_unit_format); 9538 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture"); 9539 } 9540 9541 /* Set all image uniforms to corresponding image units */ 9542 for (GLint i = 0; i < max_image_uniforms; ++i) 9543 { 9544 /* Get name */ 9545 getImageUniformName(i, image_uniform_name); 9546 9547 /* Get location */ 9548 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str()); 9549 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation"); 9550 9551 if (invalid_uniform_location == image_uniform_location) 9552 { 9553 throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__, 9554 __LINE__); 9555 } 9556 9557 /* Set uniform value */ 9558 glUniform1i(image_uniform_location, i /* image_unit */); 9559 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 9560 } 9561 9562 /* Execute draw */ 9563 glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */); 9564 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 9565 9566 glMemoryBarrier(GL_ALL_BARRIER_BITS); 9567 9568 texture_data.resize(width * height); 9569 9570 /* Get texture data */ 9571 glBindTexture(GL_TEXTURE_2D, texture_id); 9572 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 9573 9574 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]); 9575 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 9576 9577 /* Verify each image uniform */ 9578 for (GLint i = 0; i < max_image_uniforms; ++i) 9579 { 9580 imageFormatDetails format_details; 9581 getImageUniformDeclarationDetails(i, format_details); 9582 9583 if (false == 9584 format_details.m_verification_routine(getExpectedValue(i), texture_data[positive_value_index + i], 9585 texture_data[negated_value_index + i])) 9586 { 9587 m_context.getTestContext().getLog() 9588 << tcu::TestLog::Message << "Invalid result!" 9589 << " Image format: " << format_details.m_image_format << " Original value: " 9590 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i) 9591 << " Copied value: " 9592 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) 9593 << texture_data[positive_value_index + i] << " Negated value: " 9594 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) 9595 << texture_data[negated_value_index + i] << tcu::TestLog::EndMessage; 9596 9597 result = testFailed; 9598 } 9599 } 9600 9601 /* Done */ 9602 return result; 9603 } 9604 9605 /** Verifies if original_value, positive_value and negated_value match 9606 * 9607 * @tparam T Type used during verification process, it should match float values by size 9608 * 9609 * @param original_value Original value of texel, used when creating a texture 9610 * @param positive_value Value stored by shader as read 9611 * @param negated_value Value stored by shader after negation 9612 * 9613 * @return true if values match, false otherwise 9614 **/ 9615 template <typename T> 9616 static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value) 9617 { 9618 if (original_value != positive_value) 9619 { 9620 return false; 9621 } 9622 9623 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */ 9624 static const GLuint sign_bit_index = sizeof(T) * 8 - 1; /* 7, 15, 31 */ 9625 static const T sign_bit_mask = 1 << sign_bit_index; /* 0x80.. */ 9626 static const T sign_bit_inv_mask = (T)~sign_bit_mask; /* 0x7f.. */ 9627 9628 const T* positive_elements = (T*)&positive_value; 9629 const T* negated_elements = (T*)&negated_value; 9630 9631 for (GLuint i = 0; i < n_elements; ++i) 9632 { 9633 const T positive_element = positive_elements[i]; 9634 const T negated_element = negated_elements[i]; 9635 9636 const T positive_sign_bit = positive_element & sign_bit_mask; 9637 const T negated_sign_bit = negated_element & sign_bit_mask; 9638 9639 const T positive_data = positive_element & sign_bit_inv_mask; 9640 const T negated_data = negated_element & sign_bit_inv_mask; 9641 9642 /* Compare data bits */ 9643 if (positive_data != negated_data) 9644 { 9645 return false; 9646 } 9647 9648 /* Verify that sign bit is inverted */ 9649 if (positive_sign_bit == negated_sign_bit) 9650 { 9651 return false; 9652 } 9653 } 9654 9655 return true; 9656 } 9657 9658 /** Verifies if original_value, positive_value and negated_value match 9659 * 9660 * @tparam T Type used during verification process, it should match float values by size 9661 * 9662 * @param original_value Original value of texel, used when creating a texture 9663 * @param positive_value Value stored by shader as read 9664 * @param negated_value Value stored by shader after negation 9665 * 9666 * @return true if values match, false otherwise 9667 **/ 9668 template <typename T> 9669 static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value) 9670 { 9671 if (original_value != positive_value) 9672 { 9673 return false; 9674 } 9675 9676 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */ 9677 9678 const T* positive_elements = (T*)&positive_value; 9679 const T* negated_elements = (T*)&negated_value; 9680 9681 for (GLuint i = 0; i < n_elements; ++i) 9682 { 9683 const T positive_element = positive_elements[i]; 9684 const T negated_element = negated_elements[i]; 9685 9686 /* Compare data bits */ 9687 if (positive_element != -negated_element) 9688 { 9689 return false; 9690 } 9691 } 9692 9693 return true; 9694 } 9695 9696 /** Verifies if original_value, positive_value and negated_value match 9697 * 9698 * @tparam R Number of bits for red channel 9699 * @tparam G Number of bits for green channel 9700 * @tparam B Number of bits for blue channel 9701 * @tparam A Number of bits for alpha channel 9702 * 9703 * @param original_value Original value of texel, used when creating a texture 9704 * @param positive_value Value stored by shader as read 9705 * @param negated_value Value stored by shader after negation 9706 * 9707 * @return true if values match, false otherwise 9708 **/ 9709 template <GLuint R, GLuint G, GLuint B, GLuint A, typename T> 9710 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value) 9711 { 9712 if (original_value != positive_value) 9713 { 9714 return false; 9715 } 9716 9717 Integer<T, R, 0> positive_red(positive_value); 9718 Integer<T, R, 0> negated_red(negated_value); 9719 9720 Integer<T, G, R> positive_green(positive_value); 9721 Integer<T, G, R> negated_green(negated_value); 9722 9723 Integer<T, B, R + G> positive_blue(positive_value); 9724 Integer<T, B, R + G> negated_blue(negated_value); 9725 9726 Integer<T, A, R + G + B> positive_alpha(positive_value); 9727 Integer<T, A, R + G + B> negated_alpha(negated_value); 9728 9729 if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) || 9730 ((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) || 9731 ((0 != G) && (positive_green.GetNegated() != negated_green.Get())) || 9732 ((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get()))) 9733 { 9734 return false; 9735 } 9736 9737 return true; 9738 } 9739 9740 /** Verifies if original_value, positive_value and negated_value match 9741 * 9742 * @param original_value Original value of texel, used when creating a texture 9743 * @param positive_value Value stored by shader as read 9744 * @param negated_value Value stored by shader after negation 9745 * 9746 * @return true if values match, false otherwise 9747 **/ 9748 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value) 9749 { 9750 if (original_value != positive_value) 9751 { 9752 return false; 9753 } 9754 9755 if (positive_value != -negated_value) 9756 { 9757 return false; 9758 } 9759 9760 return true; 9761 } 9762 9763 /** Verifies if original_value, positive_value and negated_value match 9764 * 9765 * @param original_value Original value of texel, used when creating a texture 9766 * @param positive_value Value stored by shader as read 9767 * @param negated_value Value stored by shader after negation 9768 * 9769 * @return true if values match, false otherwise 9770 **/ 9771 template <typename T> 9772 static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value) 9773 { 9774 if (original_value != positive_value) 9775 { 9776 return false; 9777 } 9778 9779 if (0 != negated_value) 9780 { 9781 return false; 9782 } 9783 9784 return true; 9785 } 9786}; 9787 9788/** Test "Early fragment tests" description follows. 9789 * 9790 * BasicGLSLEarlyFragTests verifies that: 9791 * - early z test is applied when enabled, 9792 * - early z test is not applied when disabled. 9793 * 9794 * Proposed modifications: 9795 * - verify that early z test does not discard all fragments when enabled, 9796 * - verify that early stencil test is applied when enabled, 9797 * - verify that early stencil test does not discard all fragments when 9798 * enabled, 9799 * - verify that early stencil test is not applied when disabled. 9800 * 9801 * Steps: 9802 * - prepare 2 programs that store 1.0 at red channel to image in fragment 9803 * shader stage: 9804 * a) one program should enable early fragment tests 9805 * ("layout(early_fragment_tests) in;"), 9806 * b) second program should disable early fragment tests, 9807 * - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL 9808 * depth-stencil attachments, 9809 * - prepare 2D texture 64x64 R32F, 9810 * - enable depth test, 9811 * - verify that early z test is applied when enabled: 9812 * - use program enabling early fragment tests, 9813 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5, 9814 * - fill texture with zeros, 9815 * - bind texture to image uniform, 9816 * - draw "full screen" quad (left bottom corner at -1,-1 and right top 9817 * corner at 1,1) at z: 0.75 9818 * - verify that texture is still filled with zeros, 9819 * - verify that early z test does not discard all fragments: 9820 * - use program enabling early fragment tests, 9821 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5, 9822 * - fill texture with zeros, 9823 * - bind texture to image uniform, 9824 * - draw "full screen" quad at z: 0.25 9825 * - verify that texture is now filled with 1.0, 9826 * -verify that early z test is not applied when disabled: 9827 * - use program disabling early fragment tests, 9828 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5, 9829 * - fill texture with zeros, 9830 * - bind texture to image uniform, 9831 * - draw "full screen" quad at z: 0.75 9832 * - verify that texture is now filled with 1.0. 9833 * - disable depth test 9834 * - enable stencil test 9835 * - verify that early stencil test is applied when enabled: 9836 * - use program enabling early fragment tests, 9837 * - clean frame buffer with color: 0, stencil: 0 and depth 1, 9838 * - fill texture with zeros, 9839 * - set stencil test to: 9840 * - <func> to GL_LESS, 9841 * - <ref> to 128, 9842 * - <mask> 0xffffffff, 9843 * - bind texture to image uniform, 9844 * - draw "full screen" quad at z: 0, 9845 * - verify that texture is still filled with zeros, 9846 * - verify that early stencil test does not discard all fragments: 9847 * - use program enabling early fragment tests, 9848 * - clean frame buffer with color: 0, stencil: 128 and depth 1, 9849 * - fill texture with zeros, 9850 * - set stencil test to: 9851 * - <func> to GL_LESS, 9852 * - <ref> to 0, 9853 * - <mask> 0xffffffff, 9854 * - bind texture to image uniform, 9855 * - draw "full screen" quad at z: 0, 9856 * - verify that texture is now filled with 1.0, 9857 * - verify that early stencil test is not applied when disabled: 9858 * - use program disabling early fragment tests, 9859 * - clean frame buffer with color: 0, stencil: 0 and depth 1, 9860 * - fill texture with zeros, 9861 * - set stencil test to: 9862 * - <func> to GL_LESS, 9863 * - <ref> to 128, 9864 * - <mask> 0xffffffff, 9865 * - bind texture to image uniform, 9866 * - draw "full screen" quad at z: 0, 9867 * - verify that texture is now filled with 1.0 9868 **/ 9869class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase 9870{ 9871private: 9872 /* Constants */ 9873 GLuint m_image_edge; 9874 static const GLint m_invalid_uniform_location = -1; 9875 9876 /* Types */ 9877 /** Store id and uniform locations for a single program object 9878 * 9879 **/ 9880 struct programDetails 9881 { 9882 GLint m_depth_uniform_location; 9883 GLint m_image_uniform_location; 9884 GLuint m_program_id; 9885 9886 programDetails() 9887 : m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location) 9888 , m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location) 9889 , m_program_id(0) 9890 { 9891 /* Nothing to be done here */ 9892 } 9893 }; 9894 9895 /* Fileds */ 9896 /* Storage for texture data */ 9897 std::vector<GLfloat> m_clean_texture_data; 9898 std::vector<GLfloat> m_extracted_texture_data; 9899 9900 /* Program details */ 9901 programDetails m_disabled_early_tests; 9902 programDetails m_enabled_early_tests; 9903 9904 /* Ids of GL objects */ 9905 GLuint m_color_renderbuffer_id; 9906 GLuint m_depth_stencil_renderbuffer_id; 9907 GLuint m_framebuffer_id; 9908 GLuint m_texture_id; 9909 GLuint m_vertex_array_object_id; 9910 9911public: 9912 /* Constructor */ 9913 ImageLoadStoreEarlyFragmentTestsTest() 9914 : m_image_edge(0) 9915 , m_color_renderbuffer_id(0) 9916 , m_depth_stencil_renderbuffer_id(0) 9917 , m_framebuffer_id(0) 9918 , m_texture_id(0) 9919 , m_vertex_array_object_id(0) 9920 { 9921 /* Nothing to be done here */ 9922 } 9923 9924 /* Methods inherited from SubcaseBase */ 9925 virtual long Cleanup() 9926 { 9927 /* Restore defaults */ 9928 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 9929 glBindRenderbuffer(GL_RENDERBUFFER, 0); 9930 glBindTexture(GL_TEXTURE_2D, 0); 9931 glBindVertexArray(0); 9932 glDisable(GL_DEPTH_TEST); 9933 glDisable(GL_STENCIL_TEST); 9934 glUseProgram(0); 9935 9936 /* Delete objects */ 9937 if (0 != m_disabled_early_tests.m_program_id) 9938 { 9939 glDeleteProgram(m_disabled_early_tests.m_program_id); 9940 m_disabled_early_tests.m_program_id = 0; 9941 } 9942 9943 if (0 != m_enabled_early_tests.m_program_id) 9944 { 9945 glDeleteProgram(m_enabled_early_tests.m_program_id); 9946 m_enabled_early_tests.m_program_id = 0; 9947 } 9948 9949 if (0 != m_color_renderbuffer_id) 9950 { 9951 glDeleteRenderbuffers(1, &m_color_renderbuffer_id); 9952 m_color_renderbuffer_id = 0; 9953 } 9954 9955 if (0 != m_depth_stencil_renderbuffer_id) 9956 { 9957 glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id); 9958 m_depth_stencil_renderbuffer_id = 0; 9959 } 9960 9961 if (0 != m_framebuffer_id) 9962 { 9963 glDeleteFramebuffers(1, &m_framebuffer_id); 9964 m_framebuffer_id = 0; 9965 } 9966 9967 if (0 != m_texture_id) 9968 { 9969 glDeleteTextures(1, &m_texture_id); 9970 m_texture_id = 0; 9971 } 9972 9973 if (0 != m_vertex_array_object_id) 9974 { 9975 glDeleteVertexArrays(1, &m_vertex_array_object_id); 9976 m_vertex_array_object_id = 0; 9977 } 9978 9979 /* Done */ 9980 return NO_ERROR; 9981 } 9982 9983 virtual long Run() 9984 { 9985 bool result = true; 9986 9987 /* Bind texture to first image unit */ 9988 glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */, 9989 GL_READ_WRITE, GL_R32F); 9990 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture"); 9991 9992 /* Run tests for depth test */ 9993 if (false == testEarlyZ()) 9994 { 9995 result = false; 9996 } 9997 9998 /* Run tests for stencil test */ 9999 if (false == testEarlyStencil()) 10000 { 10001 result = false; 10002 } 10003 10004 /* Return ERROR if any problem was found */ 10005 if (false == result) 10006 { 10007 return ERROR; 10008 } 10009 10010 /* Done */ 10011 return NO_ERROR; 10012 } 10013 10014 virtual long Setup() 10015 { 10016 m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth())); 10017 10018 /* Prepare storage for texture data */ 10019 m_clean_texture_data.resize(m_image_edge * m_image_edge); 10020 m_extracted_texture_data.resize(m_image_edge * m_image_edge); 10021 10022 /* Prepare programs, framebuffer and texture */ 10023 buildPrograms(); 10024 createFramebuffer(); 10025 createTexture(); 10026 10027 /* Generate vertex array object */ 10028 glGenVertexArrays(1, &m_vertex_array_object_id); 10029 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays"); 10030 10031 /* Bind vertex array object */ 10032 glBindVertexArray(m_vertex_array_object_id); 10033 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray"); 10034 10035 /* Set clear color */ 10036 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 10037 GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor"); 10038 10039 /* Done */ 10040 return NO_ERROR; 10041 } 10042 10043private: 10044 /** Build two programs: with enabled and disabled early fragment tests 10045 * 10046 **/ 10047 void buildPrograms() 10048 { 10049 static const char* const fragment_shader_with_disabled_early_tests = 10050 "#version 400 core\n" 10051 "#extension GL_ARB_shader_image_load_store : require\n" 10052 "\n" 10053 "precision highp float;\n" 10054 "\n" 10055 "layout(r32f) uniform image2D u_image;\n" 10056 "\n" 10057 "void main()\n" 10058 "{\n" 10059 " vec4 color = vec4(1.0, 0, 0, 0);\n" 10060 "\n" 10061 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n" 10062 "\n" 10063 " discard;\n" 10064 "}\n\n"; 10065 10066 static const char* const fragment_shader_with_enabled_early_tests = 10067 "#version 400 core\n" 10068 "#extension GL_ARB_shader_image_load_store : require\n" 10069 "\n" 10070 "precision highp float;\n" 10071 "\n" 10072 "layout(early_fragment_tests) in;\n" 10073 "\n" 10074 "layout(r32f) uniform image2D u_image;\n" 10075 "\n" 10076 "void main()\n" 10077 "{\n" 10078 " vec4 color = vec4(1.0, 0, 0, 0);\n" 10079 "\n" 10080 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n" 10081 "\n" 10082 " discard;\n" 10083 "}\n\n"; 10084 10085 static const char* const geometry_shader_code = "#version 400 core\n" 10086 "#extension GL_ARB_shader_image_load_store : require\n" 10087 "\n" 10088 "precision highp float;\n" 10089 "\n" 10090 "layout(points) in;\n" 10091 "layout(triangle_strip, max_vertices = 4) out;\n" 10092 "\n" 10093 "uniform float u_depth;\n" 10094 "\n" 10095 "void main()\n" 10096 "{\n" 10097 " // Left-bottom\n" 10098 " gl_Position = vec4(-1, -1, u_depth, 1);\n" 10099 " EmitVertex();\n" 10100 "\n" 10101 " // Left-top\n" 10102 " gl_Position = vec4(-1, 1, u_depth, 1);\n" 10103 " EmitVertex();\n" 10104 "\n" 10105 " // Right-bottom\n" 10106 " gl_Position = vec4( 1, -1, u_depth, 1);\n" 10107 " EmitVertex();\n" 10108 "\n" 10109 " // Right-top\n" 10110 " gl_Position = vec4( 1, 1, u_depth, 1);\n" 10111 " EmitVertex();\n" 10112 "}\n\n"; 10113 10114 static const char* const vertex_shader_code = "#version 400 core\n" 10115 "#extension GL_ARB_shader_image_load_store : require\n" 10116 "\n" 10117 "precision highp float;\n" 10118 "\n" 10119 "void main()\n" 10120 "{\n" 10121 "}\n\n"; 10122 10123 prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code, 10124 m_disabled_early_tests); 10125 10126 prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code, 10127 m_enabled_early_tests); 10128 } 10129 10130 /** Fill texture with zeros 10131 * 10132 **/ 10133 void cleanTexture() 10134 { 10135 glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge, 10136 GL_RED, GL_FLOAT, &m_clean_texture_data[0]); 10137 GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D"); 10138 } 10139 10140 /** Create and bind (draw) framebuffer with color and depth-stencil attachments 10141 * 10142 **/ 10143 void createFramebuffer() 10144 { 10145 /* Generate render buffers */ 10146 glGenRenderbuffers(1, &m_color_renderbuffer_id); 10147 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers"); 10148 10149 glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id); 10150 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers"); 10151 10152 /* Generate and bind framebuffer object */ 10153 glGenFramebuffers(1, &m_framebuffer_id); 10154 GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers"); 10155 10156 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id); 10157 GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer"); 10158 10159 /* Prepare color render buffer */ 10160 glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id); 10161 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer"); 10162 10163 glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge); 10164 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage"); 10165 10166 /* Set up color attachment */ 10167 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id); 10168 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer"); 10169 10170 /* Prepare depth-stencil render buffer */ 10171 glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id); 10172 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer"); 10173 10174 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge); 10175 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage"); 10176 10177 /* Set up depth-stencil attachment */ 10178 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 10179 m_depth_stencil_renderbuffer_id); 10180 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer"); 10181 } 10182 10183 /** Create 2D R32F texture 10184 * 10185 **/ 10186 void createTexture() 10187 { 10188 glGenTextures(1, &m_texture_id); 10189 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures"); 10190 10191 glBindTexture(GL_TEXTURE_2D, m_texture_id); 10192 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 10193 10194 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge); 10195 GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D"); 10196 } 10197 10198 /** Extracts red channel from texture and verify if all texels are set to specified value 10199 * 10200 * @param value Expected value 10201 * 10202 * @return true if all texel match expected value, false otherwise 10203 **/ 10204 bool isTextureFilledWithValue(GLfloat value) 10205 { 10206 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]); 10207 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 10208 10209 for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i) 10210 { 10211 if (value != m_extracted_texture_data[i]) 10212 { 10213 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i 10214 << " has invalid value: " << m_extracted_texture_data[i] 10215 << " expected: " << value << tcu::TestLog::EndMessage; 10216 10217 return false; 10218 } 10219 } 10220 10221 return true; 10222 } 10223 10224 /** Build program, extract location of uniforms and store results in programDetails instance 10225 * 10226 * Throws tcu::InternalError if uniforms are inactive 10227 * 10228 * @param fragment_shader_code Source of fragment shader 10229 * @param geometry_shader_code Source of geometry shader 10230 * @param vertex_shader_code Source of vertex shader 10231 * @param out_program_details Instance of programDetails 10232 **/ 10233 void prepareProgramDetails(const char* fragment_shader_code, const char* geometry_shader_code, 10234 const char* vertex_shader_code, programDetails& out_program_details) 10235 { 10236 static const char* const depth_uniform_name = "u_depth"; 10237 static const char* const image_uniform_name = "u_image"; 10238 bool is_program_built = true; 10239 10240 GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code, 10241 fragment_shader_code, &is_program_built); 10242 10243 if (false == is_program_built) 10244 { 10245 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__); 10246 } 10247 10248 /* Get depth uniform location */ 10249 GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name); 10250 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation"); 10251 10252 if (m_invalid_uniform_location == depth_uniform_location) 10253 { 10254 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__); 10255 } 10256 10257 /* Get image uniform location */ 10258 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name); 10259 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation"); 10260 10261 if (m_invalid_uniform_location == image_uniform_location) 10262 { 10263 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__); 10264 } 10265 10266 /* Store results */ 10267 out_program_details.m_depth_uniform_location = depth_uniform_location; 10268 out_program_details.m_image_uniform_location = image_uniform_location; 10269 out_program_details.m_program_id = program_id; 10270 } 10271 10272 /** Test if early fragment stencil test works as expected. 10273 * 10274 * @return true if successful, false otherwise 10275 **/ 10276 bool testEarlyStencil() 10277 { 10278 bool result = true; 10279 10280 glEnable(GL_STENCIL_TEST); 10281 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable"); 10282 10283 glClearDepthf(1.0f); 10284 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf"); 10285 10286 /* verify that early stencil test is applied when enabled */ 10287 { 10288 glUseProgram(m_enabled_early_tests.m_program_id); 10289 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram"); 10290 10291 glClearStencil(0); 10292 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil"); 10293 10294 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 10295 GLU_EXPECT_NO_ERROR(glGetError(), "Clear"); 10296 10297 cleanTexture(); 10298 10299 glStencilFunc(GL_LESS, 128, 0xffffffff); 10300 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc"); 10301 10302 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */); 10303 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 10304 10305 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */); 10306 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f"); 10307 10308 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */); 10309 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 10310 10311 glMemoryBarrier(GL_ALL_BARRIER_BITS); 10312 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier"); 10313 10314 if (false == isTextureFilledWithValue(0.0f)) 10315 { 10316 m_context.getTestContext().getLog() << tcu::TestLog::Message 10317 << "Problem with early stencil test. It is not applied" 10318 << tcu::TestLog::EndMessage; 10319 10320 result = false; 10321 } 10322 } 10323 10324 /* verify that early stencil test does not discard all fragments */ 10325 { 10326 glClearStencil(128); 10327 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil"); 10328 10329 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 10330 GLU_EXPECT_NO_ERROR(glGetError(), "Clear"); 10331 10332 cleanTexture(); 10333 10334 glStencilFunc(GL_LESS, 0, 0xffffffff); 10335 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc"); 10336 10337 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */); 10338 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 10339 10340 glMemoryBarrier(GL_ALL_BARRIER_BITS); 10341 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier"); 10342 10343 if (false == isTextureFilledWithValue(1.0f)) 10344 { 10345 m_context.getTestContext().getLog() 10346 << tcu::TestLog::Message 10347 << "Problem with early stencil test. It discards fragments, that shall be drawn" 10348 << tcu::TestLog::EndMessage; 10349 10350 result = false; 10351 } 10352 } 10353 10354 /* verify that early stencil test is not applied when disabled */ 10355 { 10356 glUseProgram(m_disabled_early_tests.m_program_id); 10357 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram"); 10358 10359 glClearStencil(0); 10360 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil"); 10361 10362 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 10363 GLU_EXPECT_NO_ERROR(glGetError(), "Clear"); 10364 10365 cleanTexture(); 10366 10367 glStencilFunc(GL_LESS, 128, 0xffffffff); 10368 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc"); 10369 10370 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */); 10371 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 10372 10373 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */); 10374 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f"); 10375 10376 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */); 10377 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 10378 10379 glMemoryBarrier(GL_ALL_BARRIER_BITS); 10380 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier"); 10381 10382 if (false == isTextureFilledWithValue(1.0f)) 10383 { 10384 m_context.getTestContext().getLog() << tcu::TestLog::Message 10385 << "Problem with early stencil test. It is applied when disabled" 10386 << tcu::TestLog::EndMessage; 10387 10388 result = false; 10389 } 10390 } 10391 10392 glDisable(GL_STENCIL_TEST); 10393 GLU_EXPECT_NO_ERROR(glGetError(), "Disable"); 10394 10395 /* Done */ 10396 return result; 10397 } 10398 10399 /** Test if early fragment depth test works as expected. 10400 * 10401 * @return true if successful, false otherwise 10402 **/ 10403 bool testEarlyZ() 10404 { 10405 bool result = true; 10406 10407 glEnable(GL_DEPTH_TEST); 10408 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable"); 10409 10410 glClearDepthf(0.5f); 10411 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf"); 10412 10413 glClearStencil(0); 10414 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil"); 10415 10416 /* verify that early z test is applied when enabled */ 10417 { 10418 glUseProgram(m_enabled_early_tests.m_program_id); 10419 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram"); 10420 10421 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 10422 GLU_EXPECT_NO_ERROR(glGetError(), "Clear"); 10423 10424 cleanTexture(); 10425 10426 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */); 10427 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 10428 10429 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */); 10430 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f"); 10431 10432 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */); 10433 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 10434 10435 glMemoryBarrier(GL_ALL_BARRIER_BITS); 10436 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier"); 10437 10438 if (false == isTextureFilledWithValue(0.0f)) 10439 { 10440 m_context.getTestContext().getLog() << tcu::TestLog::Message 10441 << "Problem with early z test. It is not applied" 10442 << tcu::TestLog::EndMessage; 10443 10444 result = false; 10445 } 10446 } 10447 10448 /* verify that early z test does not discard all fragments */ 10449 { 10450 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 10451 GLU_EXPECT_NO_ERROR(glGetError(), "Clear"); 10452 10453 cleanTexture(); 10454 10455 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */); 10456 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 10457 10458 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */); 10459 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f"); 10460 10461 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */); 10462 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 10463 10464 glMemoryBarrier(GL_ALL_BARRIER_BITS); 10465 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier"); 10466 10467 if (false == isTextureFilledWithValue(1.0f)) 10468 { 10469 m_context.getTestContext().getLog() 10470 << tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn" 10471 << tcu::TestLog::EndMessage; 10472 10473 result = false; 10474 } 10475 } 10476 10477 /* verify that early z test is not applied when disabled */ 10478 { 10479 glUseProgram(m_disabled_early_tests.m_program_id); 10480 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram"); 10481 10482 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 10483 GLU_EXPECT_NO_ERROR(glGetError(), "Clear"); 10484 10485 cleanTexture(); 10486 10487 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */); 10488 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 10489 10490 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */); 10491 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f"); 10492 10493 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */); 10494 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 10495 10496 glMemoryBarrier(GL_ALL_BARRIER_BITS); 10497 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier"); 10498 10499 if (false == isTextureFilledWithValue(1.0f)) 10500 { 10501 m_context.getTestContext().getLog() << tcu::TestLog::Message 10502 << "Problem with early z test. It is applied when disabled" 10503 << tcu::TestLog::EndMessage; 10504 10505 result = false; 10506 } 10507 } 10508 10509 glDisable(GL_DEPTH_TEST); 10510 GLU_EXPECT_NO_ERROR(glGetError(), "Disable"); 10511 10512 /* Done */ 10513 return result; 10514 } 10515}; 10516 10517//----------------------------------------------------------------------------- 10518// 4.1 NegativeUniform 10519//----------------------------------------------------------------------------- 10520class NegativeUniform : public ShaderImageLoadStoreBase 10521{ 10522 GLuint m_program; 10523 10524 virtual long Setup() 10525 { 10526 m_program = 0; 10527 return NO_ERROR; 10528 } 10529 10530 virtual long Run() 10531 { 10532 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 10533 " gl_Position = i_position;" NL "}"; 10534 const char* glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL 10535 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(0.0));" NL 10536 " discard;" NL "}"; 10537 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 10538 10539 GLint max_image_units; 10540 glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units); 10541 glUseProgram(m_program); 10542 10543 glUniform1i(glGetUniformLocation(m_program, "g_image"), -1); 10544 if (glGetError() != GL_INVALID_VALUE) 10545 { 10546 m_context.getTestContext().getLog() 10547 << tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero." 10548 << tcu::TestLog::EndMessage; 10549 return ERROR; 10550 } 10551 glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units); 10552 if (glGetError() != GL_INVALID_VALUE) 10553 { 10554 m_context.getTestContext().getLog() 10555 << tcu::TestLog::Message 10556 << "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of " 10557 << "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage; 10558 return ERROR; 10559 } 10560 10561 GLint i = -3; 10562 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i); 10563 if (glGetError() != GL_INVALID_VALUE) 10564 { 10565 m_context.getTestContext().getLog() 10566 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero." 10567 << tcu::TestLog::EndMessage; 10568 return ERROR; 10569 } 10570 i = max_image_units + 1; 10571 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i); 10572 if (glGetError() != GL_INVALID_VALUE) 10573 { 10574 m_context.getTestContext().getLog() 10575 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is greater " 10576 "than or equal to the value of MAX_IMAGE_UNITS." 10577 << tcu::TestLog::EndMessage; 10578 return ERROR; 10579 } 10580 10581 glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0); 10582 if (glGetError() != GL_INVALID_OPERATION) 10583 { 10584 m_context.getTestContext().getLog() 10585 << tcu::TestLog::Message 10586 << "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable." 10587 << tcu::TestLog::EndMessage; 10588 return ERROR; 10589 } 10590 glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0); 10591 if (glGetError() != GL_INVALID_OPERATION) 10592 { 10593 m_context.getTestContext().getLog() 10594 << tcu::TestLog::Message 10595 << "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable." 10596 << tcu::TestLog::EndMessage; 10597 return ERROR; 10598 } 10599 10600 { 10601 glUseProgram(0); 10602 10603 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1); 10604 if (glGetError() != GL_INVALID_VALUE) 10605 { 10606 m_context.getTestContext().getLog() 10607 << tcu::TestLog::Message 10608 << "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero." 10609 << tcu::TestLog::EndMessage; 10610 return ERROR; 10611 } 10612 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units); 10613 if (glGetError() != GL_INVALID_VALUE) 10614 { 10615 m_context.getTestContext().getLog() 10616 << tcu::TestLog::Message 10617 << "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the " 10618 "value of MAX_IMAGE_UNITS." 10619 << tcu::TestLog::EndMessage; 10620 return ERROR; 10621 } 10622 10623 GLint ii = -3; 10624 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii); 10625 if (glGetError() != GL_INVALID_VALUE) 10626 { 10627 m_context.getTestContext().getLog() 10628 << tcu::TestLog::Message 10629 << "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero." 10630 << tcu::TestLog::EndMessage; 10631 return ERROR; 10632 } 10633 ii = max_image_units + 1; 10634 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii); 10635 if (glGetError() != GL_INVALID_VALUE) 10636 { 10637 m_context.getTestContext().getLog() 10638 << tcu::TestLog::Message << "glProgramUniform1iv should generate INVALID_VALUE when <value> " 10639 "is greater than or equal to the value of MAX_IMAGE_UNITS." 10640 << tcu::TestLog::EndMessage; 10641 return ERROR; 10642 } 10643 10644 glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0); 10645 if (glGetError() != GL_INVALID_OPERATION) 10646 { 10647 m_context.getTestContext().getLog() 10648 << tcu::TestLog::Message << "glProgramUniform1ui should generate INVALID_OPERATION if the " 10649 "location refers to an image variable." 10650 << tcu::TestLog::EndMessage; 10651 return ERROR; 10652 } 10653 glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0); 10654 if (glGetError() != GL_INVALID_OPERATION) 10655 { 10656 m_context.getTestContext().getLog() 10657 << tcu::TestLog::Message << "glProgramUniform2i should generate INVALID_OPERATION if the " 10658 "location refers to an image variable." 10659 << tcu::TestLog::EndMessage; 10660 return ERROR; 10661 } 10662 } 10663 10664 return NO_ERROR; 10665 } 10666 10667 virtual long Cleanup() 10668 { 10669 glUseProgram(0); 10670 glDeleteProgram(m_program); 10671 return NO_ERROR; 10672 } 10673}; 10674//----------------------------------------------------------------------------- 10675// 4.2 NegativeBind 10676//----------------------------------------------------------------------------- 10677class NegativeBind : public ShaderImageLoadStoreBase 10678{ 10679 virtual long Setup() 10680 { 10681 return NO_ERROR; 10682 } 10683 10684 virtual long Run() 10685 { 10686 glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA); 10687 if (glGetError() != GL_INVALID_VALUE) 10688 { 10689 m_context.getTestContext().getLog() 10690 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> is " 10691 "greater than or equal to the value of MAX_IMAGE_UNITS." 10692 << tcu::TestLog::EndMessage; 10693 return ERROR; 10694 } 10695 10696 glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA); 10697 if (glGetError() != GL_INVALID_VALUE) 10698 { 10699 m_context.getTestContext().getLog() 10700 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> is not " 10701 "the name of an existing texture object." 10702 << tcu::TestLog::EndMessage; 10703 return ERROR; 10704 } 10705 10706 glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234); 10707 if (glGetError() != GL_INVALID_VALUE) 10708 { 10709 m_context.getTestContext().getLog() 10710 << tcu::TestLog::Message 10711 << "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format." 10712 << tcu::TestLog::EndMessage; 10713 return ERROR; 10714 } 10715 return NO_ERROR; 10716 } 10717 10718 virtual long Cleanup() 10719 { 10720 return NO_ERROR; 10721 } 10722}; 10723//----------------------------------------------------------------------------- 10724// 4.3 NegativeCompileErrors 10725//----------------------------------------------------------------------------- 10726class NegativeCompileErrors : public ShaderImageLoadStoreBase 10727{ 10728 virtual long Run() 10729 { 10730 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10731 "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL 10732 " o_color = imageLoad(g_image, ivec2(0));" NL "}")) 10733 return ERROR; 10734 10735 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10736 "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL 10737 " o_color = imageLoad(g_image, ivec2(0));" NL "}")) 10738 return ERROR; 10739 10740 if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL 10741 "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL 10742 " imageStore(g_image, ivec2(0), i_color);" NL " o_color = i_color;" NL "}")) 10743 return ERROR; 10744 10745 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL 10746 "void main() {" NL " o_color = imageLoad(g_image, ivec2(0));" NL "}")) 10747 return ERROR; 10748 10749 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10750 "readonly uniform image2D g_image;" NL "void main() {" NL 10751 " o_color = imageLoad(g_image, ivec2(0));" NL "}")) 10752 return ERROR; 10753 10754 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10755 "layout(rg16i) uniform image1D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}")) 10756 return ERROR; 10757 10758 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10759 "layout(rg16) uniform iimage2D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}")) 10760 return ERROR; 10761 10762 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10763 "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL 10764 " imageAtomicAdd(g_image, ivec2(1), 10);" NL " o_color = vec4(1.0);" NL "}")) 10765 return ERROR; 10766 10767 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10768 "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL 10769 " imageAtomicAdd(g_image, ivec2(1), 1u);" NL " o_color = vec4(1.0);" NL "}")) 10770 return ERROR; 10771 10772 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10773 "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL 10774 " imageStore(g_image, ivec3(1), ivec4(1));" NL " o_color = vec4(1.0);" NL "}")) 10775 return ERROR; 10776 10777 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10778 "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL 10779 " imageStore(g_image, ivec3(0), uvec4(1));" NL " o_color = vec4(1.0);" NL "}")) 10780 return ERROR; 10781 10782 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10783 "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL 10784 " return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL " o_color = Load(g_image);" NL 10785 "}")) 10786 return ERROR; 10787 10788 return NO_ERROR; 10789 } 10790 10791 bool Compile(const std::string& source) 10792 { 10793 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER); 10794 10795 const char* const src = source.c_str(); 10796 glShaderSource(sh, 1, &src, NULL); 10797 glCompileShader(sh); 10798 10799 GLchar log[1024]; 10800 glGetShaderInfoLog(sh, sizeof(log), NULL, log); 10801 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n" 10802 << log << tcu::TestLog::EndMessage; 10803 10804 GLint status; 10805 glGetShaderiv(sh, GL_COMPILE_STATUS, &status); 10806 glDeleteShader(sh); 10807 10808 if (status == GL_TRUE) 10809 { 10810 m_context.getTestContext().getLog() 10811 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage; 10812 return false; 10813 } 10814 10815 return true; 10816 } 10817}; 10818//----------------------------------------------------------------------------- 10819// 4.4 NegativeLinkErrors 10820//----------------------------------------------------------------------------- 10821class NegativeLinkErrors : public ShaderImageLoadStoreBase 10822{ 10823 virtual long Run() 10824 { 10825 if (!SupportedInVS(1)) 10826 return NOT_SUPPORTED; 10827 10828 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 10829 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL 10830 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}", 10831 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10832 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL 10833 " imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}")) 10834 return ERROR; 10835 10836 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 10837 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL 10838 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}", 10839 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10840 "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL 10841 " imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}")) 10842 return ERROR; 10843 10844 return NO_ERROR; 10845 } 10846 10847 bool Link(const std::string& vs, const std::string& fs) 10848 { 10849 const GLuint p = glCreateProgram(); 10850 10851 const GLuint vsh = glCreateShader(GL_VERTEX_SHADER); 10852 glAttachShader(p, vsh); 10853 glDeleteShader(vsh); 10854 const char* const vssrc = vs.c_str(); 10855 glShaderSource(vsh, 1, &vssrc, NULL); 10856 glCompileShader(vsh); 10857 10858 const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER); 10859 glAttachShader(p, fsh); 10860 glDeleteShader(fsh); 10861 const char* const fssrc = fs.c_str(); 10862 glShaderSource(fsh, 1, &fssrc, NULL); 10863 glCompileShader(fsh); 10864 10865 GLint status; 10866 glGetShaderiv(vsh, GL_COMPILE_STATUS, &status); 10867 if (status == GL_FALSE) 10868 { 10869 glDeleteProgram(p); 10870 m_context.getTestContext().getLog() 10871 << tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage; 10872 return false; 10873 } 10874 glGetShaderiv(fsh, GL_COMPILE_STATUS, &status); 10875 if (status == GL_FALSE) 10876 { 10877 glDeleteProgram(p); 10878 m_context.getTestContext().getLog() 10879 << tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage; 10880 return false; 10881 } 10882 10883 glLinkProgram(p); 10884 10885 GLchar log[1024]; 10886 glGetProgramInfoLog(p, sizeof(log), NULL, log); 10887 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n" 10888 << log << tcu::TestLog::EndMessage; 10889 10890 glGetProgramiv(p, GL_LINK_STATUS, &status); 10891 glDeleteProgram(p); 10892 10893 if (status == GL_TRUE) 10894 { 10895 m_context.getTestContext().getLog() 10896 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage; 10897 return false; 10898 } 10899 10900 return true; 10901 } 10902}; 10903 10904/** Negative Test "Active image uniform limits", description follows. 10905 * 10906 * Program that exceeds resource limits should not compile and/or link. 10907 * 10908 * Steps: 10909 * - try to compile and link a program that uses too many image uniforms in 10910 * fragment shader stage, 10911 * - try to compile and link a program that uses too many image uniforms in 10912 * vertex shader stage, 10913 * - try to compile and link a program that uses too many image uniforms in 10914 * tessellation control shader stage, 10915 * - try to compile and link a program that uses too many image uniforms in 10916 * tessellation evaluation shader stage, 10917 * - try to compile and link a program that uses too many image uniforms in 10918 * geometry shader stage, 10919 * - try to compile and link a program that uses too many image uniforms in all 10920 * shader stages combined, any single stage should not exceed its limits, this 10921 * step might be impossible to fulfill. 10922 * 10923 * Test should use the following declaration of image uniforms: 10924 * layout(r32i) uniform iimage2D u_image[N_UNIFORMS]; 10925 * 10926 * For cases where limit for single stage is tested, N_UNIFORMS should be 10927 * defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant 10928 * corresponding to tested shader stage. 10929 * 10930 * For case where limit for combined stages is tested: 10931 * - u_image name should be appended with the name of shader stage, like 10932 * u_image_vertex, 10933 * - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where 10934 * gl_Max*ImageUniforms is constant corresponding to tested shader stage, 10935 * - compilation and linking shall succeed, when sum of all 10936 * gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to 10937 * gl_MaxCombinedImageUniforms. 10938 * 10939 * All defined image uniforms have to be active. Each shader stage that declare 10940 * image uniforms should include following code snippet: 10941 * value = 1; 10942 * for (int i = 0; i < N_UNIFORMS; ++i) 10943 * { 10944 * value = imageAtomicAdd(u_image[i], coord, value); 10945 * } 10946 **/ 10947class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase 10948{ 10949private: 10950 /* Fields */ 10951 /* Results */ 10952 bool m_result_for_combined; 10953 bool m_result_for_fragment_shader; 10954 bool m_result_for_geometry_shader; 10955 bool m_result_for_tesselation_control_shader; 10956 bool m_result_for_tesselatioon_evaluation_shader; 10957 bool m_result_for_vertex_shader; 10958 10959public: 10960 /* Constructor */ 10961 ImageLoadStoreUniformLimitsTest() 10962 : m_result_for_combined(false) 10963 , m_result_for_fragment_shader(false) 10964 , m_result_for_geometry_shader(false) 10965 , m_result_for_tesselation_control_shader(false) 10966 , m_result_for_tesselatioon_evaluation_shader(false) 10967 , m_result_for_vertex_shader(false) 10968 { 10969 /* Nothing to be done */ 10970 } 10971 10972 /* Methods inherited from SubcaseBase */ 10973 virtual long Cleanup() 10974 { 10975 /* Done */ 10976 return NO_ERROR; 10977 } 10978 10979 virtual long Run() 10980 { 10981 m_context.getTestContext().getLog() << tcu::TestLog::Message 10982 << "This test tries to build invalid programs, expect error messages about " 10983 "exceeded number of active image uniforms" 10984 << tcu::TestLog::EndMessage; 10985 10986 testFragmentShaderStage(); 10987 testGeometryShaderStage(); 10988 testTesselationControlShaderStage(); 10989 testTesselationEvaluationShaderStage(); 10990 testVertexShaderStage(); 10991 testCombinedShaderStages(); 10992 10993 /* Return error if any stage failed */ 10994 if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) || 10995 (false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) || 10996 (false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader)) 10997 { 10998 return ERROR; 10999 } 11000 11001 /* Done */ 11002 return NO_ERROR; 11003 } 11004 11005 virtual long Setup() 11006 { 11007 /* Done */ 11008 return NO_ERROR; 11009 } 11010 11011private: 11012 /** Test fragment shader stage 11013 * 11014 **/ 11015 void testFragmentShaderStage() 11016 { 11017 static const char* const fragment_shader_code = 11018 "#version 400 core\n" 11019 "#extension GL_ARB_shader_image_load_store : require\n" 11020 "\n" 11021 "precision highp float;\n" 11022 "\n" 11023 "#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n" 11024 "\n" 11025 "flat in ivec2 vs_fs_coord;\n" 11026 "\n" 11027 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n" 11028 "\n" 11029 "void main()\n" 11030 "{\n" 11031 " int value = 1;\n" 11032 "\n" 11033 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11034 " {\n" 11035 " value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n" 11036 " }\n" 11037 "\n" 11038 " discard;\n" 11039 "}\n\n"; 11040 11041 static const char* const vertex_shader_code = "#version 400 core\n" 11042 "#extension GL_ARB_shader_image_load_store : require\n" 11043 "\n" 11044 "precision highp float;\n" 11045 "\n" 11046 " in ivec2 vs_in_coord;\n" 11047 "flat out ivec2 vs_fs_coord;\n" 11048 "\n" 11049 "void main()\n" 11050 "{\n" 11051 " vs_fs_coord = vs_in_coord;\n" 11052 "}\n\n"; 11053 11054 m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, 11055 0 /* tesselation_control_shader_code */, 11056 0 /* tesselation_evaluation_shader_code */, vertex_shader_code); 11057 11058 if (false == m_result_for_fragment_shader) 11059 { 11060 m_context.getTestContext().getLog() 11061 << tcu::TestLog::Message 11062 << "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully." 11063 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n" 11064 << fragment_shader_code << tcu::TestLog::EndMessage; 11065 } 11066 } 11067 11068 /** Test geometry shader stage 11069 * 11070 **/ 11071 void testGeometryShaderStage() 11072 { 11073 static const char* const fragment_shader_code = "#version 400 core\n" 11074 "#extension GL_ARB_shader_image_load_store : require\n" 11075 "\n" 11076 "precision highp float;\n" 11077 "\n" 11078 "void main()\n" 11079 "{\n" 11080 " discard;\n" 11081 "}\n\n"; 11082 11083 static const char* const geometry_shader_code = 11084 "#version 400 core\n" 11085 "#extension GL_ARB_shader_image_load_store : require\n" 11086 "\n" 11087 "precision highp float;\n" 11088 "\n" 11089 "layout(points) in;\n" 11090 "layout(points, max_vertices = 1) out;\n" 11091 "\n" 11092 "#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n" 11093 "\n" 11094 "in ivec2 vs_gs_coord[];\n" 11095 "\n" 11096 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n" 11097 "\n" 11098 "void main()\n" 11099 "{\n" 11100 " int value = 1;\n" 11101 "\n" 11102 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11103 " {\n" 11104 " value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\n" 11105 " }\n" 11106 "}\n\n"; 11107 11108 static const char* const vertex_shader_code = "#version 400 core\n" 11109 "#extension GL_ARB_shader_image_load_store : require\n" 11110 "\n" 11111 "precision highp float;\n" 11112 "\n" 11113 "in ivec2 vs_in_coord;\n" 11114 "out ivec2 vs_gs_coord;\n" 11115 "\n" 11116 "void main()\n" 11117 "{\n" 11118 " vs_gs_coord = vs_in_coord;\n" 11119 "}\n\n"; 11120 11121 m_result_for_geometry_shader = 11122 !doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */, 11123 0 /* tesselation_evaluation_shader_code */, vertex_shader_code); 11124 11125 if (false == m_result_for_geometry_shader) 11126 { 11127 m_context.getTestContext().getLog() 11128 << tcu::TestLog::Message 11129 << "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully." 11130 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n" 11131 << geometry_shader_code << tcu::TestLog::EndMessage; 11132 } 11133 } 11134 11135 /** Test tesselation control shader stage 11136 * 11137 **/ 11138 void testTesselationControlShaderStage() 11139 { 11140 static const char* const fragment_shader_code = "#version 400 core\n" 11141 "#extension GL_ARB_shader_image_load_store : require\n" 11142 "\n" 11143 "precision highp float;\n" 11144 "\n" 11145 "void main()\n" 11146 "{\n" 11147 " discard;\n" 11148 "}\n\n"; 11149 11150 static const char* const tesselation_control_shader_code = 11151 "#version 400 core\n" 11152 "#extension GL_ARB_shader_image_load_store : require\n" 11153 "\n" 11154 "precision highp float;\n" 11155 "\n" 11156 "layout(vertices = 4) out;\n" 11157 "\n" 11158 "#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n" 11159 "\n" 11160 "in ivec2 vs_tcs_coord[];\n" 11161 "\n" 11162 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n" 11163 "\n" 11164 "void main()\n" 11165 "{\n" 11166 " int value = 1;\n" 11167 "\n" 11168 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11169 " {\n" 11170 " value = imageAtomicAdd(u_image[i], vs_tcs_coord[0], value);\n" 11171 " }\n" 11172 "}\n\n"; 11173 11174 static const char* const tesselation_evaluation_shader_code = 11175 "#version 400 core\n" 11176 "#extension GL_ARB_shader_image_load_store : require\n" 11177 "\n" 11178 "precision highp float;\n" 11179 "\n" 11180 "layout(quads, equal_spacing, ccw) in;\n" 11181 "\n" 11182 "void main()\n" 11183 "{\n" 11184 "}\n"; 11185 11186 static const char* const vertex_shader_code = "#version 400 core\n" 11187 "#extension GL_ARB_shader_image_load_store : require\n" 11188 "\n" 11189 "precision highp float;\n" 11190 "\n" 11191 "in ivec2 vs_in_coord;\n" 11192 "out ivec2 vs_tcs_coord;\n" 11193 "\n" 11194 "void main()\n" 11195 "{\n" 11196 " vs_tcs_coord = vs_in_coord;\n" 11197 "}\n\n"; 11198 11199 m_result_for_tesselation_control_shader = 11200 !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code, 11201 tesselation_evaluation_shader_code, vertex_shader_code); 11202 11203 if (false == m_result_for_tesselation_control_shader) 11204 { 11205 m_context.getTestContext().getLog() 11206 << tcu::TestLog::Message 11207 << "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully." 11208 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n" 11209 << tesselation_control_shader_code << tcu::TestLog::EndMessage; 11210 } 11211 } 11212 11213 /** Test teselation evaluation shader stage 11214 * 11215 **/ 11216 void testTesselationEvaluationShaderStage() 11217 { 11218 static const char* const fragment_shader_code = "#version 400 core\n" 11219 "#extension GL_ARB_shader_image_load_store : require\n" 11220 "\n" 11221 "precision highp float;\n" 11222 "\n" 11223 "void main()\n" 11224 "{\n" 11225 " discard;\n" 11226 "}\n\n"; 11227 11228 static const char* const tesselation_evaluation_shader_code = 11229 "#version 400 core\n" 11230 "#extension GL_ARB_shader_image_load_store : require\n" 11231 "\n" 11232 "precision highp float;\n" 11233 "\n" 11234 "layout(quads, equal_spacing, ccw) in;\n" 11235 "\n" 11236 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n" 11237 "\n" 11238 "in ivec2 vs_tes_coord[];\n" 11239 "\n" 11240 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n" 11241 "\n" 11242 "void main()\n" 11243 "{\n" 11244 " int value = 1;\n" 11245 "\n" 11246 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11247 " {\n" 11248 " value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n" 11249 " }\n" 11250 "}\n\n"; 11251 11252 static const char* const vertex_shader_code = "#version 400 core\n" 11253 "#extension GL_ARB_shader_image_load_store : require\n" 11254 "\n" 11255 "precision highp float;\n" 11256 "\n" 11257 "in ivec2 vs_in_coord;\n" 11258 "out ivec2 vs_tes_coord;\n" 11259 "\n" 11260 "void main()\n" 11261 "{\n" 11262 " vs_tes_coord = vs_in_coord;\n" 11263 "}\n\n"; 11264 11265 m_result_for_tesselatioon_evaluation_shader = !doesProgramLink( 11266 fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */, 11267 tesselation_evaluation_shader_code, vertex_shader_code); 11268 11269 if (false == m_result_for_tesselatioon_evaluation_shader) 11270 { 11271 m_context.getTestContext().getLog() 11272 << tcu::TestLog::Message 11273 << "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully." 11274 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n" 11275 << tesselation_evaluation_shader_code << tcu::TestLog::EndMessage; 11276 } 11277 } 11278 11279 /** Test vertex shader stage 11280 * 11281 **/ 11282 void testVertexShaderStage() 11283 { 11284 static const char* const fragment_shader_code = "#version 400 core\n" 11285 "#extension GL_ARB_shader_image_load_store : require\n" 11286 "\n" 11287 "precision highp float;\n" 11288 "\n" 11289 "void main()\n" 11290 "{\n" 11291 " discard;\n" 11292 "}\n\n"; 11293 11294 static const char* const vertex_shader_code = 11295 "#version 400 core\n" 11296 "#extension GL_ARB_shader_image_load_store : require\n" 11297 "\n" 11298 "precision highp float;\n" 11299 "\n" 11300 "in ivec2 vs_in_coord;\n" 11301 "\n" 11302 "#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n" 11303 "\n" 11304 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n" 11305 "\n" 11306 "void main()\n" 11307 "{\n" 11308 " int value = 1;\n" 11309 "\n" 11310 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11311 " {\n" 11312 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n" 11313 " }\n" 11314 "}\n\n"; 11315 11316 m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, 11317 0 /* tesselation_control_shader_code */, 11318 0 /* tesselation_evaluation_shader_code */, vertex_shader_code); 11319 11320 if (false == m_result_for_vertex_shader) 11321 { 11322 m_context.getTestContext().getLog() 11323 << tcu::TestLog::Message 11324 << "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully." 11325 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n" 11326 << vertex_shader_code << tcu::TestLog::EndMessage; 11327 } 11328 } 11329 11330 /** Test combined shader stages 11331 * 11332 **/ 11333 void testCombinedShaderStages() 11334 { 11335 static const char* const fragment_shader_code = 11336 "#version 400 core\n" 11337 "#extension GL_ARB_shader_image_load_store : require\n" 11338 "\n" 11339 "precision highp float;\n" 11340 "\n" 11341 "#define N_UNIFORMS gl_MaxFragmentImageUniforms\n" 11342 "\n" 11343 "flat in ivec2 gs_fs_coord;\n" 11344 "\n" 11345 "layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n" 11346 "\n" 11347 "void main()\n" 11348 "{\n" 11349 " int value = 1;\n" 11350 "\n" 11351 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11352 " {\n" 11353 " value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n" 11354 " }\n" 11355 "\n" 11356 " discard;\n" 11357 "}\n\n"; 11358 11359 static const char* const geometry_shader_code = 11360 "#version 400 core\n" 11361 "#extension GL_ARB_shader_image_load_store : require\n" 11362 "\n" 11363 "precision highp float;\n" 11364 "\n" 11365 "layout(points) in;\n" 11366 "layout(points, max_vertices = 1) out;\n" 11367 "\n" 11368 "#define N_UNIFORMS gl_MaxGeometryImageUniforms\n" 11369 "\n" 11370 "flat in ivec2 tes_gs_coord[];\n" 11371 "flat out ivec2 gs_fs_coord;\n" 11372 "\n" 11373 "layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n" 11374 "\n" 11375 "void main()\n" 11376 "{\n" 11377 " int value = 1;\n" 11378 "\n" 11379 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11380 " {\n" 11381 " value = imageAtomicAdd(u_image_geometry[i], tes_gs_coord[0], value);\n" 11382 " }\n" 11383 "\n" 11384 " gs_fs_coord = tes_gs_coord[0];\n" 11385 " EmitVertex();\n" 11386 "}\n\n"; 11387 11388 static const char* const tesselation_control_shader_code = 11389 "#version 400 core\n" 11390 "#extension GL_ARB_shader_image_load_store : require\n" 11391 "\n" 11392 "precision highp float;\n" 11393 "\n" 11394 "layout(vertices = 4) out;\n" 11395 "\n" 11396 "#define N_UNIFORMS gl_MaxTessControlImageUniforms\n" 11397 "\n" 11398 "flat in ivec2 vs_tcs_coord[];\n" 11399 "flat out ivec2 tcs_tes_coord[];\n" 11400 "\n" 11401 "layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n" 11402 "\n" 11403 "void main()\n" 11404 "{\n" 11405 " int value = 1;\n" 11406 "\n" 11407 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11408 " {\n" 11409 " value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n" 11410 " }\n" 11411 "\n" 11412 " tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n" 11413 "}\n\n"; 11414 11415 static const char* const tesselation_evaluation_shader_code = 11416 "#version 400 core\n" 11417 "#extension GL_ARB_shader_image_load_store : require\n" 11418 "\n" 11419 "precision highp float;\n" 11420 "\n" 11421 "layout(quads, equal_spacing, ccw) in;\n" 11422 "\n" 11423 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n" 11424 "\n" 11425 "flat in ivec2 tcs_tes_coord[];\n" 11426 "flat out ivec2 tes_gs_coord;\n" 11427 "\n" 11428 "layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n" 11429 "\n" 11430 "void main()\n" 11431 "{\n" 11432 " int value = 1;\n" 11433 "\n" 11434 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11435 " {\n" 11436 " value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n" 11437 " }\n" 11438 "\n" 11439 " tes_gs_coord = tcs_tes_coord[0];\n" 11440 "}\n\n"; 11441 11442 static const char* const vertex_shader_code = 11443 "#version 400 core\n" 11444 "#extension GL_ARB_shader_image_load_store : require\n" 11445 "\n" 11446 "precision highp float;\n" 11447 "\n" 11448 " in ivec2 vs_in_coord;\n" 11449 "flat out ivec2 vs_tcs_coord;\n" 11450 "\n" 11451 "#define N_UNIFORMS gl_MaxVertexImageUniforms\n" 11452 "\n" 11453 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n" 11454 "\n" 11455 "void main()\n" 11456 "{\n" 11457 " int value = 1;\n" 11458 "\n" 11459 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11460 " {\n" 11461 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n" 11462 " }\n" 11463 "\n" 11464 " vs_tcs_coord = vs_tcs_coord;\n" 11465 "}\n\n"; 11466 11467 /* Active image uniform limits */ 11468 GLint max_combined_image_uniforms = 0; 11469 GLint max_fragment_image_uniforms = 0; 11470 GLint max_geometry_image_uniforms = 0; 11471 GLint max_tesselation_control_image_uniforms = 0; 11472 GLint max_tesselation_evaluation_image_uniforms = 0; 11473 GLint max_vertex_image_uniforms = 0; 11474 11475 /* Get limit values */ 11476 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms); 11477 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms); 11478 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms); 11479 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms); 11480 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms); 11481 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms); 11482 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv"); 11483 11484 /* Check if program builds */ 11485 m_result_for_combined = 11486 !doesProgramLink(fragment_shader_code, geometry_shader_code, tesselation_control_shader_code, 11487 tesselation_evaluation_shader_code, vertex_shader_code); 11488 11489 /* Result depends on the limit values */ 11490 if (max_combined_image_uniforms >= 11491 (max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms + 11492 max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms)) 11493 { 11494 /* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */ 11495 m_result_for_combined = !m_result_for_combined; 11496 11497 if (false == m_result_for_combined) 11498 { 11499 m_context.getTestContext().getLog() 11500 << tcu::TestLog::Message << "There was an error while building a program." 11501 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n" 11502 << vertex_shader_code << "\nTesselation control shader code:\n" 11503 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n" 11504 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n" 11505 << geometry_shader_code << "\nFragment shader code:\n" 11506 << fragment_shader_code << tcu::TestLog::EndMessage; 11507 } 11508 } 11509 else 11510 { 11511 /* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */ 11512 if (false == m_result_for_combined) 11513 { 11514 m_context.getTestContext().getLog() 11515 << tcu::TestLog::Message 11516 << "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully." 11517 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n" 11518 << vertex_shader_code << "\nTesselation control shader code:\n" 11519 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n" 11520 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n" 11521 << geometry_shader_code << "\nFragment shader code:\n" 11522 << fragment_shader_code << tcu::TestLog::EndMessage; 11523 } 11524 } 11525 } 11526 11527 /** Check if program builds successfully 11528 * 11529 * @param fragment_shader_code Source code for fragment shader stage 11530 * @param geometry_shader_code Source code for geometry shader stage 11531 * @param tesselation_control_shader_code Source code for tesselation control shader stage 11532 * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage 11533 * @param vertex_shader_code Source code for vertex shader stage 11534 * 11535 * @return true if program was built without errors, false otherwise 11536 **/ 11537 bool doesProgramLink(const char* fragment_shader_code, const char* geometry_shader_code, 11538 const char* tesselation_control_shader_code, const char* tesselation_evaluation_shader_code, 11539 const char* vertex_shader_code) 11540 { 11541 bool is_program_built = true; 11542 GLuint program_id = 0; 11543 11544 program_id = 11545 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code, 11546 geometry_shader_code, fragment_shader_code, &is_program_built); 11547 11548 if (0 != program_id) 11549 { 11550 glDeleteProgram(program_id); 11551 } 11552 11553 return is_program_built; 11554 } 11555}; 11556} 11557 11558ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context& context) 11559 : TestCaseGroup(context, "shader_image_load_store", "") 11560{ 11561} 11562 11563ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void) 11564{ 11565} 11566 11567void ShaderImageLoadStoreTests::init() 11568{ 11569 using namespace deqp; 11570 addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>)); 11571 addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>)); 11572 addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>)); 11573 addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>)); 11574 addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>)); 11575 addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>)); 11576 addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages", 11577 TestSubcase::Create<BasicAllFormatsStoreGeometryStages>)); 11578 addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages", 11579 TestSubcase::Create<BasicAllFormatsLoadGeometryStages>)); 11580 addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage", 11581 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>)); 11582 addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>)); 11583 addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>)); 11584 addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>)); 11585 addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>)); 11586 addChild( 11587 new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>)); 11588 addChild( 11589 new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>)); 11590 addChild( 11591 new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>)); 11592 addChild( 11593 new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>)); 11594 addChild( 11595 new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>)); 11596 addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>)); 11597 addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>)); 11598 addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>)); 11599 addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>)); 11600 addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>)); 11601 addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>)); 11602 addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>)); 11603 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>)); 11604 addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>)); 11605 addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>)); 11606 addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>)); 11607 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>)); 11608 addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>)); 11609 addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>)); 11610 addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation", 11611 TestSubcase::Create<AdvancedMemoryDependentInvocation>)); 11612 addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>)); 11613 addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>)); 11614 addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>)); 11615 addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>)); 11616 addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>)); 11617 addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>)); 11618 addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>)); 11619 addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>)); 11620 addChild( 11621 new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>)); 11622 addChild( 11623 new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>)); 11624 addChild( 11625 new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>)); 11626 addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>)); 11627 addChild( 11628 new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>)); 11629 addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>)); 11630 addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>)); 11631 addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>)); 11632 addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>)); 11633 addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>)); 11634} 11635} 11636