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 "tcuPlatform.hpp" 29#include "tcuRenderTarget.hpp" 30#include "tcuVectorUtil.hpp" 31#include <assert.h> 32#include <climits> 33#include <cmath> 34#include <cstdarg> 35#include <deque> 36#include <iomanip> 37#include <map> 38#include <sstream> 39#include <tcuFloat.hpp> 40 41namespace gl4cts 42{ 43using namespace glw; 44 45namespace 46{ 47typedef tcu::Vec2 vec2; 48typedef tcu::Vec4 vec4; 49typedef tcu::IVec4 ivec4; 50typedef tcu::UVec4 uvec4; 51typedef tcu::Mat4 mat4; 52 53class ShaderImageLoadStoreBase : public deqp::SubcaseBase 54{ 55 virtual std::string Title() 56 { 57 return ""; 58 } 59 60 virtual std::string Purpose() 61 { 62 return ""; 63 } 64 65 virtual std::string Method() 66 { 67 return ""; 68 } 69 70 virtual std::string PassCriteria() 71 { 72 return ""; 73 } 74 75public: 76 bool SupportedInVS(int requiredVS) 77 { 78 GLint imagesVS; 79 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS); 80 if (imagesVS >= requiredVS) 81 return true; 82 else 83 { 84 std::ostringstream reason; 85 reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available." 86 << std::endl; 87 OutputNotSupported(reason.str()); 88 return false; 89 } 90 } 91 92 bool SupportedInTCS(int requiredTCS) 93 { 94 GLint imagesTCS; 95 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS); 96 if (imagesTCS >= requiredTCS) 97 return true; 98 else 99 { 100 std::ostringstream reason; 101 reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available." 102 << std::endl; 103 OutputNotSupported(reason.str()); 104 return false; 105 } 106 } 107 108 bool SupportedInTES(int requiredTES) 109 { 110 GLint imagesTES; 111 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES); 112 if (imagesTES >= requiredTES) 113 return true; 114 else 115 { 116 std::ostringstream reason; 117 reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available." 118 << std::endl; 119 OutputNotSupported(reason.str()); 120 return false; 121 } 122 } 123 124 bool SupportedInGS(int requiredGS) 125 { 126 GLint imagesGS; 127 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS); 128 if (imagesGS >= requiredGS) 129 return true; 130 else 131 { 132 std::ostringstream reason; 133 reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available." 134 << std::endl; 135 OutputNotSupported(reason.str()); 136 return false; 137 } 138 } 139 140 bool SupportedInGeomStages(int required) 141 { 142 return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) && 143 SupportedInGS(required); 144 } 145 146 bool SupportedInStage(int stage, int required) 147 { 148 switch (stage) 149 { 150 case 0: 151 return SupportedInVS(required); 152 case 1: 153 return SupportedInTCS(required); 154 case 2: 155 return SupportedInTES(required); 156 case 3: 157 return SupportedInGS(required); 158 default: 159 return true; 160 } 161 } 162 163 bool SupportedSamples(int required) 164 { 165 int i; 166 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i); 167 if (i >= required) 168 return true; 169 else 170 { 171 std::ostringstream reason; 172 reason << "Required " << required << " image samples but only " << i << " available." << std::endl; 173 OutputNotSupported(reason.str()); 174 return false; 175 } 176 } 177 178 int getWindowWidth() 179 { 180 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 181 return renderTarget.getWidth(); 182 } 183 184 int getWindowHeight() 185 { 186 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 187 return renderTarget.getHeight(); 188 } 189 190 void scaleDimensionsToMemory(int& width, int& height, int devLayers, int sysLayers, int devBPP, int sysBPP) 191 { 192 tcu::PlatformMemoryLimits memoryLimits; 193 m_context.getTestContext().getPlatform().getMemoryLimits(memoryLimits); 194 GLsizeiptr sysSpace = memoryLimits.totalSystemMemory; 195 GLsizeiptr devSpace = memoryLimits.totalDeviceLocalMemory; 196 int devInSysLayers = 0; 197 198 if (devSpace == 0) 199 { 200 devInSysLayers = devLayers; 201 devLayers = 0; 202 } 203 204 // Check if available memory is enough 205 GLsizeiptr pixelsPerLayer = width * height; 206 GLsizeiptr sysRequired = pixelsPerLayer * ((sysBPP * sysLayers) + (devBPP * devInSysLayers)); 207 GLsizeiptr devRequired = pixelsPerLayer * devBPP * devLayers; 208 if ((sysRequired <= sysSpace) && (devRequired <= devSpace)) 209 { 210 return; 211 } 212 213 // Scales the width and height such that the overall texture fits into 214 // the available space for both system and device. 215 GLdouble scale = sqrt(sysSpace / GLdouble(sysRequired)); 216 if (devSpace != 0) 217 { 218 GLdouble devScale = sqrt(devSpace / GLdouble(devRequired)); 219 scale = de::min(devScale, scale); 220 } 221 int newWidth = int(width * scale); 222 int newHeight = int(height * scale); 223 224 m_context.getTestContext().getLog() 225 << tcu::TestLog::Message << "Reducing surface dimensions to fit in memory, from " << width << "x" << height 226 << " to " << newWidth << "x" << newHeight << "." << tcu::TestLog::EndMessage; 227 228 width = newWidth; 229 height = newHeight; 230 } 231 232 inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon) 233 { 234 if (fabs(c0[0] - c1[0]) > epsilon[0]) 235 return false; 236 if (fabs(c0[1] - c1[1]) > epsilon[1]) 237 return false; 238 if (fabs(c0[2] - c1[2]) > epsilon[2]) 239 return false; 240 if (fabs(c0[3] - c1[3]) > epsilon[3]) 241 return false; 242 return true; 243 } 244 245 bool IsEqual(vec4 a, vec4 b) 246 { 247 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]); 248 } 249 250 bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat) 251 { 252 if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM) 253 { 254 return ColorEqual(v0, v1, vec4(0.0001f)); 255 } 256 else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM) 257 { 258 return ColorEqual(v0, v1, vec4(0.01f)); 259 } 260 return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]); 261 } 262 263 bool Equal(const ivec4& a, const ivec4& b, GLenum) 264 { 265 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]); 266 } 267 268 bool Equal(const uvec4& a, const uvec4& b, GLenum) 269 { 270 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]); 271 } 272 273 template <class T> 274 std::string ToString(T v) 275 { 276 std::ostringstream s; 277 s << "["; 278 for (int i = 0; i < 4; ++i) 279 s << v[i] << (i == 3 ? "" : ","); 280 s << "]"; 281 return s.str(); 282 } 283 284 bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected) 285 { 286 bool status = true; 287 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 288 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat(); 289 vec4 g_color_eps = vec4( 290 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits), 291 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits)); 292 293 std::vector<vec4> fb(w * h); 294 glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]); 295 296 for (int yy = 0; yy < h; ++yy) 297 { 298 for (int xx = 0; xx < w; ++xx) 299 { 300 const int idx = yy * w + xx; 301 if (!ColorEqual(fb[idx], expected, g_color_eps)) 302 { 303 m_context.getTestContext().getLog() 304 << tcu::TestLog::Message << "First bad color: " << ToString(fb[idx]) 305 << tcu::TestLog::EndMessage; 306 status = false; 307 return status; 308 } 309 } 310 } 311 return status; 312 } 313 314 bool CompileShader(GLuint shader) 315 { 316 glCompileShader(shader); 317 318 GLint status; 319 glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 320 if (status == GL_FALSE) 321 { 322 GLsizei length; 323 GLchar log[1024]; 324 glGetShaderInfoLog(shader, sizeof(log), &length, log); 325 if (length > 1) 326 { 327 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n" 328 << log << tcu::TestLog::EndMessage; 329 } 330 return false; 331 } 332 return true; 333 } 334 335 bool LinkProgram(GLuint program) 336 { 337 glLinkProgram(program); 338 339 GLint status; 340 glGetProgramiv(program, GL_LINK_STATUS, &status); 341 if (status == GL_FALSE) 342 { 343 GLsizei length; 344 GLchar log[1024]; 345 glGetProgramInfoLog(program, sizeof(log), &length, log); 346 if (length > 1) 347 { 348 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n" 349 << log << tcu::TestLog::EndMessage; 350 } 351 return false; 352 } 353 return true; 354 } 355 356 GLuint BuildProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs, 357 const char* src_fs, bool* result = NULL) 358 { 359 const GLuint p = glCreateProgram(); 360 361 if (src_vs) 362 { 363 GLuint sh = glCreateShader(GL_VERTEX_SHADER); 364 glAttachShader(p, sh); 365 glDeleteShader(sh); 366 glShaderSource(sh, 1, &src_vs, NULL); 367 if (!CompileShader(sh)) 368 { 369 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage; 370 if (result) 371 *result = false; 372 return p; 373 } 374 } 375 if (src_tcs) 376 { 377 GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER); 378 glAttachShader(p, sh); 379 glDeleteShader(sh); 380 glShaderSource(sh, 1, &src_tcs, NULL); 381 if (!CompileShader(sh)) 382 { 383 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage; 384 if (result) 385 *result = false; 386 return p; 387 } 388 } 389 if (src_tes) 390 { 391 GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER); 392 glAttachShader(p, sh); 393 glDeleteShader(sh); 394 glShaderSource(sh, 1, &src_tes, NULL); 395 if (!CompileShader(sh)) 396 { 397 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage; 398 if (result) 399 *result = false; 400 return p; 401 } 402 } 403 if (src_gs) 404 { 405 GLuint sh = glCreateShader(GL_GEOMETRY_SHADER); 406 glAttachShader(p, sh); 407 glDeleteShader(sh); 408 glShaderSource(sh, 1, &src_gs, NULL); 409 if (!CompileShader(sh)) 410 { 411 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage; 412 if (result) 413 *result = false; 414 return p; 415 } 416 } 417 if (src_fs) 418 { 419 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER); 420 glAttachShader(p, sh); 421 glDeleteShader(sh); 422 glShaderSource(sh, 1, &src_fs, NULL); 423 if (!CompileShader(sh)) 424 { 425 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage; 426 if (result) 427 *result = false; 428 return p; 429 } 430 } 431 if (!LinkProgram(p)) 432 { 433 if (src_vs) 434 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage; 435 if (src_tcs) 436 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage; 437 if (src_tes) 438 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage; 439 if (src_gs) 440 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage; 441 if (src_fs) 442 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage; 443 if (result) 444 *result = false; 445 return p; 446 } 447 448 return p; 449 } 450 451 GLuint BuildShaderProgram(GLenum type, const char* src) 452 { 453 const GLuint p = glCreateShaderProgramv(type, 1, &src); 454 455 GLint status; 456 glGetProgramiv(p, GL_LINK_STATUS, &status); 457 if (status == GL_FALSE) 458 { 459 GLchar log[1024]; 460 glGetProgramInfoLog(p, sizeof(log), NULL, log); 461 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n" 462 << log << "\n" 463 << src << tcu::TestLog::EndMessage; 464 } 465 466 return p; 467 } 468 469 void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo) 470 { 471 assert(vao && vbo); 472 473 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red)) 474 const float v[] = { 475 -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, 476 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, 477 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, 478 }; 479 glGenBuffers(1, vbo); 480 glBindBuffer(GL_ARRAY_BUFFER, *vbo); 481 glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW); 482 glBindBuffer(GL_ARRAY_BUFFER, 0); 483 484 if (ebo) 485 { 486 std::vector<GLushort> index_data(4); 487 for (int i = 0; i < 4; ++i) 488 { 489 index_data[i] = static_cast<GLushort>(i); 490 } 491 glGenBuffers(1, ebo); 492 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo); 493 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW); 494 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 495 } 496 497 glGenVertexArrays(1, vao); 498 glBindVertexArray(*vao); 499 glBindBuffer(GL_ARRAY_BUFFER, *vbo); 500 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0); 501 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2)); 502 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5)); 503 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8)); 504 glBindBuffer(GL_ARRAY_BUFFER, 0); 505 glEnableVertexAttribArray(0); 506 glEnableVertexAttribArray(1); 507 glEnableVertexAttribArray(2); 508 glEnableVertexAttribArray(3); 509 if (ebo) 510 { 511 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo); 512 } 513 glBindVertexArray(0); 514 } 515 516 std::string FormatEnumToString(GLenum e) 517 { 518 switch (e) 519 { 520 case GL_RGBA32F: 521 return "rgba32f"; 522 case GL_RGBA16F: 523 return "rgba16f"; 524 case GL_RG32F: 525 return "rg32f"; 526 case GL_RG16F: 527 return "rg16f"; 528 case GL_R11F_G11F_B10F: 529 return "r11f_g11f_b10f"; 530 case GL_R32F: 531 return "r32f"; 532 case GL_R16F: 533 return "r16f"; 534 535 case GL_RGBA32UI: 536 return "rgba32ui"; 537 case GL_RGBA16UI: 538 return "rgba16ui"; 539 case GL_RGB10_A2UI: 540 return "rgb10_a2ui"; 541 case GL_RGBA8UI: 542 return "rgba8ui"; 543 case GL_RG32UI: 544 return "rg32ui"; 545 case GL_RG16UI: 546 return "rg16ui"; 547 case GL_RG8UI: 548 return "rg8ui"; 549 case GL_R32UI: 550 return "r32ui"; 551 case GL_R16UI: 552 return "r16ui"; 553 case GL_R8UI: 554 return "r8ui"; 555 556 case GL_RGBA32I: 557 return "rgba32i"; 558 case GL_RGBA16I: 559 return "rgba16i"; 560 case GL_RGBA8I: 561 return "rgba8i"; 562 case GL_RG32I: 563 return "rg32i"; 564 case GL_RG16I: 565 return "rg16i"; 566 case GL_RG8I: 567 return "rg8i"; 568 case GL_R32I: 569 return "r32i"; 570 case GL_R16I: 571 return "r16i"; 572 case GL_R8I: 573 return "r8i"; 574 575 case GL_RGBA16: 576 return "rgba16"; 577 case GL_RGB10_A2: 578 return "rgb10_a2"; 579 case GL_RGBA8: 580 return "rgba8"; 581 case GL_RG16: 582 return "rg16"; 583 case GL_RG8: 584 return "rg8"; 585 case GL_R16: 586 return "r16"; 587 case GL_R8: 588 return "r8"; 589 590 case GL_RGBA16_SNORM: 591 return "rgba16_snorm"; 592 case GL_RGBA8_SNORM: 593 return "rgba8_snorm"; 594 case GL_RG16_SNORM: 595 return "rg16_snorm"; 596 case GL_RG8_SNORM: 597 return "rg8_snorm"; 598 case GL_R16_SNORM: 599 return "r16_snorm"; 600 case GL_R8_SNORM: 601 return "r8_snorm"; 602 } 603 604 assert(0); 605 return ""; 606 } 607 608 const char* StageName(int stage) 609 { 610 switch (stage) 611 { 612 case 0: 613 return "Vertex Shader"; 614 case 1: 615 return "Tessellation Control Shader"; 616 case 2: 617 return "Tessellation Evaluation Shader"; 618 case 3: 619 return "Geometry Shader"; 620 case 4: 621 return "Compute Shader"; 622 } 623 assert(0); 624 return NULL; 625 } 626 627 template <typename T> 628 GLenum Format(); 629 630 template <typename T> 631 GLenum Type(); 632 633 template <typename T> 634 std::string TypePrefix(); 635 636 template <typename T> 637 GLenum ImageType(GLenum target); 638 639 void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color) 640 { 641 glClearBufferfv(buffer, drawbuffer, &color[0]); 642 } 643 644 void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color) 645 { 646 glClearBufferiv(buffer, drawbuffer, &color[0]); 647 } 648 649 void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color) 650 { 651 glClearBufferuiv(buffer, drawbuffer, &color[0]); 652 } 653 654 bool CheckUniform(GLuint program, const std::string& name, const std::map<std::string, GLuint>& name_index_map, 655 GLint size, GLenum type) 656 { 657 std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name); 658 assert(iter != name_index_map.end()); 659 660 GLchar name_gl[32]; 661 GLsizei length_gl; 662 GLint size_gl; 663 GLenum type_gl; 664 665 glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl); 666 667 if (std::string(name_gl) != name) 668 { 669 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl 670 << " should be " << name << tcu::TestLog::EndMessage; 671 return false; 672 } 673 if (length_gl != static_cast<GLsizei>(name.length())) 674 { 675 m_context.getTestContext().getLog() 676 << tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl 677 << ")" << tcu::TestLog::EndMessage; 678 return false; 679 } 680 if (size_gl != size) 681 { 682 m_context.getTestContext().getLog() 683 << tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl 684 << ")" << tcu::TestLog::EndMessage; 685 return false; 686 } 687 if (type_gl != type) 688 { 689 m_context.getTestContext().getLog() 690 << tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl 691 << ")" << tcu::TestLog::EndMessage; 692 return false; 693 } 694 695 return true; 696 } 697 698 bool CheckMax(GLenum pname, GLint min_value) 699 { 700 GLboolean b; 701 GLint i; 702 GLfloat f; 703 GLdouble d; 704 GLint64 i64; 705 706 glGetIntegerv(pname, &i); 707 if (i < min_value) 708 return false; 709 710 glGetBooleanv(pname, &b); 711 if (b != (i ? GL_TRUE : GL_FALSE)) 712 return false; 713 714 glGetFloatv(pname, &f); 715 if (static_cast<GLint>(f) < min_value) 716 return false; 717 718 glGetDoublev(pname, &d); 719 if (static_cast<GLint>(d) < min_value) 720 return false; 721 722 glGetInteger64v(pname, &i64); 723 if (static_cast<GLint>(i64) < min_value) 724 return false; 725 726 return true; 727 } 728 729 bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, 730 GLenum format) 731 { 732 GLint i; 733 GLboolean b; 734 735 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i); 736 if (static_cast<GLuint>(i) != texture) 737 { 738 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i 739 << " should be " << texture << tcu::TestLog::EndMessage; 740 return false; 741 } 742 glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b); 743 if (b != (i ? GL_TRUE : GL_FALSE)) 744 { 745 m_context.getTestContext().getLog() 746 << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be " 747 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage; 748 return false; 749 } 750 751 glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i); 752 if (i != level) 753 { 754 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i 755 << " should be " << level << tcu::TestLog::EndMessage; 756 return false; 757 } 758 glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b); 759 if (b != (i ? GL_TRUE : GL_FALSE)) 760 { 761 m_context.getTestContext().getLog() 762 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be " 763 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage; 764 return false; 765 } 766 767 glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i); 768 if (i != layered) 769 { 770 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i 771 << " should be " << layered << tcu::TestLog::EndMessage; 772 return false; 773 } 774 glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b); 775 if (b != (i ? GL_TRUE : GL_FALSE)) 776 { 777 m_context.getTestContext().getLog() 778 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be " 779 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage; 780 return false; 781 } 782 783 glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i); 784 if (i != layer) 785 { 786 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i 787 << " should be " << layer << tcu::TestLog::EndMessage; 788 return false; 789 } 790 glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b); 791 if (b != (i ? GL_TRUE : GL_FALSE)) 792 { 793 m_context.getTestContext().getLog() 794 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be " 795 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage; 796 return false; 797 } 798 799 glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i); 800 if (static_cast<GLenum>(i) != access) 801 { 802 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i 803 << " should be " << access << tcu::TestLog::EndMessage; 804 return false; 805 } 806 glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b); 807 if (b != (i ? GL_TRUE : GL_FALSE)) 808 { 809 m_context.getTestContext().getLog() 810 << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be " 811 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage; 812 return false; 813 } 814 815 glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i); 816 if (static_cast<GLenum>(i) != format) 817 { 818 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i 819 << " should be " << format << tcu::TestLog::EndMessage; 820 return false; 821 } 822 glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b); 823 if (b != (i ? GL_TRUE : GL_FALSE)) 824 { 825 m_context.getTestContext().getLog() 826 << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be " 827 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage; 828 return false; 829 } 830 831 return true; 832 } 833 const char* EnumToString(GLenum e) 834 { 835 switch (e) 836 { 837 case GL_TEXTURE_1D: 838 return "GL_TEXTURE_1D"; 839 case GL_TEXTURE_2D: 840 return "GL_TEXTURE_2D"; 841 case GL_TEXTURE_3D: 842 return "GL_TEXTURE_3D"; 843 case GL_TEXTURE_RECTANGLE: 844 return "GL_TEXTURE_RECTANGLE"; 845 case GL_TEXTURE_CUBE_MAP: 846 return "GL_TEXTURE_CUBE_MAP"; 847 case GL_TEXTURE_1D_ARRAY: 848 return "GL_TEXTURE_1D_ARRAY"; 849 case GL_TEXTURE_2D_ARRAY: 850 return "GL_TEXTURE_2D_ARRAY"; 851 case GL_TEXTURE_CUBE_MAP_ARRAY: 852 return "GL_TEXTURE_CUBE_MAP_ARRAY"; 853 854 default: 855 assert(0); 856 break; 857 } 858 return NULL; 859 } 860}; 861 862template <> 863GLenum ShaderImageLoadStoreBase::Format<vec4>() 864{ 865 return GL_RGBA; 866} 867 868template <> 869GLenum ShaderImageLoadStoreBase::Format<ivec4>() 870{ 871 return GL_RGBA_INTEGER; 872} 873 874template <> 875GLenum ShaderImageLoadStoreBase::Format<uvec4>() 876{ 877 return GL_RGBA_INTEGER; 878} 879 880template <> 881GLenum ShaderImageLoadStoreBase::Format<GLint>() 882{ 883 return GL_RED_INTEGER; 884} 885 886template <> 887GLenum ShaderImageLoadStoreBase::Format<GLuint>() 888{ 889 return GL_RED_INTEGER; 890} 891 892template <> 893GLenum ShaderImageLoadStoreBase::Type<vec4>() 894{ 895 return GL_FLOAT; 896} 897 898template <> 899GLenum ShaderImageLoadStoreBase::Type<ivec4>() 900{ 901 return GL_INT; 902} 903 904template <> 905GLenum ShaderImageLoadStoreBase::Type<uvec4>() 906{ 907 return GL_UNSIGNED_INT; 908} 909 910template <> 911GLenum ShaderImageLoadStoreBase::Type<GLint>() 912{ 913 return GL_INT; 914} 915 916template <> 917GLenum ShaderImageLoadStoreBase::Type<GLuint>() 918{ 919 return GL_UNSIGNED_INT; 920} 921 922template <> 923std::string ShaderImageLoadStoreBase::TypePrefix<vec4>() 924{ 925 return ""; 926} 927 928template <> 929std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>() 930{ 931 return "i"; 932} 933 934template <> 935std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>() 936{ 937 return "u"; 938} 939 940template <> 941std::string ShaderImageLoadStoreBase::TypePrefix<GLint>() 942{ 943 return "i"; 944} 945 946template <> 947std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>() 948{ 949 return "u"; 950} 951 952template <> 953GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target) 954{ 955 switch (target) 956 { 957 case GL_TEXTURE_1D: 958 return GL_IMAGE_1D; 959 case GL_TEXTURE_2D: 960 return GL_IMAGE_2D; 961 case GL_TEXTURE_3D: 962 return GL_IMAGE_3D; 963 case GL_TEXTURE_RECTANGLE: 964 return GL_IMAGE_2D_RECT; 965 case GL_TEXTURE_CUBE_MAP: 966 return GL_IMAGE_CUBE; 967 case GL_TEXTURE_BUFFER: 968 return GL_IMAGE_BUFFER; 969 case GL_TEXTURE_1D_ARRAY: 970 return GL_IMAGE_1D_ARRAY; 971 case GL_TEXTURE_2D_ARRAY: 972 return GL_IMAGE_2D_ARRAY; 973 case GL_TEXTURE_CUBE_MAP_ARRAY: 974 return GL_IMAGE_CUBE_MAP_ARRAY; 975 case GL_TEXTURE_2D_MULTISAMPLE: 976 return GL_IMAGE_2D_MULTISAMPLE; 977 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 978 return GL_IMAGE_2D_MULTISAMPLE_ARRAY; 979 } 980 assert(0); 981 return 0; 982} 983 984template <> 985GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target) 986{ 987 switch (target) 988 { 989 case GL_TEXTURE_1D: 990 return GL_INT_IMAGE_1D; 991 case GL_TEXTURE_2D: 992 return GL_INT_IMAGE_2D; 993 case GL_TEXTURE_3D: 994 return GL_INT_IMAGE_3D; 995 case GL_TEXTURE_RECTANGLE: 996 return GL_INT_IMAGE_2D_RECT; 997 case GL_TEXTURE_CUBE_MAP: 998 return GL_INT_IMAGE_CUBE; 999 case GL_TEXTURE_BUFFER: 1000 return GL_INT_IMAGE_BUFFER; 1001 case GL_TEXTURE_1D_ARRAY: 1002 return GL_INT_IMAGE_1D_ARRAY; 1003 case GL_TEXTURE_2D_ARRAY: 1004 return GL_INT_IMAGE_2D_ARRAY; 1005 case GL_TEXTURE_CUBE_MAP_ARRAY: 1006 return GL_INT_IMAGE_CUBE_MAP_ARRAY; 1007 case GL_TEXTURE_2D_MULTISAMPLE: 1008 return GL_INT_IMAGE_2D_MULTISAMPLE; 1009 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 1010 return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY; 1011 } 1012 assert(0); 1013 return 0; 1014} 1015 1016template <> 1017GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target) 1018{ 1019 switch (target) 1020 { 1021 case GL_TEXTURE_1D: 1022 return GL_UNSIGNED_INT_IMAGE_1D; 1023 case GL_TEXTURE_2D: 1024 return GL_UNSIGNED_INT_IMAGE_2D; 1025 case GL_TEXTURE_3D: 1026 return GL_UNSIGNED_INT_IMAGE_3D; 1027 case GL_TEXTURE_RECTANGLE: 1028 return GL_UNSIGNED_INT_IMAGE_2D_RECT; 1029 case GL_TEXTURE_CUBE_MAP: 1030 return GL_UNSIGNED_INT_IMAGE_CUBE; 1031 case GL_TEXTURE_BUFFER: 1032 return GL_UNSIGNED_INT_IMAGE_BUFFER; 1033 case GL_TEXTURE_1D_ARRAY: 1034 return GL_UNSIGNED_INT_IMAGE_1D_ARRAY; 1035 case GL_TEXTURE_2D_ARRAY: 1036 return GL_UNSIGNED_INT_IMAGE_2D_ARRAY; 1037 case GL_TEXTURE_CUBE_MAP_ARRAY: 1038 return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY; 1039 case GL_TEXTURE_2D_MULTISAMPLE: 1040 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE; 1041 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 1042 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY; 1043 } 1044 assert(0); 1045 return 0; 1046} 1047 1048//----------------------------------------------------------------------------- 1049// 1.1.1 BasicAPIGet 1050//----------------------------------------------------------------------------- 1051class BasicAPIGet : public ShaderImageLoadStoreBase 1052{ 1053 virtual long Run() 1054 { 1055 if (!CheckMax(GL_MAX_IMAGE_UNITS, 8)) 1056 { 1057 m_context.getTestContext().getLog() 1058 << tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage; 1059 return ERROR; 1060 } 1061 if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8)) 1062 { 1063 m_context.getTestContext().getLog() 1064 << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid." 1065 << tcu::TestLog::EndMessage; 1066 return ERROR; 1067 } 1068 if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0)) 1069 { 1070 m_context.getTestContext().getLog() 1071 << tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage; 1072 return ERROR; 1073 } 1074 if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0)) 1075 { 1076 m_context.getTestContext().getLog() 1077 << tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid." 1078 << tcu::TestLog::EndMessage; 1079 return ERROR; 1080 } 1081 if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0)) 1082 { 1083 m_context.getTestContext().getLog() 1084 << tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid." 1085 << tcu::TestLog::EndMessage; 1086 return ERROR; 1087 } 1088 if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0)) 1089 { 1090 m_context.getTestContext().getLog() 1091 << tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid." 1092 << tcu::TestLog::EndMessage; 1093 return ERROR; 1094 } 1095 if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0)) 1096 { 1097 m_context.getTestContext().getLog() 1098 << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid." 1099 << tcu::TestLog::EndMessage; 1100 return ERROR; 1101 } 1102 if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8)) 1103 { 1104 m_context.getTestContext().getLog() 1105 << tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid." 1106 << tcu::TestLog::EndMessage; 1107 return ERROR; 1108 } 1109 if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8)) 1110 { 1111 m_context.getTestContext().getLog() 1112 << tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid." 1113 << tcu::TestLog::EndMessage; 1114 return ERROR; 1115 } 1116 return NO_ERROR; 1117 } 1118}; 1119//----------------------------------------------------------------------------- 1120// 1.1.2 BasicAPIBind 1121//----------------------------------------------------------------------------- 1122class BasicAPIBind : public ShaderImageLoadStoreBase 1123{ 1124 GLuint m_texture; 1125 1126 virtual long Setup() 1127 { 1128 m_texture = 0; 1129 return NO_ERROR; 1130 } 1131 1132 virtual long Run() 1133 { 1134 for (GLuint index = 0; index < 8; ++index) 1135 { 1136 if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8)) 1137 { 1138 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index 1139 << " has invalid default state." << tcu::TestLog::EndMessage; 1140 return ERROR; 1141 } 1142 } 1143 1144 glGenTextures(1, &m_texture); 1145 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 1146 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL); 1147 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL); 1148 glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL); 1149 glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL); 1150 glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL); 1151 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 1152 1153 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); 1154 if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F)) 1155 return ERROR; 1156 1157 glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8); 1158 if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8)) 1159 return ERROR; 1160 1161 glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16); 1162 if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16)) 1163 return ERROR; 1164 1165 glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I); 1166 if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I)) 1167 return ERROR; 1168 1169 glDeleteTextures(1, &m_texture); 1170 m_texture = 0; 1171 1172 for (GLuint index = 0; index < 8; ++index) 1173 { 1174 GLint name; 1175 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name); 1176 if (name != 0) 1177 { 1178 m_context.getTestContext().getLog() 1179 << tcu::TestLog::Message << "Binding point " << index 1180 << " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage; 1181 return ERROR; 1182 } 1183 } 1184 1185 return NO_ERROR; 1186 } 1187 1188 virtual long Cleanup() 1189 { 1190 glDeleteTextures(1, &m_texture); 1191 return NO_ERROR; 1192 } 1193}; 1194//----------------------------------------------------------------------------- 1195// 1.1.3 BasicAPIBarrier 1196//----------------------------------------------------------------------------- 1197class BasicAPIBarrier : public ShaderImageLoadStoreBase 1198{ 1199 virtual long Run() 1200 { 1201 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT); 1202 glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT); 1203 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT); 1204 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); 1205 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 1206 glMemoryBarrier(GL_COMMAND_BARRIER_BIT); 1207 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); 1208 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 1209 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 1210 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); 1211 glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT); 1212 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT); 1213 1214 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT | 1215 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT | 1216 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT | 1217 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT); 1218 1219 glMemoryBarrier(GL_ALL_BARRIER_BITS); 1220 1221 return NO_ERROR; 1222 } 1223}; 1224//----------------------------------------------------------------------------- 1225// 1.1.4 BasicAPITexParam 1226//----------------------------------------------------------------------------- 1227class BasicAPITexParam : public ShaderImageLoadStoreBase 1228{ 1229 GLuint m_texture; 1230 1231 virtual long Setup() 1232 { 1233 m_texture = 0; 1234 return NO_ERROR; 1235 } 1236 1237 virtual long Run() 1238 { 1239 glGenTextures(1, &m_texture); 1240 glBindTexture(GL_TEXTURE_2D, m_texture); 1241 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL); 1242 1243 GLint i; 1244 GLfloat f; 1245 GLuint ui; 1246 1247 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i); 1248 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE) 1249 { 1250 m_context.getTestContext().getLog() 1251 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to " 1252 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL." 1253 << tcu::TestLog::EndMessage; 1254 return ERROR; 1255 } 1256 glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f); 1257 if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE) 1258 { 1259 m_context.getTestContext().getLog() 1260 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to " 1261 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL." 1262 << tcu::TestLog::EndMessage; 1263 return ERROR; 1264 } 1265 glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i); 1266 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE) 1267 { 1268 m_context.getTestContext().getLog() 1269 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to " 1270 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL." 1271 << tcu::TestLog::EndMessage; 1272 return ERROR; 1273 } 1274 glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui); 1275 if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE) 1276 { 1277 m_context.getTestContext().getLog() 1278 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to " 1279 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL." 1280 << tcu::TestLog::EndMessage; 1281 return ERROR; 1282 } 1283 1284 return NO_ERROR; 1285 } 1286 1287 virtual long Cleanup() 1288 { 1289 glDeleteTextures(1, &m_texture); 1290 return NO_ERROR; 1291 } 1292}; 1293//----------------------------------------------------------------------------- 1294// 1.2.1 BasicAllFormatsStore 1295//----------------------------------------------------------------------------- 1296class BasicAllFormatsStore : public ShaderImageLoadStoreBase 1297{ 1298 GLuint m_vao; 1299 GLuint m_vbo; 1300 1301 virtual long Setup() 1302 { 1303 m_vao = 0; 1304 m_vbo = 0; 1305 return NO_ERROR; 1306 } 1307 1308 virtual long Run() 1309 { 1310 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 1311 1312 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1313 return ERROR; 1314 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1315 return ERROR; 1316 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1317 return ERROR; 1318 1319 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1320 return ERROR; 1321 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1322 return ERROR; 1323 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1324 return ERROR; 1325 1326 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1327 return ERROR; 1328 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1329 return ERROR; 1330 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1331 return ERROR; 1332 1333 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f))) 1334 return ERROR; 1335 1336 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1337 return ERROR; 1338 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1339 return ERROR; 1340 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1341 return ERROR; 1342 1343 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1344 return ERROR; 1345 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1346 return ERROR; 1347 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1348 return ERROR; 1349 1350 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1351 return ERROR; 1352 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1353 return ERROR; 1354 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1355 return ERROR; 1356 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1357 return ERROR; 1358 1359 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1360 return ERROR; 1361 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1362 return ERROR; 1363 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1364 return ERROR; 1365 1366 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1367 return ERROR; 1368 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1369 return ERROR; 1370 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1371 return ERROR; 1372 1373 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f))) 1374 return ERROR; 1375 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f))) 1376 return ERROR; 1377 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1378 return ERROR; 1379 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1380 return ERROR; 1381 1382 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 1383 return ERROR; 1384 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1385 return ERROR; 1386 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1387 return ERROR; 1388 1389 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1390 return ERROR; 1391 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1392 return ERROR; 1393 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1394 return ERROR; 1395 1396 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1397 return ERROR; 1398 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1399 return ERROR; 1400 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1401 return ERROR; 1402 1403 return NO_ERROR; 1404 } 1405 1406 template <typename T> 1407 bool Write(GLenum internalformat, const T& write_value, const T& expected_value) 1408 { 1409 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 1410 " gl_Position = i_position;" NL "}"; 1411 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str()); 1412 const int kSize = 16; 1413 std::vector<T> data(kSize * kSize); 1414 GLuint texture; 1415 glGenTextures(1, &texture); 1416 1417 for (GLuint unit = 0; unit < 8; ++unit) 1418 { 1419 glBindTexture(GL_TEXTURE_2D, texture); 1420 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1422 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 1423 glBindTexture(GL_TEXTURE_2D, 0); 1424 1425 glViewport(0, 0, kSize, kSize); 1426 glUseProgram(program); 1427 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 1428 glBindVertexArray(m_vao); 1429 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1430 1431 glBindTexture(GL_TEXTURE_2D, texture); 1432 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 1433 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]); 1434 1435 for (int i = 0; i < kSize * kSize; ++i) 1436 { 1437 if (!Equal(data[i], expected_value, internalformat)) 1438 { 1439 glDeleteTextures(1, &texture); 1440 glUseProgram(0); 1441 glDeleteProgram(program); 1442 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i]) 1443 << ". Value should be: " << ToString(expected_value) 1444 << ". Format is: " << FormatEnumToString(internalformat) 1445 << ". Unit is: " << unit << tcu::TestLog::EndMessage; 1446 return false; 1447 } 1448 } 1449 1450 if (unit < 7) 1451 { 1452 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1)); 1453 } 1454 } 1455 1456 glDeleteTextures(1, &texture); 1457 glUseProgram(0); 1458 glDeleteProgram(program); 1459 1460 return true; 1461 } 1462 1463 virtual long Cleanup() 1464 { 1465 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 1466 glDeleteVertexArrays(1, &m_vao); 1467 glDeleteBuffers(1, &m_vbo); 1468 return NO_ERROR; 1469 } 1470 1471 template <typename T> 1472 std::string GenFS(GLenum internalformat, const T& value) 1473 { 1474 std::ostringstream os; 1475 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 1476 << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 1477 " imageStore(g_image, coord, " 1478 << TypePrefix<T>() << "vec4" << value << ");" NL " discard;" NL "}"; 1479 return os.str(); 1480 } 1481}; 1482//----------------------------------------------------------------------------- 1483// 1.2.2 BasicAllFormatsLoad 1484//----------------------------------------------------------------------------- 1485class BasicAllFormatsLoad : public ShaderImageLoadStoreBase 1486{ 1487 GLuint m_vao; 1488 GLuint m_vbo; 1489 1490 virtual long Setup() 1491 { 1492 m_vao = 0; 1493 m_vbo = 0; 1494 return NO_ERROR; 1495 } 1496 1497 virtual long Run() 1498 { 1499 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 1500 1501 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1502 return ERROR; 1503 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1504 return ERROR; 1505 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1506 return ERROR; 1507 1508 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1509 return ERROR; 1510 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1511 return ERROR; 1512 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1513 return ERROR; 1514 1515 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1516 return ERROR; 1517 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1518 return ERROR; 1519 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1520 return ERROR; 1521 1522 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f))) 1523 return ERROR; 1524 1525 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1526 return ERROR; 1527 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1528 return ERROR; 1529 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1530 return ERROR; 1531 1532 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1533 return ERROR; 1534 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1535 return ERROR; 1536 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1537 return ERROR; 1538 1539 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1540 return ERROR; 1541 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1542 return ERROR; 1543 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1544 return ERROR; 1545 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1546 return ERROR; 1547 1548 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1549 return ERROR; 1550 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1551 return ERROR; 1552 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1553 return ERROR; 1554 1555 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1556 return ERROR; 1557 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1558 return ERROR; 1559 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1560 return ERROR; 1561 1562 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f))) 1563 return ERROR; 1564 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f))) 1565 return ERROR; 1566 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1567 return ERROR; 1568 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1569 return ERROR; 1570 1571 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 1572 return ERROR; 1573 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1574 return ERROR; 1575 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1576 return ERROR; 1577 1578 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1579 return ERROR; 1580 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1581 return ERROR; 1582 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1583 return ERROR; 1584 1585 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1586 return ERROR; 1587 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1588 return ERROR; 1589 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1590 return ERROR; 1591 1592 return NO_ERROR; 1593 } 1594 1595 template <typename T> 1596 bool Read(GLenum internalformat, const T& value, const T& expected_value) 1597 { 1598 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 1599 " gl_Position = i_position;" NL "}"; 1600 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str()); 1601 const int kSize = 16; 1602 std::vector<T> data(kSize * kSize, value); 1603 GLuint texture; 1604 glGenTextures(1, &texture); 1605 1606 for (GLuint unit = 0; unit < 8; ++unit) 1607 { 1608 glBindTexture(GL_TEXTURE_2D, texture); 1609 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1610 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1611 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 1612 glBindTexture(GL_TEXTURE_2D, 0); 1613 1614 glViewport(0, 0, kSize, kSize); 1615 glClear(GL_COLOR_BUFFER_BIT); 1616 glUseProgram(program); 1617 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 1618 glBindVertexArray(m_vao); 1619 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1620 1621 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 1622 { 1623 glDeleteTextures(1, &texture); 1624 glUseProgram(0); 1625 glDeleteProgram(program); 1626 m_context.getTestContext().getLog() 1627 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat) 1628 << ". Unit is: " << unit << tcu::TestLog::EndMessage; 1629 return false; 1630 } 1631 1632 if (unit < 7) 1633 { 1634 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1)); 1635 } 1636 } 1637 1638 glDeleteTextures(1, &texture); 1639 glUseProgram(0); 1640 glDeleteProgram(program); 1641 1642 return true; 1643 } 1644 1645 virtual long Cleanup() 1646 { 1647 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 1648 glDeleteVertexArrays(1, &m_vao); 1649 glDeleteBuffers(1, &m_vbo); 1650 return NO_ERROR; 1651 } 1652 1653 template <typename T> 1654 std::string GenFS(GLenum internalformat, const T& expected_value) 1655 { 1656 std::ostringstream os; 1657 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 1658 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 1659 << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " " 1660 << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL " if (v != " << TypePrefix<T>() << "vec4" 1661 << expected_value 1662 << ") 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 "}"; 1663 return os.str(); 1664 } 1665}; 1666//----------------------------------------------------------------------------- 1667// 1.2.3 BasicAllFormatsStoreGeometryStages 1668//----------------------------------------------------------------------------- 1669class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase 1670{ 1671 GLuint m_vao; 1672 1673 virtual long Setup() 1674 { 1675 glGenVertexArrays(1, &m_vao); 1676 return NO_ERROR; 1677 } 1678 1679 virtual long Run() 1680 { 1681 if (!SupportedInGeomStages(1)) 1682 return NOT_SUPPORTED; 1683 glEnable(GL_RASTERIZER_DISCARD); 1684 1685 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1686 return ERROR; 1687 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1688 return ERROR; 1689 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1690 return ERROR; 1691 1692 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1693 return ERROR; 1694 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1695 return ERROR; 1696 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1697 return ERROR; 1698 1699 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1700 return ERROR; 1701 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1702 return ERROR; 1703 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1704 return ERROR; 1705 1706 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f))) 1707 return ERROR; 1708 1709 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1710 return ERROR; 1711 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1712 return ERROR; 1713 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1714 return ERROR; 1715 1716 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1717 return ERROR; 1718 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1719 return ERROR; 1720 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1721 return ERROR; 1722 1723 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1724 return ERROR; 1725 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1726 return ERROR; 1727 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1728 return ERROR; 1729 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1730 return ERROR; 1731 1732 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1733 return ERROR; 1734 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1735 return ERROR; 1736 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1737 return ERROR; 1738 1739 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1740 return ERROR; 1741 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1742 return ERROR; 1743 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1744 return ERROR; 1745 1746 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f))) 1747 return ERROR; 1748 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f))) 1749 return ERROR; 1750 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1751 return ERROR; 1752 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1753 return ERROR; 1754 1755 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 1756 return ERROR; 1757 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1758 return ERROR; 1759 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1760 return ERROR; 1761 1762 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1763 return ERROR; 1764 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1765 return ERROR; 1766 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1767 return ERROR; 1768 1769 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1770 return ERROR; 1771 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1772 return ERROR; 1773 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1774 return ERROR; 1775 1776 return NO_ERROR; 1777 } 1778 1779 template <typename T> 1780 bool Write(GLenum internalformat, const T& write_value, const T& expected_value) 1781 { 1782 const GLuint program = 1783 BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(), 1784 GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL); 1785 const int kSize = 1; 1786 std::vector<T> data(kSize * kSize); 1787 GLuint texture[4]; 1788 glGenTextures(4, texture); 1789 1790 for (int i = 0; i < 4; ++i) 1791 { 1792 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]); 1793 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1794 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1795 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]); 1796 } 1797 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 1798 1799 glUseProgram(program); 1800 glUniform1i(glGetUniformLocation(program, "g_image0"), 0); 1801 glUniform1i(glGetUniformLocation(program, "g_image1"), 1); 1802 glUniform1i(glGetUniformLocation(program, "g_image2"), 2); 1803 glUniform1i(glGetUniformLocation(program, "g_image3"), 3); 1804 for (GLuint i = 0; i < 4; ++i) 1805 { 1806 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 1807 } 1808 glBindVertexArray(m_vao); 1809 glPatchParameteri(GL_PATCH_VERTICES, 1); 1810 glDrawArrays(GL_PATCHES, 0, 1); 1811 glPatchParameteri(GL_PATCH_VERTICES, 3); 1812 1813 for (int i = 0; i < 4; ++i) 1814 { 1815 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]); 1816 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 1817 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]); 1818 1819 if (!Equal(data[0], expected_value, internalformat)) 1820 { 1821 glDeleteTextures(4, texture); 1822 glUseProgram(0); 1823 glDeleteProgram(program); 1824 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0]) 1825 << ". Value should be: " << ToString(expected_value) 1826 << ". Format is: " << FormatEnumToString(internalformat) 1827 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage; 1828 return false; 1829 } 1830 } 1831 glDeleteTextures(4, texture); 1832 glUseProgram(0); 1833 glDeleteProgram(program); 1834 return true; 1835 } 1836 1837 virtual long Cleanup() 1838 { 1839 glDisable(GL_RASTERIZER_DISCARD); 1840 glDeleteVertexArrays(1, &m_vao); 1841 return NO_ERROR; 1842 } 1843 1844 template <typename T> 1845 std::string GenVS(GLenum internalformat, const T& value) 1846 { 1847 std::ostringstream os; 1848 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 1849 << TypePrefix<T>() << "image2DArray g_image0;" NL "void main() {" NL 1850 " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " imageStore(g_image0, coord, " 1851 << TypePrefix<T>() << "vec4" << value << ");" NL "}"; 1852 return os.str(); 1853 } 1854 1855 template <typename T> 1856 std::string GenTCS(GLenum internalformat, const T& value) 1857 { 1858 std::ostringstream os; 1859 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat) 1860 << ") writeonly uniform " << TypePrefix<T>() 1861 << "image2DArray g_image1;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL 1862 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL 1863 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL 1864 " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " imageStore(g_image1, coord, " 1865 << TypePrefix<T>() << "vec4" << value << ");" NL "}"; 1866 return os.str(); 1867 } 1868 1869 template <typename T> 1870 std::string GenTES(GLenum internalformat, const T& value) 1871 { 1872 std::ostringstream os; 1873 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout(" 1874 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 1875 << "image2DArray g_image2;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL 1876 " imageStore(g_image2, coord, " 1877 << TypePrefix<T>() << "vec4" << value << ");" NL "}"; 1878 return os.str(); 1879 } 1880 1881 template <typename T> 1882 std::string GenGS(GLenum internalformat, const T& value) 1883 { 1884 std::ostringstream os; 1885 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout(" 1886 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 1887 << "image2DArray g_image3;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL 1888 " imageStore(g_image3, coord, " 1889 << TypePrefix<T>() << "vec4" << value << ");" NL "}"; 1890 return os.str(); 1891 } 1892}; 1893//----------------------------------------------------------------------------- 1894// 1.2.4 BasicAllFormatsLoadGeometryStages 1895//----------------------------------------------------------------------------- 1896class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase 1897{ 1898 GLuint m_vao; 1899 1900 virtual long Setup() 1901 { 1902 glGenVertexArrays(1, &m_vao); 1903 return NO_ERROR; 1904 } 1905 1906 virtual long Run() 1907 { 1908 if (!SupportedInGeomStages(2)) 1909 return NOT_SUPPORTED; 1910 glEnable(GL_RASTERIZER_DISCARD); 1911 1912 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1913 return ERROR; 1914 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1915 return ERROR; 1916 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1917 return ERROR; 1918 1919 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1920 return ERROR; 1921 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 1922 return ERROR; 1923 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1924 return ERROR; 1925 1926 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1927 return ERROR; 1928 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1929 return ERROR; 1930 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1931 return ERROR; 1932 1933 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f))) 1934 return ERROR; 1935 1936 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1937 return ERROR; 1938 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1939 return ERROR; 1940 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1941 return ERROR; 1942 1943 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1944 return ERROR; 1945 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 1946 return ERROR; 1947 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1948 return ERROR; 1949 1950 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1951 return ERROR; 1952 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1953 return ERROR; 1954 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1955 return ERROR; 1956 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1957 return ERROR; 1958 1959 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1960 return ERROR; 1961 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1962 return ERROR; 1963 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1964 return ERROR; 1965 1966 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1967 return ERROR; 1968 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 1969 return ERROR; 1970 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1971 return ERROR; 1972 1973 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f))) 1974 return ERROR; 1975 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f))) 1976 return ERROR; 1977 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1978 return ERROR; 1979 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1980 return ERROR; 1981 1982 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 1983 return ERROR; 1984 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 1985 return ERROR; 1986 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1987 return ERROR; 1988 1989 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1990 return ERROR; 1991 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1992 return ERROR; 1993 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 1994 return ERROR; 1995 1996 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1997 return ERROR; 1998 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 1999 return ERROR; 2000 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 2001 return ERROR; 2002 2003 return NO_ERROR; 2004 } 2005 2006 template <typename T> 2007 bool Read(GLenum internalformat, const T& value, const T& expected_value) 2008 { 2009 const GLuint program = BuildProgram( 2010 GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(), 2011 GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL); 2012 const int kSize = 1; 2013 std::vector<T> data(kSize * kSize, value); 2014 GLuint texture[8]; 2015 glGenTextures(8, texture); 2016 2017 for (int i = 0; i < 4; ++i) 2018 { 2019 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]); 2020 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2021 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2022 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]); 2023 } 2024 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 2025 vec4 zero(0); 2026 for (int i = 4; i < 8; ++i) 2027 { 2028 glBindTexture(GL_TEXTURE_2D, texture[i]); 2029 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2030 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2031 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero); 2032 } 2033 glBindTexture(GL_TEXTURE_2D, 0); 2034 2035 glUseProgram(program); 2036 glUniform1i(glGetUniformLocation(program, "g_image0"), 0); 2037 glUniform1i(glGetUniformLocation(program, "g_image1"), 1); 2038 glUniform1i(glGetUniformLocation(program, "g_image2"), 2); 2039 glUniform1i(glGetUniformLocation(program, "g_image3"), 3); 2040 glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4); 2041 glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5); 2042 glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6); 2043 glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7); 2044 2045 for (GLuint i = 0; i < 4; ++i) 2046 { 2047 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 2048 } 2049 for (GLuint i = 4; i < 8; ++i) 2050 { 2051 glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 2052 } 2053 glBindVertexArray(m_vao); 2054 glPatchParameteri(GL_PATCH_VERTICES, 1); 2055 glDrawArrays(GL_PATCHES, 0, 1); 2056 glPatchParameteri(GL_PATCH_VERTICES, 3); 2057 2058 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 2059 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat(); 2060 vec4 g_color_eps = vec4( 2061 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits), 2062 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits)); 2063 2064 for (int i = 0; i < 4; ++i) 2065 { 2066 glBindTexture(GL_TEXTURE_2D, texture[i + 4]); 2067 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2068 vec4 result; 2069 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]); 2070 if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps)) 2071 { 2072 glDeleteTextures(8, texture); 2073 glUseProgram(0); 2074 glDeleteProgram(program); 2075 m_context.getTestContext().getLog() 2076 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat) 2077 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage; 2078 return false; 2079 } 2080 } 2081 glDeleteTextures(8, texture); 2082 glUseProgram(0); 2083 glDeleteProgram(program); 2084 return true; 2085 } 2086 2087 virtual long Cleanup() 2088 { 2089 glDisable(GL_RASTERIZER_DISCARD); 2090 glDeleteVertexArrays(1, &m_vao); 2091 return NO_ERROR; 2092 } 2093 2094 template <typename T> 2095 std::string GenVS(GLenum internalformat, const T& expected_value) 2096 { 2097 std::ostringstream os; 2098 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 2099 << TypePrefix<T>() 2100 << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL 2101 "void main() {" NL " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " " 2102 << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL " if (v != " << TypePrefix<T>() << "vec4" 2103 << expected_value << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL 2104 " else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}"; 2105 return os.str(); 2106 } 2107 2108 template <typename T> 2109 std::string GenTCS(GLenum internalformat, const T& expected_value) 2110 { 2111 std::ostringstream os; 2112 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat) 2113 << ") readonly uniform " << TypePrefix<T>() 2114 << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL 2115 "void main() {" NL " gl_TessLevelInner[0] = 1;" NL " gl_TessLevelInner[1] = 1;" NL 2116 " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL " gl_TessLevelOuter[2] = 1;" NL 2117 " gl_TessLevelOuter[3] = 1;" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " " 2118 << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL " if (v != " << TypePrefix<T>() << "vec4" 2119 << expected_value << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL 2120 " else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}"; 2121 return os.str(); 2122 } 2123 2124 template <typename T> 2125 std::string GenTES(GLenum internalformat, const T& expected_value) 2126 { 2127 std::ostringstream os; 2128 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout(" 2129 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 2130 << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL 2131 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " " 2132 << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL " if (v != " << TypePrefix<T>() << "vec4" 2133 << expected_value << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL 2134 " else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}"; 2135 return os.str(); 2136 } 2137 2138 template <typename T> 2139 std::string GenGS(GLenum internalformat, const T& expected_value) 2140 { 2141 std::ostringstream os; 2142 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout(" 2143 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 2144 << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL 2145 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL " " 2146 << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL " if (v != " << TypePrefix<T>() << "vec4" 2147 << expected_value << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL 2148 " else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}"; 2149 return os.str(); 2150 } 2151}; 2152//----------------------------------------------------------------------------- 2153// 1.2.5 BasicAllFormatsLoadStoreComputeStage 2154//----------------------------------------------------------------------------- 2155class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase 2156{ 2157 virtual long Run() 2158 { 2159 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) 2160 { 2161 m_context.getTestContext().getLog() 2162 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test" 2163 << tcu::TestLog::EndMessage; 2164 return NOT_SUPPORTED; 2165 } 2166 2167 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 2168 return ERROR; 2169 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 2170 return ERROR; 2171 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 2172 return ERROR; 2173 2174 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 2175 return ERROR; 2176 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 2177 return ERROR; 2178 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 2179 return ERROR; 2180 2181 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2182 return ERROR; 2183 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 2184 return ERROR; 2185 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 2186 return ERROR; 2187 2188 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f))) 2189 return ERROR; 2190 2191 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2192 return ERROR; 2193 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 2194 return ERROR; 2195 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 2196 return ERROR; 2197 2198 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2199 return ERROR; 2200 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 2201 return ERROR; 2202 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 2203 return ERROR; 2204 2205 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 2206 return ERROR; 2207 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 2208 return ERROR; 2209 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 2210 return ERROR; 2211 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 2212 return ERROR; 2213 2214 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 2215 return ERROR; 2216 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 2217 return ERROR; 2218 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 2219 return ERROR; 2220 2221 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 2222 return ERROR; 2223 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 2224 return ERROR; 2225 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 2226 return ERROR; 2227 2228 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f))) 2229 return ERROR; 2230 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f))) 2231 return ERROR; 2232 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 2233 return ERROR; 2234 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 2235 return ERROR; 2236 2237 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 2238 return ERROR; 2239 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 2240 return ERROR; 2241 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 2242 return ERROR; 2243 2244 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 2245 return ERROR; 2246 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 2247 return ERROR; 2248 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 2249 return ERROR; 2250 2251 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 2252 return ERROR; 2253 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 2254 return ERROR; 2255 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 2256 return ERROR; 2257 2258 return NO_ERROR; 2259 } 2260 2261 template <typename T> 2262 bool Read(GLenum internalformat, const T& value, const T& expected_value) 2263 { 2264 GLuint program; 2265 std::string source = GenCS<T>(internalformat); 2266 const char* const src = source.c_str(); 2267 GLuint sh = glCreateShader(GL_COMPUTE_SHADER); 2268 glShaderSource(sh, 1, &src, NULL); 2269 glCompileShader(sh); 2270 program = glCreateProgram(); 2271 glAttachShader(program, sh); 2272 glLinkProgram(program); 2273 glDeleteShader(sh); 2274 2275 const int kSize = 1; 2276 std::vector<T> data(kSize * kSize, value); 2277 GLuint texture[2]; 2278 glGenTextures(2, texture); 2279 2280 glBindTexture(GL_TEXTURE_2D, texture[0]); 2281 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2282 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2283 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2284 glBindTexture(GL_TEXTURE_2D, texture[1]); 2285 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2286 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2287 vec4 zero(0); 2288 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero); 2289 2290 glBindTexture(GL_TEXTURE_2D, 0); 2291 2292 glUseProgram(program); 2293 glUniform1i(glGetUniformLocation(program, "g_image_read"), 0); 2294 glUniform1i(glGetUniformLocation(program, "g_image_write"), 1); 2295 2296 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 2297 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2298 2299 glDispatchCompute(1, 1, 1); 2300 2301 for (int i = 0; i < 2; ++i) 2302 { 2303 glBindTexture(GL_TEXTURE_2D, texture[i]); 2304 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2305 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]); 2306 2307 if (!Equal(data[0], expected_value, internalformat)) 2308 { 2309 glDeleteTextures(4, texture); 2310 glUseProgram(0); 2311 glDeleteProgram(program); 2312 m_context.getTestContext().getLog() 2313 << tcu::TestLog::Message << "Value is: " << ToString(data[0]) 2314 << ". Value should be: " << ToString(expected_value) 2315 << ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage; 2316 return false; 2317 } 2318 } 2319 glDeleteTextures(2, texture); 2320 glUseProgram(0); 2321 glDeleteProgram(program); 2322 return true; 2323 } 2324 2325 template <typename T> 2326 std::string GenCS(GLenum internalformat) 2327 { 2328 std::ostringstream os; 2329 os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL 2330 "layout(" 2331 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 2332 << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 2333 << TypePrefix<T>() << "image2D g_image_write;" NL "void main() {" NL 2334 " ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL " " 2335 << TypePrefix<T>() 2336 << "vec4 v = imageLoad(g_image_read, coord);" NL " imageStore(g_image_write, coord, v);" NL "}"; 2337 return os.str(); 2338 } 2339}; 2340//----------------------------------------------------------------------------- 2341// 1.3.1 BasicAllTargetsStore 2342//----------------------------------------------------------------------------- 2343class BasicAllTargetsStore : public ShaderImageLoadStoreBase 2344{ 2345 GLuint m_vao; 2346 GLuint m_vbo; 2347 2348 virtual long Setup() 2349 { 2350 m_vao = 0; 2351 m_vbo = 0; 2352 return NO_ERROR; 2353 } 2354 2355 virtual long Run() 2356 { 2357 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 2358 2359 if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 2360 return ERROR; 2361 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2362 return ERROR; 2363 if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 2364 return ERROR; 2365 2366 if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 2367 return ERROR; 2368 if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2369 return ERROR; 2370 if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 2371 return ERROR; 2372 2373 if (SupportedSamples(4)) 2374 { 2375 if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 2376 return ERROR; 2377 2378 GLint isamples; 2379 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples); 2380 if (isamples >= 4) 2381 { 2382 if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2383 return ERROR; 2384 if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 2385 return ERROR; 2386 } 2387 } 2388 return NO_ERROR; 2389 } 2390 2391 virtual long Cleanup() 2392 { 2393 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 2394 glDeleteVertexArrays(1, &m_vao); 2395 glDeleteBuffers(1, &m_vbo); 2396 return NO_ERROR; 2397 } 2398 2399 template <typename T> 2400 bool Write(GLenum internalformat, const T& write_value, const T& expected_value) 2401 { 2402 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 2403 " gl_Position = i_position;" NL "}"; 2404 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str()); 2405 GLuint textures[8]; 2406 GLuint buffer; 2407 glGenTextures(8, textures); 2408 glGenBuffers(1, &buffer); 2409 2410 const int kSize = 16; 2411 std::vector<T> data(kSize * kSize * 2); 2412 2413 glBindTexture(GL_TEXTURE_1D, textures[0]); 2414 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2415 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2416 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2417 glBindTexture(GL_TEXTURE_1D, 0); 2418 2419 glBindTexture(GL_TEXTURE_2D, textures[1]); 2420 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2422 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2423 glBindTexture(GL_TEXTURE_2D, 0); 2424 2425 glBindTexture(GL_TEXTURE_3D, textures[2]); 2426 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2427 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2428 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 2429 glBindTexture(GL_TEXTURE_3D, 0); 2430 2431 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]); 2432 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2433 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2434 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2435 glBindTexture(GL_TEXTURE_RECTANGLE, 0); 2436 2437 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); 2438 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2439 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2440 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 2441 &data[0]); 2442 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 2443 &data[0]); 2444 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 2445 &data[0]); 2446 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 2447 &data[0]); 2448 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 2449 &data[0]); 2450 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 2451 &data[0]); 2452 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 2453 2454 glBindBuffer(GL_TEXTURE_BUFFER, buffer); 2455 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW); 2456 glBindBuffer(GL_TEXTURE_BUFFER, 0); 2457 glBindTexture(GL_TEXTURE_BUFFER, textures[5]); 2458 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer); 2459 glBindTexture(GL_TEXTURE_BUFFER, 0); 2460 2461 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]); 2462 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2463 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2464 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 2465 glBindTexture(GL_TEXTURE_1D_ARRAY, 0); 2466 2467 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); 2468 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2469 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2470 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 2471 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 2472 2473 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 2474 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 2475 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2476 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 2477 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2478 glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 2479 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2480 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2481 2482 glUseProgram(program); 2483 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0); 2484 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1); 2485 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2); 2486 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3); 2487 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4); 2488 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5); 2489 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6); 2490 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7); 2491 2492 glBindVertexArray(m_vao); 2493 glViewport(0, 0, kSize, kSize); 2494 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 2495 2496 bool status = true; 2497 2498 glBindTexture(GL_TEXTURE_1D, textures[0]); 2499 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2500 glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]); 2501 glBindTexture(GL_TEXTURE_1D, 0); 2502 for (int i = 0; i < kSize; ++i) 2503 { 2504 if (!tcu::allEqual(data[i], expected_value)) 2505 { 2506 status = false; 2507 m_context.getTestContext().getLog() 2508 << tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i]) 2509 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2510 break; 2511 } 2512 } 2513 std::fill(data.begin(), data.end(), T(0)); 2514 2515 glBindTexture(GL_TEXTURE_2D, textures[1]); 2516 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2517 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]); 2518 glBindTexture(GL_TEXTURE_2D, 0); 2519 for (int i = 0; i < kSize * kSize; ++i) 2520 { 2521 if (!tcu::allEqual(data[i], expected_value)) 2522 { 2523 status = false; 2524 m_context.getTestContext().getLog() 2525 << tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i]) 2526 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2527 break; 2528 } 2529 } 2530 2531 glBindTexture(GL_TEXTURE_3D, textures[2]); 2532 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2533 glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]); 2534 glBindTexture(GL_TEXTURE_3D, 0); 2535 for (int i = 0; i < kSize * kSize * 2; ++i) 2536 { 2537 if (!tcu::allEqual(data[i], expected_value)) 2538 { 2539 status = false; 2540 m_context.getTestContext().getLog() 2541 << tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i]) 2542 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2543 break; 2544 } 2545 } 2546 2547 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]); 2548 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2549 glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]); 2550 glBindTexture(GL_TEXTURE_RECTANGLE, 0); 2551 for (int i = 0; i < kSize * kSize; ++i) 2552 { 2553 if (!tcu::allEqual(data[i], expected_value)) 2554 { 2555 status = false; 2556 m_context.getTestContext().getLog() 2557 << tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i]) 2558 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2559 break; 2560 } 2561 } 2562 2563 { 2564 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); 2565 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2566 for (int face = 0; face < 6; ++face) 2567 { 2568 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]); 2569 for (int i = 0; i < kSize * kSize; ++i) 2570 { 2571 if (!tcu::allEqual(data[i], expected_value)) 2572 { 2573 status = false; 2574 m_context.getTestContext().getLog() 2575 << tcu::TestLog::Message 2576 << "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i]) 2577 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2578 break; 2579 } 2580 } 2581 } 2582 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 2583 } 2584 2585 glBindTexture(GL_TEXTURE_BUFFER, textures[5]); 2586 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2587 glBindTexture(GL_TEXTURE_BUFFER, 0); 2588 glBindBuffer(GL_TEXTURE_BUFFER, buffer); 2589 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]); 2590 glBindBuffer(GL_TEXTURE_BUFFER, 0); 2591 for (int i = 0; i < kSize; ++i) 2592 { 2593 if (!tcu::allEqual(data[i], expected_value)) 2594 { 2595 status = false; 2596 m_context.getTestContext().getLog() 2597 << tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i]) 2598 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2599 break; 2600 } 2601 } 2602 2603 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]); 2604 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2605 glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]); 2606 glBindTexture(GL_TEXTURE_1D_ARRAY, 0); 2607 for (int i = 0; i < kSize * 2; ++i) 2608 { 2609 if (!tcu::allEqual(data[i], expected_value)) 2610 { 2611 status = false; 2612 m_context.getTestContext().getLog() 2613 << tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i]) 2614 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2615 break; 2616 } 2617 } 2618 2619 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); 2620 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2621 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]); 2622 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 2623 for (int i = 0; i < kSize * kSize * 2; ++i) 2624 { 2625 if (!tcu::allEqual(data[i], expected_value)) 2626 { 2627 status = false; 2628 m_context.getTestContext().getLog() 2629 << tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i]) 2630 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2631 break; 2632 } 2633 } 2634 2635 glUseProgram(0); 2636 glDeleteProgram(program); 2637 glDeleteTextures(8, textures); 2638 glDeleteBuffers(1, &buffer); 2639 2640 return status; 2641 } 2642 2643 template <typename T> 2644 bool WriteMS(GLenum internalformat, const T& write_value, const T& expected_value) 2645 { 2646 2647 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 2648 " gl_Position = i_position;" NL "}"; 2649 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str()); 2650 const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str()); 2651 GLuint textures[2]; 2652 glGenTextures(2, textures); 2653 2654 const int kSize = 16; 2655 2656 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]); 2657 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE); 2658 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); 2659 2660 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]); 2661 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE); 2662 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0); 2663 2664 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 2665 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2666 2667 glClear(GL_COLOR_BUFFER_BIT); 2668 glUseProgram(program); 2669 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1); 2670 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4); 2671 2672 glBindVertexArray(m_vao); 2673 glViewport(0, 0, kSize, kSize); 2674 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 2675 2676 bool status = true; 2677 2678 glActiveTexture(GL_TEXTURE0); 2679 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]); 2680 glActiveTexture(GL_TEXTURE1); 2681 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]); 2682 2683 glUseProgram(val_program); 2684 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0); 2685 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1); 2686 2687 glBindVertexArray(m_vao); 2688 glViewport(0, 0, kSize, kSize); 2689 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 2690 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 2691 2692 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 2693 { 2694 status = false; 2695 m_context.getTestContext().getLog() 2696 << tcu::TestLog::Message 2697 << "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed." 2698 << tcu::TestLog::EndMessage; 2699 } 2700 2701 glActiveTexture(GL_TEXTURE0); 2702 glDeleteTextures(2, textures); 2703 glUseProgram(0); 2704 glDeleteProgram(program); 2705 glDeleteProgram(val_program); 2706 2707 return status; 2708 } 2709 2710 template <typename T> 2711 bool WriteCubeArray(GLenum internalformat, const T& write_value, const T& expected_value) 2712 { 2713 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 2714 " gl_Position = i_position;" NL "}"; 2715 const GLuint program = 2716 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str()); 2717 GLuint textures[1]; 2718 glGenTextures(1, textures); 2719 2720 const int kSize = 16; 2721 2722 std::vector<T> data(kSize * kSize * 12); 2723 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]); 2724 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 2725 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(), 2726 &data[0]); 2727 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); 2728 2729 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 2730 2731 glUseProgram(program); 2732 glBindVertexArray(m_vao); 2733 glViewport(0, 0, kSize, kSize); 2734 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 2735 2736 bool status = true; 2737 2738 std::fill(data.begin(), data.end(), T(0)); 2739 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]); 2740 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2741 glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]); 2742 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); 2743 for (int i = 0; i < kSize * kSize * 12; ++i) 2744 { 2745 if (!tcu::allEqual(data[i], expected_value)) 2746 { 2747 status = false; 2748 m_context.getTestContext().getLog() 2749 << tcu::TestLog::Message 2750 << "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i]) 2751 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage; 2752 break; 2753 } 2754 } 2755 2756 glDeleteTextures(1, textures); 2757 glUseProgram(0); 2758 glDeleteProgram(program); 2759 2760 return status; 2761 } 2762 2763 template <typename T> 2764 std::string GenFS(GLenum internalformat, const T& write_value) 2765 { 2766 std::ostringstream os; 2767 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 2768 << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) 2769 << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" 2770 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 2771 << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 2772 << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) 2773 << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" 2774 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 2775 << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 2776 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat) 2777 << ") writeonly uniform " << TypePrefix<T>() 2778 << "image2DArray g_image_2darray;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 2779 " imageStore(g_image_1d, coord.x, " 2780 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2d, coord, " << TypePrefix<T>() 2781 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>() 2782 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>() 2783 << "vec4" << write_value << ");" NL " imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4" 2784 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" 2785 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" 2786 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4" 2787 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4" 2788 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4" 2789 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4" 2790 << write_value << ");" NL " imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4" 2791 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4" 2792 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4" 2793 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" 2794 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" 2795 << write_value << ");" NL " discard;" NL "}"; 2796 return os.str(); 2797 } 2798 2799 template <typename T> 2800 std::string GenFSMS(GLenum internalformat, const T& write_value) 2801 { 2802 std::ostringstream os; 2803 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 2804 << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) 2805 << ") writeonly uniform " << TypePrefix<T>() 2806 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 2807 " imageStore(g_image_2dms, coord, 0, " 2808 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 1, " 2809 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 2, " 2810 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 3, " 2811 << TypePrefix<T>() << "vec4" << write_value 2812 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4" 2813 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>() 2814 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 2, " 2815 << TypePrefix<T>() << "vec4" << write_value 2816 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4" 2817 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>() 2818 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 1, " 2819 << TypePrefix<T>() << "vec4" << write_value 2820 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4" 2821 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>() 2822 << "vec4" << write_value << ");" NL " discard;" NL "}"; 2823 return os.str(); 2824 } 2825 2826 template <typename T> 2827 std::string GenFSMSVal(const T& expected_value) 2828 { 2829 std::ostringstream os; 2830 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>() 2831 << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>() 2832 << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 2833 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (texelFetch(g_sampler_2dms, coord, 0) != " 2834 << TypePrefix<T>() << "vec4" << expected_value 2835 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 1) != " 2836 << TypePrefix<T>() << "vec4" << expected_value 2837 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 2) != " 2838 << TypePrefix<T>() << "vec4" << expected_value 2839 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 3) != " 2840 << TypePrefix<T>() << "vec4" << expected_value 2841 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL 2842 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != " 2843 << TypePrefix<T>() << "vec4" << expected_value 2844 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL 2845 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != " 2846 << TypePrefix<T>() << "vec4" << expected_value 2847 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL 2848 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != " 2849 << TypePrefix<T>() << "vec4" << expected_value 2850 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL 2851 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != " 2852 << TypePrefix<T>() << "vec4" << expected_value 2853 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL 2854 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != " 2855 << TypePrefix<T>() << "vec4" << expected_value 2856 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL 2857 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != " 2858 << TypePrefix<T>() << "vec4" << expected_value 2859 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL 2860 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != " 2861 << TypePrefix<T>() << "vec4" << expected_value 2862 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL 2863 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != " 2864 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}"; 2865 return os.str(); 2866 } 2867 2868 template <typename T> 2869 std::string GenFSCubeArray(GLenum internalformat, const T& write_value) 2870 { 2871 std::ostringstream os; 2872 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 2873 << TypePrefix<T>() 2874 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 2875 " imageStore(g_image_cube_array, ivec3(coord, 0), " 2876 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 1), " 2877 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 2), " 2878 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 3), " 2879 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 4), " 2880 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 5), " 2881 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 6), " 2882 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 7), " 2883 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 8), " 2884 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 9), " 2885 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 10), " 2886 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 11), " 2887 << TypePrefix<T>() << "vec4" << write_value << ");" NL " discard;" NL "}"; 2888 return os.str(); 2889 } 2890}; 2891//----------------------------------------------------------------------------- 2892// 1.3.2.1 BasicAllTargetsLoadNonMS 2893//----------------------------------------------------------------------------- 2894class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase 2895{ 2896 GLuint m_vao; 2897 GLuint m_vbo; 2898 2899 virtual long Setup() 2900 { 2901 m_vao = 0; 2902 m_vbo = 0; 2903 return NO_ERROR; 2904 } 2905 2906 virtual long Run() 2907 { 2908 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 2909 2910 if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f))) 2911 return ERROR; 2912 if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000))) 2913 return ERROR; 2914 if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000))) 2915 return ERROR; 2916 2917 if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f))) 2918 return ERROR; 2919 if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000))) 2920 return ERROR; 2921 if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000))) 2922 return ERROR; 2923 2924 return NO_ERROR; 2925 } 2926 2927 virtual long Cleanup() 2928 { 2929 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 2930 glDeleteVertexArrays(1, &m_vao); 2931 glDeleteBuffers(1, &m_vbo); 2932 return NO_ERROR; 2933 } 2934 2935 template <typename T> 2936 bool Read(GLenum internalformat, const T& value, const T& expected_value) 2937 { 2938 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 2939 " gl_Position = i_position;" NL "}"; 2940 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str()); 2941 GLuint textures[7]; 2942 GLuint buffer; 2943 glGenTextures(7, textures); 2944 glGenBuffers(1, &buffer); 2945 2946 const int kSize = 16; 2947 std::vector<T> data(kSize * kSize * 2, value); 2948 2949 glBindTexture(GL_TEXTURE_1D, textures[0]); 2950 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2951 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2952 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2953 glBindTexture(GL_TEXTURE_1D, 0); 2954 2955 glBindTexture(GL_TEXTURE_2D, textures[1]); 2956 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2957 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2958 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2959 glBindTexture(GL_TEXTURE_2D, 0); 2960 2961 glBindTexture(GL_TEXTURE_3D, textures[2]); 2962 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2963 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2964 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 2965 glBindTexture(GL_TEXTURE_3D, 0); 2966 2967 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]); 2968 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2969 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2970 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 2971 glBindTexture(GL_TEXTURE_RECTANGLE, 0); 2972 2973 glBindBuffer(GL_TEXTURE_BUFFER, buffer); 2974 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW); 2975 glBindBuffer(GL_TEXTURE_BUFFER, 0); 2976 glBindTexture(GL_TEXTURE_BUFFER, textures[4]); 2977 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer); 2978 glBindTexture(GL_TEXTURE_BUFFER, 0); 2979 2980 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]); 2981 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2982 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2983 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 2984 glBindTexture(GL_TEXTURE_1D_ARRAY, 0); 2985 2986 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]); 2987 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2988 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2989 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 2990 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 2991 2992 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 2993 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 2994 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 2995 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 2996 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 2997 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 2998 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 2999 3000 glClear(GL_COLOR_BUFFER_BIT); 3001 3002 glUseProgram(program); 3003 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0); 3004 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1); 3005 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2); 3006 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3); 3007 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4); 3008 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5); 3009 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6); 3010 3011 glBindVertexArray(m_vao); 3012 glViewport(0, 0, kSize, kSize); 3013 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3014 3015 bool status = true; 3016 3017 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 3018 { 3019 status = false; 3020 } 3021 3022 std::map<std::string, GLuint> name_index_map; 3023 GLint uniforms; 3024 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms); 3025 if (uniforms != 7) 3026 { 3027 status = false; 3028 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms 3029 << " should be 7." << tcu::TestLog::EndMessage; 3030 } 3031 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index) 3032 { 3033 GLchar name[32]; 3034 glGetActiveUniformName(program, index, sizeof(name), NULL, name); 3035 name_index_map.insert(std::make_pair(std::string(name), index)); 3036 } 3037 3038 if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D))) 3039 status = false; 3040 if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D))) 3041 status = false; 3042 if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D))) 3043 status = false; 3044 if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE))) 3045 status = false; 3046 if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER))) 3047 status = false; 3048 if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY))) 3049 status = false; 3050 if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY))) 3051 status = false; 3052 3053 glUseProgram(0); 3054 glDeleteProgram(program); 3055 glDeleteTextures(7, textures); 3056 glDeleteBuffers(1, &buffer); 3057 3058 return status; 3059 } 3060 3061 template <typename T> 3062 bool ReadCube(GLenum internalformat, const T& value, const T& expected_value) 3063 { 3064 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 3065 " gl_Position = i_position;" NL "}"; 3066 const GLuint program = 3067 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str()); 3068 GLuint textures[2]; 3069 glGenTextures(2, textures); 3070 3071 const int kSize = 16; 3072 std::vector<T> data(kSize * kSize * 12, value); 3073 3074 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]); 3075 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3076 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3077 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3078 &data[0]); 3079 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3080 &data[0]); 3081 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3082 &data[0]); 3083 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3084 &data[0]); 3085 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3086 &data[0]); 3087 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3088 &data[0]); 3089 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 3090 3091 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]); 3092 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3093 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3094 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(), 3095 &data[0]); 3096 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); 3097 3098 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 3099 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 3100 3101 glClear(GL_COLOR_BUFFER_BIT); 3102 3103 glUseProgram(program); 3104 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0); 3105 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1); 3106 3107 glBindVertexArray(m_vao); 3108 glViewport(0, 0, kSize, kSize); 3109 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3110 3111 bool status = true; 3112 3113 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 3114 { 3115 status = false; 3116 } 3117 3118 std::map<std::string, GLuint> name_index_map; 3119 GLint uniforms; 3120 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms); 3121 if (uniforms != 2) 3122 { 3123 status = false; 3124 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms 3125 << " should be 2." << tcu::TestLog::EndMessage; 3126 } 3127 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index) 3128 { 3129 GLchar name[32]; 3130 glGetActiveUniformName(program, index, sizeof(name), NULL, name); 3131 name_index_map.insert(std::make_pair(std::string(name), index)); 3132 } 3133 3134 if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP))) 3135 status = false; 3136 if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY))) 3137 status = false; 3138 3139 glUseProgram(0); 3140 glDeleteProgram(program); 3141 glDeleteTextures(2, textures); 3142 3143 return status; 3144 } 3145 3146 template <typename T> 3147 std::string GenFS(GLenum internalformat, const T& expected_value) 3148 { 3149 std::ostringstream os; 3150 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 3151 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 3152 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 3153 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) 3154 << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" 3155 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 3156 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 3157 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) 3158 << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" 3159 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 3160 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 3161 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " " 3162 << TypePrefix<T>() 3163 << "vec4 v;" NL " v = imageLoad(g_image_1d, coord.x);" NL " if (v != " << TypePrefix<T>() << "vec4" 3164 << expected_value 3165 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_2d, coord);" NL " if (v != " 3166 << TypePrefix<T>() << "vec4" << expected_value 3167 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL 3168 " if (v != " 3169 << TypePrefix<T>() << "vec4" << expected_value 3170 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL 3171 " if (v != " 3172 << TypePrefix<T>() << "vec4" << expected_value 3173 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_2drect, coord);" NL " if (v != " 3174 << TypePrefix<T>() << "vec4" << expected_value 3175 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_buffer, coord.x);" NL " if (v != " 3176 << TypePrefix<T>() << "vec4" << expected_value 3177 << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL 3178 " if (v != " 3179 << TypePrefix<T>() << "vec4" << expected_value 3180 << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL 3181 " if (v != " 3182 << TypePrefix<T>() << "vec4" << expected_value 3183 << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL 3184 " if (v != " 3185 << TypePrefix<T>() << "vec4" << expected_value 3186 << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL 3187 " if (v != " 3188 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}"; 3189 return os.str(); 3190 } 3191 3192 template <typename T> 3193 std::string GenFSCube(GLenum internalformat, const T& expected_value) 3194 { 3195 std::ostringstream os; 3196 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 3197 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 3198 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 3199 << TypePrefix<T>() 3200 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 3201 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " " 3202 << TypePrefix<T>() 3203 << "vec4 v;" NL " v = imageLoad(g_image_cube, ivec3(coord, 0));" NL " if (v != " << TypePrefix<T>() 3204 << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL 3205 " v = imageLoad(g_image_cube, ivec3(coord, 1));" NL " if (v != " 3206 << TypePrefix<T>() << "vec4" << expected_value 3207 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube, ivec3(coord, 2));" NL 3208 " if (v != " 3209 << TypePrefix<T>() << "vec4" << expected_value 3210 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube, ivec3(coord, 3));" NL 3211 " if (v != " 3212 << TypePrefix<T>() << "vec4" << expected_value 3213 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube, ivec3(coord, 4));" NL 3214 " if (v != " 3215 << TypePrefix<T>() << "vec4" << expected_value 3216 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube, ivec3(coord, 5));" NL 3217 " if (v != " 3218 << TypePrefix<T>() << "vec4" << expected_value 3219 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL 3220 " if (v != " 3221 << TypePrefix<T>() << "vec4" << expected_value 3222 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL 3223 " if (v != " 3224 << TypePrefix<T>() << "vec4" << expected_value 3225 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL 3226 " if (v != " 3227 << TypePrefix<T>() << "vec4" << expected_value 3228 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL 3229 " if (v != " 3230 << TypePrefix<T>() << "vec4" << expected_value 3231 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL 3232 " if (v != " 3233 << TypePrefix<T>() << "vec4" << expected_value 3234 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL 3235 " if (v != " 3236 << TypePrefix<T>() << "vec4" << expected_value 3237 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL 3238 " if (v != " 3239 << TypePrefix<T>() << "vec4" << expected_value 3240 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL 3241 " if (v != " 3242 << TypePrefix<T>() << "vec4" << expected_value 3243 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL 3244 " if (v != " 3245 << TypePrefix<T>() << "vec4" << expected_value 3246 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL 3247 " if (v != " 3248 << TypePrefix<T>() << "vec4" << expected_value 3249 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL 3250 " if (v != " 3251 << TypePrefix<T>() << "vec4" << expected_value 3252 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL 3253 " if (v != " 3254 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}"; 3255 return os.str(); 3256 } 3257}; 3258//----------------------------------------------------------------------------- 3259// 1.3.2.2 BasicAllTargetsLoadMS 3260//----------------------------------------------------------------------------- 3261class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase 3262{ 3263 GLuint m_vao; 3264 GLuint m_vbo; 3265 3266 virtual long Setup() 3267 { 3268 m_vao = 0; 3269 m_vbo = 0; 3270 return NO_ERROR; 3271 } 3272 3273 virtual long Run() 3274 { 3275 if (!SupportedSamples(4)) 3276 return NOT_SUPPORTED; 3277 3278 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 3279 3280 if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f))) 3281 return ERROR; 3282 3283 GLint isamples; 3284 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples); 3285 if (isamples >= 4) 3286 { 3287 if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 3288 return ERROR; 3289 if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 3290 return ERROR; 3291 } 3292 3293 return NO_ERROR; 3294 } 3295 3296 virtual long Cleanup() 3297 { 3298 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 3299 glDeleteVertexArrays(1, &m_vao); 3300 glDeleteBuffers(1, &m_vbo); 3301 return NO_ERROR; 3302 } 3303 3304 template <typename T> 3305 bool ReadMS(GLenum internalformat, const T& value, const T& expected_value) 3306 { 3307 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 3308 " gl_Position = i_position;" NL "}"; 3309 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str()); 3310 GLuint textures[2]; 3311 glGenTextures(2, textures); 3312 3313 const int kSize = 16; 3314 3315 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]); 3316 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE); 3317 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); 3318 3319 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]); 3320 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE); 3321 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0); 3322 3323 GLuint fbo; 3324 glGenFramebuffers(1, &fbo); 3325 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 3326 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0); 3327 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0); 3328 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1); 3329 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; 3330 glDrawBuffers(3, draw_buffers); 3331 ClearBuffer(GL_COLOR, 0, value); 3332 ClearBuffer(GL_COLOR, 1, value); 3333 ClearBuffer(GL_COLOR, 2, value); 3334 glDeleteFramebuffers(1, &fbo); 3335 3336 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 3337 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 3338 3339 glUseProgram(program); 3340 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1); 3341 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4); 3342 3343 glClear(GL_COLOR_BUFFER_BIT); 3344 glBindVertexArray(m_vao); 3345 glViewport(0, 0, kSize, kSize); 3346 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3347 3348 bool status = true; 3349 3350 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 3351 { 3352 status = false; 3353 } 3354 3355 std::map<std::string, GLuint> name_index_map; 3356 GLint uniforms; 3357 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms); 3358 if (uniforms != 2) 3359 { 3360 status = false; 3361 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms 3362 << " should be 2." << tcu::TestLog::EndMessage; 3363 } 3364 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index) 3365 { 3366 GLchar name[32]; 3367 glGetActiveUniformName(program, index, sizeof(name), NULL, name); 3368 name_index_map.insert(std::make_pair(std::string(name), index)); 3369 } 3370 3371 if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE))) 3372 status = false; 3373 if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1, 3374 ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY))) 3375 status = false; 3376 3377 glDeleteTextures(2, textures); 3378 glUseProgram(0); 3379 glDeleteProgram(program); 3380 3381 return status; 3382 } 3383 3384 template <typename T> 3385 std::string GenFSMS(GLenum internalformat, const T& expected_value) 3386 { 3387 std::ostringstream os; 3388 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 3389 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 3390 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 3391 << TypePrefix<T>() 3392 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 3393 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (imageLoad(g_image_2dms, coord, 0) != " 3394 << TypePrefix<T>() << "vec4" << expected_value 3395 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 1) != " 3396 << TypePrefix<T>() << "vec4" << expected_value 3397 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 2) != " 3398 << TypePrefix<T>() << "vec4" << expected_value 3399 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 3) != " 3400 << TypePrefix<T>() << "vec4" << expected_value 3401 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != " 3402 << TypePrefix<T>() << "vec4" << expected_value 3403 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != " 3404 << TypePrefix<T>() << "vec4" << expected_value 3405 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != " 3406 << TypePrefix<T>() << "vec4" << expected_value 3407 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != " 3408 << TypePrefix<T>() << "vec4" << expected_value 3409 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != " 3410 << TypePrefix<T>() << "vec4" << expected_value 3411 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != " 3412 << TypePrefix<T>() << "vec4" << expected_value 3413 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != " 3414 << TypePrefix<T>() << "vec4" << expected_value 3415 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != " 3416 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}"; 3417 return os.str(); 3418 } 3419}; 3420//----------------------------------------------------------------------------- 3421// 1.3.3 BasicAllTargetsAtomic 3422//----------------------------------------------------------------------------- 3423class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase 3424{ 3425 GLuint m_vao; 3426 GLuint m_vbo; 3427 3428 virtual long Setup() 3429 { 3430 m_vao = 0; 3431 m_vbo = 0; 3432 return NO_ERROR; 3433 } 3434 3435 virtual long Run() 3436 { 3437 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 3438 3439 if (!Atomic<GLint>(GL_R32I)) 3440 return ERROR; 3441 if (!Atomic<GLuint>(GL_R32UI)) 3442 return ERROR; 3443 3444 if (!AtomicCube<GLint>(GL_R32I)) 3445 return ERROR; 3446 if (!AtomicCube<GLuint>(GL_R32UI)) 3447 return ERROR; 3448 3449 GLint isamples; 3450 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples); 3451 if (SupportedSamples(4) && isamples >= 4) 3452 { 3453 if (!AtomicMS<GLint>(GL_R32I)) 3454 return ERROR; 3455 if (!AtomicMS<GLuint>(GL_R32UI)) 3456 return ERROR; 3457 } 3458 3459 return NO_ERROR; 3460 } 3461 3462 virtual long Cleanup() 3463 { 3464 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 3465 glDeleteVertexArrays(1, &m_vao); 3466 glDeleteBuffers(1, &m_vbo); 3467 return NO_ERROR; 3468 } 3469 3470 template <typename T> 3471 bool Atomic(GLenum internalformat) 3472 { 3473 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 3474 " gl_Position = i_position;" NL "}"; 3475 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str()); 3476 GLuint textures[7]; 3477 GLuint buffer; 3478 glGenTextures(7, textures); 3479 glGenBuffers(1, &buffer); 3480 3481 const int kSize = 16; 3482 std::vector<T> data(kSize * kSize * 2); 3483 3484 glBindTexture(GL_TEXTURE_1D, textures[0]); 3485 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3486 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3487 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]); 3488 glBindTexture(GL_TEXTURE_1D, 0); 3489 3490 glBindTexture(GL_TEXTURE_2D, textures[1]); 3491 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3493 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 3494 glBindTexture(GL_TEXTURE_2D, 0); 3495 3496 glBindTexture(GL_TEXTURE_3D, textures[2]); 3497 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3498 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3499 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 3500 glBindTexture(GL_TEXTURE_3D, 0); 3501 3502 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]); 3503 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3504 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3505 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]); 3506 glBindTexture(GL_TEXTURE_RECTANGLE, 0); 3507 3508 glBindBuffer(GL_TEXTURE_BUFFER, buffer); 3509 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW); 3510 glBindBuffer(GL_TEXTURE_BUFFER, 0); 3511 glBindTexture(GL_TEXTURE_BUFFER, textures[4]); 3512 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer); 3513 glBindTexture(GL_TEXTURE_BUFFER, 0); 3514 3515 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]); 3516 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3517 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3518 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 3519 glBindTexture(GL_TEXTURE_1D_ARRAY, 0); 3520 3521 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]); 3522 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3523 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3524 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]); 3525 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 3526 3527 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 3528 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 3529 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 3530 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 3531 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 3532 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 3533 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 3534 3535 glClear(GL_COLOR_BUFFER_BIT); 3536 3537 glUseProgram(program); 3538 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0); 3539 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1); 3540 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2); 3541 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3); 3542 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4); 3543 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5); 3544 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6); 3545 3546 glBindVertexArray(m_vao); 3547 glViewport(0, 0, kSize, 1); 3548 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3549 3550 bool status = true; 3551 3552 if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1))) 3553 { 3554 status = false; 3555 } 3556 3557 glUseProgram(0); 3558 glDeleteProgram(program); 3559 glDeleteTextures(7, textures); 3560 glDeleteBuffers(1, &buffer); 3561 3562 return status; 3563 } 3564 3565 template <typename T> 3566 bool AtomicCube(GLenum internalformat) 3567 { 3568 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 3569 " gl_Position = i_position;" NL "}"; 3570 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str()); 3571 GLuint textures[2]; 3572 glGenTextures(2, textures); 3573 3574 const int kSize = 16; 3575 std::vector<T> data(kSize * kSize * 12); 3576 3577 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]); 3578 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3579 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3580 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3581 &data[0]); 3582 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3583 &data[0]); 3584 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3585 &data[0]); 3586 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3587 &data[0]); 3588 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3589 &data[0]); 3590 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), 3591 &data[0]); 3592 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 3593 3594 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]); 3595 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3596 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3597 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(), 3598 &data[0]); 3599 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); 3600 3601 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 3602 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 3603 3604 glClear(GL_COLOR_BUFFER_BIT); 3605 3606 glUseProgram(program); 3607 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0); 3608 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1); 3609 3610 glBindVertexArray(m_vao); 3611 glViewport(0, 0, kSize, kSize); 3612 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3613 3614 bool status = true; 3615 3616 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 3617 { 3618 status = false; 3619 } 3620 3621 glUseProgram(0); 3622 glDeleteProgram(program); 3623 glDeleteTextures(2, textures); 3624 3625 return status; 3626 } 3627 3628 template <typename T> 3629 bool AtomicMS(GLenum internalformat) 3630 { 3631 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 3632 " gl_Position = i_position;" NL "}"; 3633 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str()); 3634 GLuint textures[2]; 3635 glGenTextures(2, textures); 3636 3637 const int kSize = 16; 3638 3639 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]); 3640 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE); 3641 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); 3642 3643 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]); 3644 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE); 3645 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0); 3646 3647 GLuint fbo; 3648 glGenFramebuffers(1, &fbo); 3649 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 3650 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0); 3651 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0); 3652 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1); 3653 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; 3654 glDrawBuffers(3, draw_buffers); 3655 if (internalformat == GL_R32I) 3656 { 3657 const GLint value[4] = { 0, 0, 0, 0 }; 3658 glClearBufferiv(GL_COLOR, 0, value); 3659 glClearBufferiv(GL_COLOR, 1, value); 3660 glClearBufferiv(GL_COLOR, 2, value); 3661 } 3662 else 3663 { 3664 const GLuint value[4] = { 0, 0, 0, 0 }; 3665 glClearBufferuiv(GL_COLOR, 0, value); 3666 glClearBufferuiv(GL_COLOR, 1, value); 3667 glClearBufferuiv(GL_COLOR, 2, value); 3668 } 3669 glDeleteFramebuffers(1, &fbo); 3670 3671 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 3672 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 3673 3674 glUseProgram(program); 3675 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1); 3676 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4); 3677 3678 glClear(GL_COLOR_BUFFER_BIT); 3679 glBindVertexArray(m_vao); 3680 glViewport(0, 0, kSize, kSize); 3681 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3682 3683 bool status = true; 3684 3685 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 3686 { 3687 status = false; 3688 } 3689 3690 glDeleteTextures(2, textures); 3691 glUseProgram(0); 3692 glDeleteProgram(program); 3693 3694 return status; 3695 } 3696 3697 template <typename T> 3698 std::string GenFS(GLenum internalformat) 3699 { 3700 std::ostringstream os; 3701 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 3702 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 3703 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " 3704 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) 3705 << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" 3706 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 3707 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " 3708 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) 3709 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" 3710 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 3711 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 3712 " ivec2 coord = ivec2(gl_FragCoord.xy);" 3713 3714 NL " if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3715 " if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3716 " if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3717 " if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3718 " if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3719 " if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3720 " if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3721 " if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3722 " if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3723 3724 NL " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3725 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3726 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3727 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3728 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3729 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3730 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3731 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3732 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3733 3734 NL " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3735 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3736 " if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3737 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3738 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3739 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3740 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3741 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, " 3742 "1.0);" NL 3743 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3744 3745 NL " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3746 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3747 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3748 " if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3749 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3750 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3751 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3752 " if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3753 " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3754 3755 NL " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3756 " if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3757 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3758 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3759 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3760 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3761 " if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3762 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3763 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3764 3765 NL 3766 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3767 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3768 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3769 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3770 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3771 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3772 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, " 3773 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = " 3774 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), " 3775 "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3776 3777 NL " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3778 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3779 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3780 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3781 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3782 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3783 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, " 3784 "1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, " 3785 "0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) " 3786 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}"; 3787 return os.str(); 3788 } 3789 3790 template <typename T> 3791 std::string GenFSCube(GLenum internalformat) 3792 { 3793 std::ostringstream os; 3794 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 3795 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 3796 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " 3797 << TypePrefix<T>() 3798 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 3799 " ivec2 coord = ivec2(gl_FragCoord.xy);" 3800 3801 NL " if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3802 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3803 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3804 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3805 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3806 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3807 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3808 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, " 3809 "1.0);" NL 3810 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 3811 3812 NL " if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, " 3813 "1.0);" NL " if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, " 3814 "0.0, 1.0);" NL " if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color " 3815 "= vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicAnd(g_image_cube_array, " 3816 "ivec3(coord, 0), 0) != 4) o_color = " 3817 "vec4(1.0, 0.0, 0.0, 1.0);" NL 3818 " if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3819 " if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, " 3820 "1.0);" NL " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, " 3821 "0.0, 0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != " 3822 "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3823 " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, " 3824 "1.0);" NL "}"; 3825 return os.str(); 3826 } 3827 3828 template <typename T> 3829 std::string GenFSMS(GLenum internalformat) 3830 { 3831 std::ostringstream os; 3832 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout(" 3833 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 3834 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " 3835 << TypePrefix<T>() 3836 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 3837 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 3838 " if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3839 " if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3840 " if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3841 " if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3842 " if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3843 " if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3844 " if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3845 " if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3846 " if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL 3847 " if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, " 3848 "1.0);" NL " if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, " 3849 "0.0, 0.0, 1.0);" NL " if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) " 3850 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3851 " if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, " 3852 "1.0);" NL " if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, " 3853 "0.0, 0.0, 1.0);" NL " if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) " 3854 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3855 " if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, " 3856 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = " 3857 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2dms_array, " 3858 "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, " 3859 "0.0, 1.0);" NL "}"; 3860 return os.str(); 3861 } 3862}; 3863//----------------------------------------------------------------------------- 3864// LoadStoreMachine 3865//----------------------------------------------------------------------------- 3866class LoadStoreMachine : public ShaderImageLoadStoreBase 3867{ 3868 GLuint m_vao; 3869 int m_stage; 3870 3871 virtual long Setup() 3872 { 3873 glGenVertexArrays(1, &m_vao); 3874 return NO_ERROR; 3875 } 3876 3877 virtual long Cleanup() 3878 { 3879 glDisable(GL_RASTERIZER_DISCARD); 3880 glDeleteVertexArrays(1, &m_vao); 3881 return NO_ERROR; 3882 } 3883 3884 template <typename T> 3885 bool Write(GLenum internalformat, const T& write_value, const T& expected_value) 3886 { 3887 const GLenum targets[] = { GL_TEXTURE_1D, GL_TEXTURE_2D, 3888 GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE, 3889 GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY, 3890 GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY }; 3891 const int kTargets = sizeof(targets) / sizeof(targets[0]); 3892 GLuint program_store = 0; 3893 GLuint program_load = 0; 3894 if (m_stage == 0) 3895 { // VS 3896 program_store = 3897 BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL); 3898 program_load = 3899 BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL); 3900 } 3901 else if (m_stage == 1) 3902 { // TCS 3903 const char* const glsl_vs = "#version 420 core" NL "void main() {}"; 3904 const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}"; 3905 program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(), 3906 glsl_tes, NULL, NULL); 3907 program_load = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(), 3908 glsl_tes, NULL, NULL); 3909 } 3910 else if (m_stage == 2) 3911 { // TES 3912 const char* const glsl_vs = "#version 420 core" NL "void main() {}"; 3913 program_store = 3914 BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL); 3915 program_load = 3916 BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL); 3917 } 3918 else if (m_stage == 3) 3919 { // GS 3920 const char* const glsl_vs = "#version 420 core" NL "void main() {}"; 3921 program_store = 3922 BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL); 3923 program_load = 3924 BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL); 3925 } 3926 else if (m_stage == 4) 3927 { // CS 3928 { 3929 std::string source = GenStoreShader(m_stage, internalformat, write_value); 3930 const char* const src = source.c_str(); 3931 GLuint sh = glCreateShader(GL_COMPUTE_SHADER); 3932 glShaderSource(sh, 1, &src, NULL); 3933 glCompileShader(sh); 3934 program_store = glCreateProgram(); 3935 glAttachShader(program_store, sh); 3936 glLinkProgram(program_store); 3937 glDeleteShader(sh); 3938 } 3939 { 3940 std::string source = GenLoadShader(m_stage, internalformat, expected_value); 3941 const char* const src = source.c_str(); 3942 GLuint sh = glCreateShader(GL_COMPUTE_SHADER); 3943 glShaderSource(sh, 1, &src, NULL); 3944 glCompileShader(sh); 3945 program_load = glCreateProgram(); 3946 glAttachShader(program_load, sh); 3947 glLinkProgram(program_load); 3948 glDeleteShader(sh); 3949 } 3950 } 3951 GLuint textures[kTargets], texture_result; 3952 glGenTextures(kTargets, textures); 3953 glGenTextures(1, &texture_result); 3954 3955 glBindTexture(GL_TEXTURE_2D, texture_result); 3956 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3957 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3958 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1); 3959 3960 for (int i = 0; i < kTargets; ++i) 3961 { 3962 glBindTexture(targets[i], textures[i]); 3963 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3964 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3965 3966 if (targets[i] == GL_TEXTURE_1D) 3967 { 3968 glTexStorage1D(targets[i], 1, internalformat, 1); 3969 } 3970 else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE) 3971 { 3972 glTexStorage2D(targets[i], 1, internalformat, 1, 1); 3973 } 3974 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY) 3975 { 3976 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2); 3977 } 3978 else if (targets[i] == GL_TEXTURE_CUBE_MAP) 3979 { 3980 glTexStorage2D(targets[i], 1, internalformat, 1, 1); 3981 } 3982 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY) 3983 { 3984 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12); 3985 } 3986 else if (targets[i] == GL_TEXTURE_1D_ARRAY) 3987 { 3988 glTexStorage2D(targets[i], 1, internalformat, 1, 2); 3989 } 3990 } 3991 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 3992 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 3993 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 3994 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 3995 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 3996 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 3997 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 3998 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 3999 4000 glUseProgram(program_store); 4001 glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0); 4002 glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1); 4003 glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2); 4004 glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3); 4005 glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4); 4006 glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5); 4007 glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6); 4008 glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7); 4009 4010 glBindVertexArray(m_vao); 4011 if (m_stage == 1 || m_stage == 2) 4012 { // TCS or TES 4013 glPatchParameteri(GL_PATCH_VERTICES, 1); 4014 glDrawArrays(GL_PATCHES, 0, 1); 4015 glPatchParameteri(GL_PATCH_VERTICES, 3); 4016 } 4017 else if (m_stage == 4) 4018 { // CS 4019 glDispatchCompute(1, 1, 1); 4020 } 4021 else 4022 { 4023 glDrawArrays(GL_POINTS, 0, 1); 4024 } 4025 4026 bool status = true; 4027 for (int i = 0; i < kTargets; ++i) 4028 { 4029 glBindTexture(targets[i], textures[i]); 4030 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 4031 4032 if (targets[i] == GL_TEXTURE_CUBE_MAP) 4033 { 4034 for (int face = 0; face < 6; ++face) 4035 { 4036 T data; 4037 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]); 4038 if (!Equal(data, expected_value, internalformat)) 4039 { 4040 status = false; 4041 m_context.getTestContext().getLog() 4042 << tcu::TestLog::Message << "Value is: " << ToString(data) 4043 << ". Value should be: " << ToString(expected_value) 4044 << ". Format is: " << FormatEnumToString(internalformat) 4045 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage) 4046 << tcu::TestLog::EndMessage; 4047 } 4048 } 4049 } 4050 else 4051 { 4052 T data[12]; 4053 4054 for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(data); ndx++) 4055 data[ndx] = T(0); 4056 4057 glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]); 4058 4059 int count = 1; 4060 if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY) 4061 count = 2; 4062 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY) 4063 count = 12; 4064 else if (targets[i] == GL_TEXTURE_1D_ARRAY) 4065 count = 2; 4066 4067 for (int j = 0; j < count; ++j) 4068 { 4069 if (!Equal(data[j], expected_value, internalformat)) 4070 { 4071 status = false; 4072 m_context.getTestContext().getLog() 4073 << tcu::TestLog::Message << "Value is: " << ToString(data[j]) 4074 << ". Value should be: " << ToString(expected_value) 4075 << ". Format is: " << FormatEnumToString(internalformat) 4076 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage) 4077 << tcu::TestLog::EndMessage; 4078 } 4079 } 4080 } 4081 } 4082 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 4083 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 4084 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 4085 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 4086 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 4087 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 4088 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 4089 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 4090 4091 glUseProgram(program_load); 4092 glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0); 4093 glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1); 4094 glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2); 4095 glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3); 4096 glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4); 4097 glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5); 4098 glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6); 4099 glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7); 4100 4101 if (m_stage == 1 || m_stage == 2) 4102 { // TCS or TES 4103 glPatchParameteri(GL_PATCH_VERTICES, 1); 4104 glDrawArrays(GL_PATCHES, 0, 1); 4105 glPatchParameteri(GL_PATCH_VERTICES, 3); 4106 } 4107 else if (m_stage == 4) 4108 { // CS 4109 glDispatchCompute(1, 1, 1); 4110 } 4111 else 4112 { 4113 glDrawArrays(GL_POINTS, 0, 1); 4114 } 4115 { 4116 vec4 color; 4117 glBindTexture(GL_TEXTURE_2D, texture_result); 4118 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 4119 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]); 4120 if (!tcu::allEqual(color, vec4(0, 1, 0, 1))) 4121 { 4122 status = false; 4123 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color) 4124 << ". Format is: " << FormatEnumToString(internalformat) 4125 << ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage; 4126 } 4127 } 4128 glUseProgram(0); 4129 glDeleteProgram(program_store); 4130 glDeleteProgram(program_load); 4131 glDeleteTextures(kTargets, textures); 4132 glDeleteTextures(1, &texture_result); 4133 return status; 4134 } 4135 4136 template <typename T> 4137 std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value) 4138 { 4139 std::ostringstream os; 4140 os << "#version 420 core"; 4141 if (stage == 4) 4142 { // CS 4143 os << NL "#extension GL_ARB_compute_shader : require"; 4144 } 4145 os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 4146 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 4147 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) 4148 << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" 4149 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 4150 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 4151 << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) 4152 << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" 4153 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>() 4154 << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat) 4155 << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform " 4156 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value 4157 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);"; 4158 if (stage == 0) 4159 { // VS 4160 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);"; 4161 } 4162 else if (stage == 1) 4163 { // TCS 4164 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL 4165 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL 4166 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL 4167 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);"; 4168 } 4169 else if (stage == 2) 4170 { // TES 4171 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL 4172 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);"; 4173 } 4174 else if (stage == 3) 4175 { // GS 4176 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL 4177 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);"; 4178 } 4179 else if (stage == 4) 4180 { // CS 4181 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL 4182 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);"; 4183 } 4184 os << NL " imageStore(g_image_1d, coord.x, g_value);" NL " imageStore(g_image_2d, coord, g_value);" NL 4185 " imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL 4186 " imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL 4187 " imageStore(g_image_2drect, coord, g_value);" NL " for (int i = 0; i < 6; ++i) {" NL 4188 " imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL " }" NL 4189 " imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL 4190 " imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL 4191 " imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL 4192 " imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL 4193 " for (int i = 0; i < 6; ++i) {" NL 4194 " imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL " }" NL 4195 " for (int i = 0; i < 6; ++i) {" NL 4196 " imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL " }" NL "}"; 4197 return os.str(); 4198 } 4199 4200 template <typename T> 4201 std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value) 4202 { 4203 std::ostringstream os; 4204 os << "#version 420 core"; 4205 if (stage == 4) 4206 { // CS 4207 os << NL "#extension GL_ARB_compute_shader : require"; 4208 } 4209 os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 4210 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 4211 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) 4212 << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" 4213 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 4214 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " 4215 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat) 4216 << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout(" 4217 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>() 4218 << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL 4219 "uniform " 4220 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value 4221 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);"; 4222 if (stage == 0) 4223 { // VS 4224 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);"; 4225 } 4226 else if (stage == 1) 4227 { // TCS 4228 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL 4229 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL 4230 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL 4231 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);"; 4232 } 4233 else if (stage == 2) 4234 { // TES 4235 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL 4236 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);"; 4237 } 4238 else if (stage == 3) 4239 { // GS 4240 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL 4241 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);"; 4242 } 4243 else if (stage == 4) 4244 { // CS 4245 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL 4246 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);"; 4247 } 4248 os << NL " vec4 r = vec4(0, 1, 0, 1);" NL " " << TypePrefix<T>() 4249 << "vec4 v;" NL " v = imageLoad(g_image_2d, coord);" NL 4250 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL 4251 " v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL 4252 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_2drect, coord);" NL 4253 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL 4254 " v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL 4255 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_1darray, coord);" NL 4256 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL 4257 " v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL 4258 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL 4259 " v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL 4260 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " imageStore(g_image_result, coord, r);" NL "}"; 4261 return os.str(); 4262 } 4263 4264protected: 4265 long RunStage(int stage) 4266 { 4267 if (!SupportedInStage(stage, 8)) 4268 return NOT_SUPPORTED; 4269 4270 glEnable(GL_RASTERIZER_DISCARD); 4271 m_stage = stage; 4272 4273 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 4274 return ERROR; 4275 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 4276 return ERROR; 4277 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 4278 return ERROR; 4279 4280 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 4281 return ERROR; 4282 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f))) 4283 return ERROR; 4284 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 4285 return ERROR; 4286 4287 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 4288 return ERROR; 4289 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 4290 return ERROR; 4291 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 4292 return ERROR; 4293 4294 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f))) 4295 return ERROR; 4296 4297 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 4298 return ERROR; 4299 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 4300 return ERROR; 4301 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 4302 return ERROR; 4303 4304 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 4305 return ERROR; 4306 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1))) 4307 return ERROR; 4308 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 4309 return ERROR; 4310 4311 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 4312 return ERROR; 4313 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 4314 return ERROR; 4315 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 4316 return ERROR; 4317 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 4318 return ERROR; 4319 4320 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 4321 return ERROR; 4322 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 4323 return ERROR; 4324 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 4325 return ERROR; 4326 4327 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 4328 return ERROR; 4329 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1))) 4330 return ERROR; 4331 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 4332 return ERROR; 4333 4334 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f))) 4335 return ERROR; 4336 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f))) 4337 return ERROR; 4338 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 4339 return ERROR; 4340 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 4341 return ERROR; 4342 4343 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 4344 return ERROR; 4345 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f))) 4346 return ERROR; 4347 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 4348 return ERROR; 4349 4350 // 4351 { 4352 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 4353 return ERROR; 4354 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 4355 return ERROR; 4356 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 4357 return ERROR; 4358 4359 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 4360 return ERROR; 4361 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f))) 4362 return ERROR; 4363 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f))) 4364 return ERROR; 4365 } 4366 return NO_ERROR; 4367 } 4368}; 4369//----------------------------------------------------------------------------- 4370// AtomicMachine 4371//----------------------------------------------------------------------------- 4372class AtomicMachine : public ShaderImageLoadStoreBase 4373{ 4374 GLuint m_vao; 4375 4376 virtual long Setup() 4377 { 4378 glEnable(GL_RASTERIZER_DISCARD); 4379 glGenVertexArrays(1, &m_vao); 4380 return NO_ERROR; 4381 } 4382 4383 virtual long Cleanup() 4384 { 4385 glDisable(GL_RASTERIZER_DISCARD); 4386 glDeleteVertexArrays(1, &m_vao); 4387 return NO_ERROR; 4388 } 4389 4390 template <typename T> 4391 bool Atomic(int stage, GLenum internalformat) 4392 { 4393 GLuint program = 0; 4394 if (stage == 0) 4395 { // VS 4396 program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL); 4397 } 4398 else if (stage == 1) 4399 { // TCS 4400 const char* const glsl_vs = "#version 420 core" NL "void main() {}"; 4401 const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}"; 4402 program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL); 4403 } 4404 else if (stage == 2) 4405 { // TES 4406 const char* const glsl_vs = "#version 420 core" NL "void main() {}"; 4407 program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL); 4408 } 4409 else if (stage == 3) 4410 { // GS 4411 const char* const glsl_vs = "#version 420 core" NL "void main() {}"; 4412 program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL); 4413 } 4414 else if (stage == 4) 4415 { // CS 4416 std::string source = GenShader<T>(stage, internalformat); 4417 const char* const src = source.c_str(); 4418 GLuint sh = glCreateShader(GL_COMPUTE_SHADER); 4419 glShaderSource(sh, 1, &src, NULL); 4420 glCompileShader(sh); 4421 program = glCreateProgram(); 4422 glAttachShader(program, sh); 4423 glLinkProgram(program); 4424 glDeleteShader(sh); 4425 } 4426 GLuint texture_result; 4427 glGenTextures(1, &texture_result); 4428 glBindTexture(GL_TEXTURE_2D, texture_result); 4429 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4430 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4431 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1); 4432 4433 const GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP, 4434 GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY }; 4435 const int kTargets = sizeof(targets) / sizeof(targets[0]); 4436 4437 GLuint textures[kTargets]; 4438 GLuint buffer; 4439 glGenTextures(kTargets, textures); 4440 glGenBuffers(1, &buffer); 4441 4442 for (int i = 0; i < kTargets; ++i) 4443 { 4444 glBindTexture(targets[i], textures[i]); 4445 if (targets[i] != GL_TEXTURE_BUFFER) 4446 { 4447 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4448 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4449 } 4450 if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE) 4451 { 4452 glTexStorage2D(targets[i], 1, internalformat, 1, 1); 4453 } 4454 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY) 4455 { 4456 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2); 4457 } 4458 else if (targets[i] == GL_TEXTURE_CUBE_MAP) 4459 { 4460 glTexStorage2D(targets[i], 1, internalformat, 1, 1); 4461 } 4462 else if (targets[i] == GL_TEXTURE_BUFFER) 4463 { 4464 glBindBuffer(GL_TEXTURE_BUFFER, buffer); 4465 glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW); 4466 glBindBuffer(GL_TEXTURE_BUFFER, 0); 4467 glTexBuffer(targets[i], internalformat, buffer); 4468 } 4469 else if (targets[i] == GL_TEXTURE_1D_ARRAY) 4470 { 4471 glTexStorage2D(targets[i], 1, internalformat, 1, 2); 4472 } 4473 } 4474 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 4475 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 4476 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 4477 glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 4478 glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 4479 glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); 4480 glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 4481 glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); 4482 4483 glUseProgram(program); 4484 glUniform1i(glGetUniformLocation(program, "g_image_result"), 0); 4485 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1); 4486 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2); 4487 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3); 4488 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4); 4489 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5); 4490 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6); 4491 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7); 4492 4493 glBindVertexArray(m_vao); 4494 if (stage == 1 || stage == 2) 4495 { // TCS or TES 4496 glPatchParameteri(GL_PATCH_VERTICES, 1); 4497 glDrawArrays(GL_PATCHES, 0, 1); 4498 glPatchParameteri(GL_PATCH_VERTICES, 3); 4499 } 4500 else if (stage == 4) 4501 { // CS 4502 glDispatchCompute(1, 1, 1); 4503 } 4504 else 4505 { 4506 glDrawArrays(GL_POINTS, 0, 1); 4507 } 4508 4509 bool status = true; 4510 { 4511 vec4 color; 4512 glBindTexture(GL_TEXTURE_2D, texture_result); 4513 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 4514 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]); 4515 if (!tcu::allEqual(color, vec4(0, 1, 0, 1))) 4516 { 4517 status = false; 4518 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color) 4519 << ". Format is: " << FormatEnumToString(internalformat) 4520 << ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage; 4521 } 4522 } 4523 glUseProgram(0); 4524 glDeleteProgram(program); 4525 glDeleteTextures(7, textures); 4526 glDeleteTextures(1, &texture_result); 4527 glDeleteBuffers(1, &buffer); 4528 return status; 4529 } 4530 4531 template <typename T> 4532 std::string GenShader(int stage, GLenum internalformat) 4533 { 4534 std::ostringstream os; 4535 os << "#version 420 core"; 4536 if (stage == 4) 4537 { // CS 4538 os << NL "#extension GL_ARB_compute_shader : require"; 4539 } 4540 os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 4541 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " 4542 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) 4543 << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" 4544 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 4545 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " 4546 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) 4547 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" 4548 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>() 4549 << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL 4550 "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);"; 4551 if (stage == 0) 4552 { // VS 4553 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_value[0]);"; 4554 } 4555 else if (stage == 1) 4556 { // TCS 4557 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL 4558 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL 4559 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL 4560 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);"; 4561 } 4562 else if (stage == 2) 4563 { // TES 4564 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL 4565 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);"; 4566 } 4567 else if (stage == 3) 4568 { // GS 4569 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL 4570 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);"; 4571 } 4572 else if (stage == 4) 4573 { // CS 4574 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL 4575 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);"; 4576 } 4577 os << NL 4578 " vec4 o_color = vec4(0, 1, 0, 1);" NL " imageAtomicExchange(g_image_2d, coord, 0);" NL 4579 " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4580 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4581 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4582 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4583 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4584 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4585 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4586 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4587 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4588 4589 NL " imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL 4590 " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4591 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4592 " if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4593 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4594 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4595 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4596 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4597 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4598 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4599 4600 NL " imageAtomicExchange(g_image_2drect, coord, 0);" NL 4601 " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4602 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4603 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4604 " if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4605 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4606 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4607 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4608 " if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, " 4609 "1.0);" NL " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4610 4611 NL " imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL " if (imageAtomicAdd(g_image_cube, " 4612 "ivec3(coord, 0), g_value[2]) != 0) " 4613 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4614 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4615 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4616 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4617 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4618 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4619 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4620 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, " 4621 "0.0, 1.0);" NL 4622 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4623 4624 NL " imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL 4625 " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4626 " if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4627 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4628 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4629 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4630 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4631 " if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, " 4632 "1.0);" NL 4633 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4634 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4635 4636 NL " imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL 4637 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4638 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4639 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, " 4640 "1.0);" NL 4641 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4642 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4643 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4644 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, " 4645 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, " 4646 "0.0, 0.0, 1.0);" NL 4647 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4648 4649 NL " imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL 4650 " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4651 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4652 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4653 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4654 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4655 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, " 4656 "1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, " 4657 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) " 4658 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 4659 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" 4660 4661 NL " imageStore(g_image_result, coord, o_color);" NL "}"; 4662 return os.str(); 4663 } 4664 4665protected: 4666 long RunStage(int stage) 4667 { 4668 if (!SupportedInStage(stage, 8)) 4669 return NOT_SUPPORTED; 4670 if (!Atomic<GLint>(stage, GL_R32I)) 4671 return ERROR; 4672 if (!Atomic<GLuint>(stage, GL_R32UI)) 4673 return ERROR; 4674 return NO_ERROR; 4675 } 4676}; 4677//----------------------------------------------------------------------------- 4678// 1.3.4 BasicAllTargetsLoadStoreVS 4679//----------------------------------------------------------------------------- 4680class BasicAllTargetsLoadStoreVS : public LoadStoreMachine 4681{ 4682 virtual long Run() 4683 { 4684 return RunStage(0); 4685 } 4686}; 4687//----------------------------------------------------------------------------- 4688// 1.3.5 BasicAllTargetsLoadStoreTCS 4689//----------------------------------------------------------------------------- 4690class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine 4691{ 4692 virtual long Run() 4693 { 4694 return RunStage(1); 4695 } 4696}; 4697//----------------------------------------------------------------------------- 4698// 1.3.6 BasicAllTargetsLoadStoreTES 4699//----------------------------------------------------------------------------- 4700class BasicAllTargetsLoadStoreTES : public LoadStoreMachine 4701{ 4702 virtual long Run() 4703 { 4704 return RunStage(2); 4705 } 4706}; 4707//----------------------------------------------------------------------------- 4708// 1.3.7 BasicAllTargetsLoadStoreGS 4709//----------------------------------------------------------------------------- 4710class BasicAllTargetsLoadStoreGS : public LoadStoreMachine 4711{ 4712 virtual long Run() 4713 { 4714 return RunStage(3); 4715 } 4716}; 4717//----------------------------------------------------------------------------- 4718// 1.3.8 BasicAllTargetsLoadStoreCS 4719//----------------------------------------------------------------------------- 4720class BasicAllTargetsLoadStoreCS : public LoadStoreMachine 4721{ 4722 virtual long Run() 4723 { 4724 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) 4725 { 4726 m_context.getTestContext().getLog() 4727 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test" 4728 << tcu::TestLog::EndMessage; 4729 return NO_ERROR; 4730 } 4731 4732 return RunStage(4); 4733 } 4734}; 4735//----------------------------------------------------------------------------- 4736// 1.3.9 BasicAllTargetsAtomicVS 4737//----------------------------------------------------------------------------- 4738class BasicAllTargetsAtomicVS : public AtomicMachine 4739{ 4740 virtual long Run() 4741 { 4742 return RunStage(0); 4743 } 4744}; 4745//----------------------------------------------------------------------------- 4746// 1.3.10 BasicAllTargetsAtomicTCS 4747//----------------------------------------------------------------------------- 4748class BasicAllTargetsAtomicTCS : public AtomicMachine 4749{ 4750 virtual long Run() 4751 { 4752 return RunStage(1); 4753 } 4754}; 4755//----------------------------------------------------------------------------- 4756// 1.3.11 BasicAllTargetsAtomicTES 4757//----------------------------------------------------------------------------- 4758class BasicAllTargetsAtomicTES : public AtomicMachine 4759{ 4760 virtual long Run() 4761 { 4762 return RunStage(2); 4763 } 4764}; 4765//----------------------------------------------------------------------------- 4766// 1.3.12 BasicAllTargetsAtomicGS 4767//----------------------------------------------------------------------------- 4768class BasicAllTargetsAtomicGS : public AtomicMachine 4769{ 4770 virtual long Run() 4771 { 4772 return RunStage(3); 4773 } 4774}; 4775//----------------------------------------------------------------------------- 4776// 1.3.13 BasicAllTargetsAtomicCS 4777//----------------------------------------------------------------------------- 4778class BasicAllTargetsAtomicCS : public AtomicMachine 4779{ 4780 virtual long Run() 4781 { 4782 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) 4783 { 4784 m_context.getTestContext().getLog() 4785 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test" 4786 << tcu::TestLog::EndMessage; 4787 return NO_ERROR; 4788 } 4789 4790 return RunStage(4); 4791 } 4792}; 4793//----------------------------------------------------------------------------- 4794// 1.4.1 BasicGLSLMisc 4795//----------------------------------------------------------------------------- 4796class BasicGLSLMisc : public ShaderImageLoadStoreBase 4797{ 4798 GLuint m_texture; 4799 GLuint m_program; 4800 GLuint m_vao, m_vbo; 4801 4802 virtual long Setup() 4803 { 4804 m_texture = 0; 4805 m_program = 0; 4806 m_vao = m_vbo = 0; 4807 return NO_ERROR; 4808 } 4809 4810 virtual long Run() 4811 { 4812 const int kSize = 32; 4813 std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f)); 4814 4815 glGenTextures(1, &m_texture); 4816 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 4817 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 4818 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]); 4819 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 4820 4821 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 4822 " gl_Position = i_position;" NL "}"; 4823 const char* src_fs = 4824 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 4825 "layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL 4826 "layout(rgba32f) volatile uniform image2D g_image_layer1;" NL 4827 "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 4828 " imageStore(g_image_layer0, coord, vec4(1.0));" NL " memoryBarrier();" NL 4829 " imageStore(g_image_layer0, coord, vec4(2.0));" NL " memoryBarrier();" NL 4830 " imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL " memoryBarrier();" NL 4831 " o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}"; 4832 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs); 4833 4834 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 4835 4836 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4837 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F); 4838 4839 glClear(GL_COLOR_BUFFER_BIT); 4840 glViewport(0, 0, kSize, kSize); 4841 4842 glUseProgram(m_program); 4843 glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0); 4844 glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1); 4845 4846 glBindVertexArray(m_vao); 4847 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 4848 4849 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1))) 4850 { 4851 return ERROR; 4852 } 4853 return NO_ERROR; 4854 } 4855 4856 virtual long Cleanup() 4857 { 4858 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 4859 glDeleteTextures(1, &m_texture); 4860 glDeleteVertexArrays(1, &m_vao); 4861 glDeleteBuffers(1, &m_vbo); 4862 glUseProgram(0); 4863 glDeleteProgram(m_program); 4864 return NO_ERROR; 4865 } 4866}; 4867//----------------------------------------------------------------------------- 4868// 1.4.2 BasicGLSLEarlyFragTests 4869//----------------------------------------------------------------------------- 4870class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase 4871{ 4872 GLuint m_texture[2]; 4873 GLuint m_program[2]; 4874 GLuint m_vao, m_vbo; 4875 4876 virtual long Setup() 4877 { 4878 m_texture[0] = m_texture[1] = 0; 4879 m_program[0] = m_program[1] = 0; 4880 m_vao = m_vbo = 0; 4881 return NO_ERROR; 4882 } 4883 4884 virtual long Run() 4885 { 4886 int ds = m_context.getRenderContext().getRenderTarget().getDepthBits(); 4887 4888 const int kSize = 32; 4889 std::vector<vec4> data(kSize * kSize); 4890 4891 glGenTextures(2, m_texture); 4892 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 4893 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 4894 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]); 4895 glBindTexture(GL_TEXTURE_2D, 0); 4896 4897 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 4898 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 4899 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]); 4900 glBindTexture(GL_TEXTURE_2D, 0); 4901 4902 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 4903 " gl_Position = i_position;" NL "}"; 4904 const char* glsl_early_frag_tests_fs = 4905 "#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL 4906 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL 4907 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL 4908 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}"; 4909 const char* glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 4910 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL 4911 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL 4912 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}"; 4913 m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs); 4914 m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 4915 4916 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 4917 4918 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4919 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4920 4921 glViewport(0, 0, kSize, kSize); 4922 glBindVertexArray(m_vao); 4923 4924 glEnable(GL_DEPTH_TEST); 4925 glClearColor(0.0, 1.0f, 0.0, 1.0f); 4926 glClearDepthf(0.0f); 4927 4928 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 4929 glUseProgram(m_program[0]); 4930 glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0); 4931 4932 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 4933 4934 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 4935 glUseProgram(m_program[1]); 4936 glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1); 4937 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 4938 4939 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 4940 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 4941 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]); 4942 for (int i = 0; i < kSize * kSize; ++i) 4943 { 4944 if (IsEqual(data[i], vec4(1.0f)) && ds != 0) 4945 return ERROR; 4946 } 4947 4948 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 4949 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 4950 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]); 4951 for (int i = 0; i < kSize * kSize; ++i) 4952 { 4953 if (!IsEqual(data[i], vec4(1.0f)) && ds != 0) 4954 return ERROR; 4955 } 4956 4957 return NO_ERROR; 4958 } 4959 4960 virtual long Cleanup() 4961 { 4962 glDisable(GL_DEPTH_TEST); 4963 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 4964 glClearDepthf(1.0f); 4965 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 4966 glDeleteTextures(2, m_texture); 4967 glDeleteVertexArrays(1, &m_vao); 4968 glDeleteBuffers(1, &m_vbo); 4969 glUseProgram(0); 4970 glDeleteProgram(m_program[0]); 4971 glDeleteProgram(m_program[1]); 4972 return NO_ERROR; 4973 } 4974}; 4975//----------------------------------------------------------------------------- 4976// 1.4.3 BasicGLSLConst 4977//----------------------------------------------------------------------------- 4978class BasicGLSLConst : public ShaderImageLoadStoreBase 4979{ 4980 GLuint m_program; 4981 GLuint m_vao, m_vbo; 4982 4983 virtual long Setup() 4984 { 4985 m_program = 0; 4986 m_vao = m_vbo = 0; 4987 return NO_ERROR; 4988 } 4989 4990 virtual long Run() 4991 { 4992 bool isAtLeast44Context = 4993 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4)); 4994 4995 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 4996 " gl_Position = i_position;" NL "}"; 4997 std::ostringstream src_fs; 4998 src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core"; 4999 src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL 5000 "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL 5001 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL 5002 "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL 5003 "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL 5004 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL 5005 " if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);"; 5006 if (isAtLeast44Context) 5007 src_fs << NL " if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = " 5008 "vec4(0.2, 0.0, 0.0, 0.2);"; 5009 else 5010 src_fs << NL " if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) " 5011 "o_color = vec4(0.2, 0.0, 0.0, 0.2);"; 5012 src_fs << NL 5013 " if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL 5014 " if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL 5015 " if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, " 5016 "0.5);" NL " if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, " 5017 "0.0, 0.0, 0.6);" NL 5018 " if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL 5019 " if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL 5020 " if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}"; 5021 5022 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str()); 5023 glUseProgram(m_program); 5024 5025 GLint i; 5026 glGetIntegerv(GL_MAX_IMAGE_UNITS, &i); 5027 glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i); 5028 5029 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i); 5030 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i); 5031 5032 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i); 5033 glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i); 5034 5035 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i); 5036 glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i); 5037 5038 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i); 5039 glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i); 5040 5041 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i); 5042 glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i); 5043 5044 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i); 5045 glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i); 5046 5047 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i); 5048 glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i); 5049 5050 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i); 5051 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i); 5052 5053 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 5054 5055 glClear(GL_COLOR_BUFFER_BIT); 5056 glBindVertexArray(m_vao); 5057 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5058 5059 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 5060 { 5061 return ERROR; 5062 } 5063 return NO_ERROR; 5064 } 5065 5066 virtual long Cleanup() 5067 { 5068 glDeleteVertexArrays(1, &m_vao); 5069 glDeleteBuffers(1, &m_vbo); 5070 glUseProgram(0); 5071 glDeleteProgram(m_program); 5072 return NO_ERROR; 5073 } 5074}; 5075//----------------------------------------------------------------------------- 5076// 2.1.1 AdvancedSyncImageAccess 5077//----------------------------------------------------------------------------- 5078class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase 5079{ 5080 GLuint m_buffer; 5081 GLuint m_buffer_tex; 5082 GLuint m_store_program; 5083 GLuint m_draw_program; 5084 GLuint m_attribless_vao; 5085 5086 virtual long Setup() 5087 { 5088 m_buffer = 0; 5089 m_buffer_tex = 0; 5090 m_store_program = 0; 5091 m_draw_program = 0; 5092 m_attribless_vao = 0; 5093 return NO_ERROR; 5094 } 5095 5096 virtual long Run() 5097 { 5098 if (!SupportedInVS(1)) 5099 return NOT_SUPPORTED; 5100 const char* const glsl_store_vs = 5101 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL 5102 " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL 5103 " imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}"; 5104 const char* const glsl_draw_vs = 5105 "#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL 5106 "uniform samplerBuffer g_sampler;" NL "void main() {" NL " vec4 pi = imageLoad(g_image, gl_VertexID);" NL 5107 " vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL 5108 " 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 5109 " gl_Position = pi;" NL "}"; 5110 const char* const glsl_draw_fs = 5111 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL 5112 " o_color = vs_color;" NL "}"; 5113 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL); 5114 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs); 5115 5116 glGenVertexArrays(1, &m_attribless_vao); 5117 glBindVertexArray(m_attribless_vao); 5118 5119 glGenBuffers(1, &m_buffer); 5120 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5121 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW); 5122 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5123 5124 glGenTextures(1, &m_buffer_tex); 5125 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex); 5126 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer); 5127 5128 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F); 5129 5130 glEnable(GL_RASTERIZER_DISCARD); 5131 glUseProgram(m_store_program); 5132 glDrawArrays(GL_POINTS, 0, 4); 5133 5134 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT); 5135 5136 glDisable(GL_RASTERIZER_DISCARD); 5137 glClear(GL_COLOR_BUFFER_BIT); 5138 glUseProgram(m_draw_program); 5139 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5140 5141 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 5142 { 5143 return ERROR; 5144 } 5145 return NO_ERROR; 5146 } 5147 5148 virtual long Cleanup() 5149 { 5150 glUseProgram(0); 5151 glDeleteBuffers(1, &m_buffer); 5152 glDeleteTextures(1, &m_buffer_tex); 5153 glDeleteProgram(m_store_program); 5154 glDeleteProgram(m_draw_program); 5155 glDeleteVertexArrays(1, &m_attribless_vao); 5156 return NO_ERROR; 5157 } 5158}; 5159//----------------------------------------------------------------------------- 5160// 2.1.2 AdvancedSyncVertexArray 5161//----------------------------------------------------------------------------- 5162class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase 5163{ 5164 GLuint m_position_buffer; 5165 GLuint m_color_buffer; 5166 GLuint m_element_buffer; 5167 GLuint m_position_buffer_tex; 5168 GLuint m_color_buffer_tex; 5169 GLuint m_element_buffer_tex; 5170 GLuint m_store_program; 5171 GLuint m_draw_program; 5172 GLuint m_attribless_vao; 5173 GLuint m_draw_vao; 5174 5175 virtual long Setup() 5176 { 5177 m_position_buffer = 0; 5178 m_color_buffer = 0; 5179 m_element_buffer = 0; 5180 m_position_buffer_tex = 0; 5181 m_color_buffer_tex = 0; 5182 m_element_buffer_tex = 0; 5183 m_store_program = 0; 5184 m_draw_program = 0; 5185 m_attribless_vao = 0; 5186 m_draw_vao = 0; 5187 return NO_ERROR; 5188 } 5189 5190 virtual long Run() 5191 { 5192 if (!SupportedInVS(3)) 5193 return NOT_SUPPORTED; 5194 const char* const glsl_store_vs = 5195 "#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL 5196 "layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL 5197 "layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL 5198 "void main() {" NL " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL 5199 " imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL 5200 " imageStore(g_color_buffer, gl_VertexID, g_color);" NL 5201 " imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}"; 5202 const char* const glsl_draw_vs = 5203 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 5204 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL 5205 " gl_Position = i_position;" NL " vs_color = i_color;" NL "}"; 5206 const char* const glsl_draw_fs = 5207 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL 5208 " o_color = vs_color;" NL "}"; 5209 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL); 5210 glUseProgram(m_store_program); 5211 glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0); 5212 glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1); 5213 glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2); 5214 glUseProgram(0); 5215 5216 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs); 5217 5218 glGenBuffers(1, &m_position_buffer); 5219 glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer); 5220 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW); 5221 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5222 5223 glGenBuffers(1, &m_color_buffer); 5224 glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer); 5225 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW); 5226 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5227 5228 glGenBuffers(1, &m_element_buffer); 5229 glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer); 5230 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW); 5231 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5232 5233 glGenTextures(1, &m_position_buffer_tex); 5234 glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex); 5235 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer); 5236 glBindTexture(GL_TEXTURE_BUFFER, 0); 5237 5238 glGenTextures(1, &m_color_buffer_tex); 5239 glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex); 5240 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer); 5241 glBindTexture(GL_TEXTURE_BUFFER, 0); 5242 5243 glGenTextures(1, &m_element_buffer_tex); 5244 glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex); 5245 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer); 5246 glBindTexture(GL_TEXTURE_BUFFER, 0); 5247 5248 glGenVertexArrays(1, &m_attribless_vao); 5249 5250 glGenVertexArrays(1, &m_draw_vao); 5251 glBindVertexArray(m_draw_vao); 5252 glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer); 5253 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); 5254 glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer); 5255 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); 5256 glBindBuffer(GL_ARRAY_BUFFER, 0); 5257 glEnableVertexAttribArray(0); 5258 glEnableVertexAttribArray(1); 5259 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer); 5260 glBindVertexArray(0); 5261 5262 glEnable(GL_RASTERIZER_DISCARD); 5263 glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F); 5264 glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 5265 glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI); 5266 glUseProgram(m_store_program); 5267 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f); 5268 glBindVertexArray(m_attribless_vao); 5269 glDrawArrays(GL_POINTS, 0, 4); 5270 5271 glDisable(GL_RASTERIZER_DISCARD); 5272 glClear(GL_COLOR_BUFFER_BIT); 5273 glUseProgram(m_draw_program); 5274 glBindVertexArray(m_draw_vao); 5275 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT); 5276 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0); 5277 5278 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 5279 { 5280 return ERROR; 5281 } 5282 5283 glEnable(GL_RASTERIZER_DISCARD); 5284 glUseProgram(m_store_program); 5285 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f); 5286 glBindVertexArray(m_attribless_vao); 5287 glDrawArrays(GL_POINTS, 0, 4); 5288 5289 glDisable(GL_RASTERIZER_DISCARD); 5290 glClear(GL_COLOR_BUFFER_BIT); 5291 glUseProgram(m_draw_program); 5292 glBindVertexArray(m_draw_vao); 5293 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT); 5294 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0); 5295 5296 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1))) 5297 { 5298 return ERROR; 5299 } 5300 return NO_ERROR; 5301 } 5302 5303 virtual long Cleanup() 5304 { 5305 glDisable(GL_RASTERIZER_DISCARD); 5306 glUseProgram(0); 5307 glDeleteBuffers(1, &m_position_buffer); 5308 glDeleteBuffers(1, &m_color_buffer); 5309 glDeleteBuffers(1, &m_element_buffer); 5310 glDeleteTextures(1, &m_position_buffer_tex); 5311 glDeleteTextures(1, &m_color_buffer_tex); 5312 glDeleteTextures(1, &m_element_buffer_tex); 5313 glDeleteProgram(m_store_program); 5314 glDeleteProgram(m_draw_program); 5315 glDeleteVertexArrays(1, &m_attribless_vao); 5316 glDeleteVertexArrays(1, &m_draw_vao); 5317 return NO_ERROR; 5318 } 5319}; 5320 5321//----------------------------------------------------------------------------- 5322// 2.1.4 AdvancedSyncDrawIndirect 5323//----------------------------------------------------------------------------- 5324class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase 5325{ 5326 GLuint m_draw_command_buffer; 5327 GLuint m_draw_command_buffer_tex; 5328 GLuint m_store_program; 5329 GLuint m_draw_program; 5330 GLuint m_attribless_vao; 5331 GLuint m_draw_vao; 5332 GLuint m_draw_vbo; 5333 5334 virtual long Setup() 5335 { 5336 m_draw_command_buffer = 0; 5337 m_draw_command_buffer_tex = 0; 5338 m_store_program = 0; 5339 m_draw_program = 0; 5340 m_attribless_vao = 0; 5341 m_draw_vao = 0; 5342 m_draw_vbo = 0; 5343 return NO_ERROR; 5344 } 5345 5346 virtual long Run() 5347 { 5348 if (!SupportedInVS(1)) 5349 return NOT_SUPPORTED; 5350 const char* const glsl_store_vs = 5351 "#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL 5352 " imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}"; 5353 const char* const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 5354 "void main() {" NL " gl_Position = i_position;" NL "}"; 5355 const char* const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 5356 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}"; 5357 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL); 5358 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs); 5359 5360 glGenBuffers(1, &m_draw_command_buffer); 5361 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer); 5362 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW); 5363 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); 5364 5365 glGenTextures(1, &m_draw_command_buffer_tex); 5366 glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex); 5367 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer); 5368 glBindTexture(GL_TEXTURE_BUFFER, 0); 5369 5370 glGenVertexArrays(1, &m_attribless_vao); 5371 CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL); 5372 5373 glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); 5374 5375 glEnable(GL_RASTERIZER_DISCARD); 5376 glUseProgram(m_store_program); 5377 glBindVertexArray(m_attribless_vao); 5378 glDrawArrays(GL_POINTS, 0, 1); 5379 5380 glDisable(GL_RASTERIZER_DISCARD); 5381 glClear(GL_COLOR_BUFFER_BIT); 5382 glUseProgram(m_draw_program); 5383 glBindVertexArray(m_draw_vao); 5384 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer); 5385 glMemoryBarrier(GL_COMMAND_BARRIER_BIT); 5386 glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0); 5387 5388 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 5389 { 5390 return ERROR; 5391 } 5392 return NO_ERROR; 5393 } 5394 5395 virtual long Cleanup() 5396 { 5397 glUseProgram(0); 5398 glDeleteBuffers(1, &m_draw_command_buffer); 5399 glDeleteTextures(1, &m_draw_command_buffer_tex); 5400 glDeleteProgram(m_store_program); 5401 glDeleteProgram(m_draw_program); 5402 glDeleteVertexArrays(1, &m_attribless_vao); 5403 glDeleteVertexArrays(1, &m_draw_vao); 5404 glDeleteBuffers(1, &m_draw_vbo); 5405 return NO_ERROR; 5406 } 5407}; 5408//----------------------------------------------------------------------------- 5409// 2.1.5 AdvancedSyncTextureUpdate 5410//----------------------------------------------------------------------------- 5411class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase 5412{ 5413 GLuint m_texture; 5414 GLuint m_store_program; 5415 GLuint m_draw_program; 5416 GLuint m_vao; 5417 GLuint m_vbo; 5418 GLuint m_pbo; 5419 5420 virtual long Setup() 5421 { 5422 m_texture = 0; 5423 m_store_program = 0; 5424 m_draw_program = 0; 5425 m_vao = 0; 5426 m_vbo = 0; 5427 m_pbo = 0; 5428 return NO_ERROR; 5429 } 5430 5431 virtual long Run() 5432 { 5433 const char* const glsl_vs = 5434 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL 5435 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}"; 5436 const char* const glsl_store_fs = 5437 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL 5438 " imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL " discard;" NL "}"; 5439 const char* const glsl_draw_fs = 5440 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL 5441 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}"; 5442 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs); 5443 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs); 5444 5445 std::vector<vec4> data(16 * 16, vec4(1.0f)); 5446 glGenBuffers(1, &m_pbo); 5447 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo); 5448 glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ); 5449 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 5450 5451 glGenTextures(1, &m_texture); 5452 glBindTexture(GL_TEXTURE_2D, m_texture); 5453 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 5454 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL); 5455 glBindTexture(GL_TEXTURE_2D, 0); 5456 5457 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 5458 5459 glViewport(0, 0, 16, 16); 5460 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 5461 glUseProgram(m_store_program); 5462 glBindVertexArray(m_vao); 5463 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5464 5465 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo); 5466 glBindTexture(GL_TEXTURE_2D, m_texture); 5467 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 5468 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0); 5469 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 5470 5471 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 5472 glClear(GL_COLOR_BUFFER_BIT); 5473 glUseProgram(m_draw_program); 5474 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5475 5476 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1))) 5477 { 5478 return ERROR; 5479 } 5480 return NO_ERROR; 5481 } 5482 5483 virtual long Cleanup() 5484 { 5485 glUseProgram(0); 5486 glDeleteBuffers(1, &m_vbo); 5487 glDeleteBuffers(1, &m_pbo); 5488 glDeleteTextures(1, &m_texture); 5489 glDeleteProgram(m_store_program); 5490 glDeleteProgram(m_draw_program); 5491 glDeleteVertexArrays(1, &m_vao); 5492 return NO_ERROR; 5493 } 5494}; 5495//----------------------------------------------------------------------------- 5496// 2.1.6 AdvancedSyncImageAccess2 5497//----------------------------------------------------------------------------- 5498class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase 5499{ 5500 GLuint m_texture; 5501 GLuint m_store_program; 5502 GLuint m_draw_program; 5503 GLuint m_vao; 5504 GLuint m_vbo; 5505 5506 virtual long Setup() 5507 { 5508 m_texture = 0; 5509 m_store_program = 0; 5510 m_draw_program = 0; 5511 m_vao = 0; 5512 m_vbo = 0; 5513 return NO_ERROR; 5514 } 5515 5516 virtual long Run() 5517 { 5518 const char* const glsl_vs = 5519 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL 5520 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}"; 5521 const char* const glsl_store_fs = 5522 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL 5523 " imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL " discard;" NL "}"; 5524 const char* const glsl_draw_fs = 5525 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL 5526 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}"; 5527 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs); 5528 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs); 5529 5530 int width = getWindowWidth(); 5531 int height = getWindowHeight(); 5532 scaleDimensionsToMemory(width, height, 1, 1, 16, 16); 5533 5534 glGenTextures(1, &m_texture); 5535 glBindTexture(GL_TEXTURE_2D, m_texture); 5536 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 5537 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL); 5538 glBindTexture(GL_TEXTURE_2D, 0); 5539 5540 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 5541 5542 glViewport(0, 0, width, height); 5543 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 5544 glUseProgram(m_store_program); 5545 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f); 5546 glBindVertexArray(m_vao); 5547 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5548 5549 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 5550 5551 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f); 5552 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5553 5554 glClear(GL_COLOR_BUFFER_BIT); 5555 glBindTexture(GL_TEXTURE_2D, m_texture); 5556 glUseProgram(m_draw_program); 5557 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5558 5559 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1))) 5560 { 5561 return ERROR; 5562 } 5563 return NO_ERROR; 5564 } 5565 5566 virtual long Cleanup() 5567 { 5568 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 5569 glUseProgram(0); 5570 glDeleteBuffers(1, &m_vbo); 5571 glDeleteTextures(1, &m_texture); 5572 glDeleteProgram(m_store_program); 5573 glDeleteProgram(m_draw_program); 5574 glDeleteVertexArrays(1, &m_vao); 5575 return NO_ERROR; 5576 } 5577}; 5578//----------------------------------------------------------------------------- 5579// 2.1.7 AdvancedSyncBufferUpdate 5580//----------------------------------------------------------------------------- 5581class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase 5582{ 5583 GLuint m_buffer; 5584 GLuint m_buffer_tex; 5585 GLuint m_store_program; 5586 GLuint m_attribless_vao; 5587 5588 virtual long Setup() 5589 { 5590 m_buffer = 0; 5591 m_buffer_tex = 0; 5592 m_store_program = 0; 5593 m_attribless_vao = 0; 5594 return NO_ERROR; 5595 } 5596 5597 virtual long Run() 5598 { 5599 if (!SupportedInVS(1)) 5600 return NOT_SUPPORTED; 5601 const char* const glsl_store_vs = 5602 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL 5603 " imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}"; 5604 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL); 5605 5606 glGenVertexArrays(1, &m_attribless_vao); 5607 glBindVertexArray(m_attribless_vao); 5608 5609 glGenBuffers(1, &m_buffer); 5610 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5611 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW); 5612 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5613 5614 glGenTextures(1, &m_buffer_tex); 5615 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex); 5616 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer); 5617 5618 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 5619 5620 glEnable(GL_RASTERIZER_DISCARD); 5621 glUseProgram(m_store_program); 5622 glDrawArrays(GL_POINTS, 0, 1000); 5623 5624 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 5625 5626 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5627 vec4* ptr = 5628 reinterpret_cast<vec4*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT)); 5629 for (int i = 0; i < 1000; ++i) 5630 { 5631 if (!IsEqual(ptr[i], vec4(static_cast<float>(i)))) 5632 { 5633 m_context.getTestContext().getLog() 5634 << tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage; 5635 return ERROR; 5636 } 5637 } 5638 return NO_ERROR; 5639 } 5640 5641 virtual long Cleanup() 5642 { 5643 glDisable(GL_RASTERIZER_DISCARD); 5644 glUseProgram(0); 5645 glDeleteBuffers(1, &m_buffer); 5646 glDeleteTextures(1, &m_buffer_tex); 5647 glDeleteProgram(m_store_program); 5648 glDeleteVertexArrays(1, &m_attribless_vao); 5649 return NO_ERROR; 5650 } 5651}; 5652//----------------------------------------------------------------------------- 5653// 2.2.1 AdvancedAllStagesOneImage 5654//----------------------------------------------------------------------------- 5655class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase 5656{ 5657 GLuint m_program; 5658 GLuint m_vao; 5659 GLuint m_vbo; 5660 GLuint m_ebo; 5661 GLuint m_buffer; 5662 GLuint m_buffer_tex; 5663 GLuint m_texture; 5664 5665 virtual long Setup() 5666 { 5667 m_program = 0; 5668 m_vao = 0; 5669 m_vbo = 0; 5670 m_ebo = 0; 5671 m_buffer = 0; 5672 m_buffer_tex = 0; 5673 m_texture = 0; 5674 return NO_ERROR; 5675 } 5676 5677 virtual long Run() 5678 { 5679 if (!SupportedInGeomStages(2)) 5680 return NOT_SUPPORTED; 5681 const char* const glsl_vs = 5682 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 5683 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL 5684 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL 5685 " gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL " imageAtomicAdd(g_buffer, 0, 1);" NL 5686 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}"; 5687 const char* const glsl_tcs = 5688 "#version 420 core" NL "layout(vertices = 1) out;" NL 5689 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL 5690 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL 5691 " gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL " gl_TessLevelInner[0] = 1.0;" NL 5692 " gl_TessLevelInner[1] = 1.0;" NL " gl_TessLevelOuter[0] = 1.0;" NL " gl_TessLevelOuter[1] = 1.0;" NL 5693 " gl_TessLevelOuter[2] = 1.0;" NL " gl_TessLevelOuter[3] = 1.0;" NL " imageAtomicAdd(g_buffer, 0, 1);" NL 5694 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}"; 5695 const char* const glsl_tes = 5696 "#version 420 core" NL "layout(triangles, point_mode) in;" NL 5697 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL 5698 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL 5699 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL 5700 " gl_Position = gl_in[0].gl_Position;" NL "}"; 5701 const char* const glsl_gs = 5702 "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL 5703 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL 5704 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL 5705 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL 5706 " gl_Position = gl_in[0].gl_Position;" NL " EmitVertex();" NL "}"; 5707 const char* const glsl_fs = 5708 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 5709 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL 5710 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL 5711 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL 5712 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}"; 5713 m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs); 5714 glUseProgram(m_program); 5715 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0); 5716 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1); 5717 5718 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 5719 5720 GLint i32 = 0; 5721 glGenBuffers(1, &m_buffer); 5722 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5723 glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW); 5724 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5725 5726 glGenTextures(1, &m_buffer_tex); 5727 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex); 5728 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer); 5729 glBindTexture(GL_TEXTURE_BUFFER, 0); 5730 5731 GLuint ui32 = 0; 5732 glGenTextures(1, &m_texture); 5733 glBindTexture(GL_TEXTURE_2D, m_texture); 5734 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 5735 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 5736 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32); 5737 glBindTexture(GL_TEXTURE_2D, 0); 5738 5739 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I); 5740 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); 5741 5742 glBindVertexArray(m_vao); 5743 glPatchParameteri(GL_PATCH_VERTICES, 1); 5744 5745 glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0); 5746 glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1); 5747 5748 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 5749 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5750 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32); 5751 if (i32 < 20 || i32 > 50) 5752 { 5753 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32 5754 << " should be in the range [20;50]" << tcu::TestLog::EndMessage; 5755 return ERROR; 5756 } 5757 5758 glBindTexture(GL_TEXTURE_2D, m_texture); 5759 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32); 5760 if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32)) 5761 { 5762 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be " 5763 << (2 * i32) << tcu::TestLog::EndMessage; 5764 return ERROR; 5765 } 5766 5767 return NO_ERROR; 5768 } 5769 5770 virtual long Cleanup() 5771 { 5772 glPatchParameteri(GL_PATCH_VERTICES, 3); 5773 glUseProgram(0); 5774 glDeleteBuffers(1, &m_buffer); 5775 glDeleteBuffers(1, &m_vbo); 5776 glDeleteBuffers(1, &m_ebo); 5777 glDeleteTextures(1, &m_buffer_tex); 5778 glDeleteTextures(1, &m_texture); 5779 glDeleteProgram(m_program); 5780 glDeleteVertexArrays(1, &m_vao); 5781 return NO_ERROR; 5782 } 5783}; 5784//----------------------------------------------------------------------------- 5785// 2.3.1 AdvancedMemoryDependentInvocation 5786//----------------------------------------------------------------------------- 5787class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase 5788{ 5789 GLuint m_buffer; 5790 GLuint m_buffer_tex; 5791 GLuint m_texture; 5792 GLuint m_program; 5793 GLuint m_vao; 5794 GLuint m_vbo; 5795 5796 virtual long Setup() 5797 { 5798 m_buffer = 0; 5799 m_buffer_tex = 0; 5800 m_texture = 0; 5801 m_program = 0; 5802 m_vao = 0; 5803 m_vbo = 0; 5804 return NO_ERROR; 5805 } 5806 5807 virtual long Run() 5808 { 5809 if (!SupportedInVS(2)) 5810 return NOT_SUPPORTED; 5811 const char* const glsl_vs = 5812 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 5813 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL 5814 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL 5815 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " gl_Position = i_position;" NL 5816 " vs_color = i_color;" NL " imageStore(g_buffer, 0, vec4(1.0));" NL 5817 " imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL " memoryBarrier();" NL "}"; 5818 const char* const glsl_fs = 5819 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL 5820 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL 5821 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL 5822 " if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL 5823 " if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}"; 5824 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 5825 glUseProgram(m_program); 5826 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0); 5827 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1); 5828 5829 vec4 zero(0); 5830 glGenBuffers(1, &m_buffer); 5831 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5832 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW); 5833 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5834 5835 glGenTextures(1, &m_buffer_tex); 5836 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex); 5837 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer); 5838 glBindTexture(GL_TEXTURE_BUFFER, 0); 5839 5840 glGenTextures(1, &m_texture); 5841 glBindTexture(GL_TEXTURE_2D, m_texture); 5842 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 5843 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero); 5844 glBindTexture(GL_TEXTURE_2D, 0); 5845 5846 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 5847 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 5848 5849 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 5850 5851 glClear(GL_COLOR_BUFFER_BIT); 5852 glBindVertexArray(m_vao); 5853 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0); 5854 5855 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 5856 { 5857 return ERROR; 5858 } 5859 return NO_ERROR; 5860 } 5861 5862 virtual long Cleanup() 5863 { 5864 glUseProgram(0); 5865 glDeleteBuffers(1, &m_vbo); 5866 glDeleteBuffers(1, &m_buffer); 5867 glDeleteTextures(1, &m_texture); 5868 glDeleteTextures(1, &m_buffer_tex); 5869 glDeleteProgram(m_program); 5870 glDeleteVertexArrays(1, &m_vao); 5871 return NO_ERROR; 5872 } 5873}; 5874//----------------------------------------------------------------------------- 5875// 2.3.2 AdvancedMemoryOrder 5876//----------------------------------------------------------------------------- 5877class AdvancedMemoryOrder : public ShaderImageLoadStoreBase 5878{ 5879 GLuint m_buffer; 5880 GLuint m_buffer_tex; 5881 GLuint m_texture; 5882 GLuint m_program; 5883 GLuint m_vao; 5884 GLuint m_vbo; 5885 5886 virtual long Setup() 5887 { 5888 m_buffer = 0; 5889 m_buffer_tex = 0; 5890 m_texture = 0; 5891 m_program = 0; 5892 m_vao = 0; 5893 m_vbo = 0; 5894 return NO_ERROR; 5895 } 5896 5897 virtual long Run() 5898 { 5899 if (!SupportedInVS(1)) 5900 return NOT_SUPPORTED; 5901 const char* const glsl_vs = 5902 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL 5903 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL 5904 " gl_Position = i_position;" NL " vs_color = vec4(0, 1, 0, 1);" NL 5905 " imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL " imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL 5906 " imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL 5907 " if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}"; 5908 const char* const glsl_fs = 5909 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL 5910 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL 5911 " ivec2 coord = ivec2(gl_FragCoord);" NL " for (int i = 0; i < 3; ++i) {" NL 5912 " imageStore(g_image, coord, vec4(i));" NL " vec4 v = imageLoad(g_image, coord);" NL 5913 " if (v != vec4(i)) {" NL " o_color = vec4(v.xyz, 0.0);" NL " break;" NL " }" NL " }" NL 5914 "}"; 5915 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 5916 glUseProgram(m_program); 5917 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0); 5918 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1); 5919 5920 glGenBuffers(1, &m_buffer); 5921 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 5922 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW); 5923 glBindBuffer(GL_TEXTURE_BUFFER, 0); 5924 5925 glGenTextures(1, &m_buffer_tex); 5926 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex); 5927 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer); 5928 glBindTexture(GL_TEXTURE_BUFFER, 0); 5929 5930 int width = getWindowWidth(); 5931 int height = getWindowHeight(); 5932 scaleDimensionsToMemory(width, height, 1, 2, 16, 16); 5933 5934 std::vector<vec4> data(width * height); 5935 glGenTextures(1, &m_texture); 5936 glBindTexture(GL_TEXTURE_2D, m_texture); 5937 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 5938 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]); 5939 glBindTexture(GL_TEXTURE_2D, 0); 5940 5941 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 5942 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 5943 5944 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 5945 5946 glClear(GL_COLOR_BUFFER_BIT); 5947 glViewport(0, 0, width, height); 5948 glBindVertexArray(m_vao); 5949 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0); 5950 5951 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1))) 5952 { 5953 return ERROR; 5954 } 5955 return NO_ERROR; 5956 } 5957 5958 virtual long Cleanup() 5959 { 5960 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 5961 glUseProgram(0); 5962 glDeleteBuffers(1, &m_vbo); 5963 glDeleteBuffers(1, &m_buffer); 5964 glDeleteTextures(1, &m_texture); 5965 glDeleteTextures(1, &m_buffer_tex); 5966 glDeleteProgram(m_program); 5967 glDeleteVertexArrays(1, &m_vao); 5968 return NO_ERROR; 5969 } 5970}; 5971//----------------------------------------------------------------------------- 5972// 2.4.1 AdvancedSSOSimple 5973//----------------------------------------------------------------------------- 5974class AdvancedSSOSimple : public ShaderImageLoadStoreBase 5975{ 5976 GLuint m_texture; 5977 GLuint m_pipeline[2]; 5978 GLuint m_vsp, m_fsp0, m_fsp1; 5979 GLuint m_vao, m_vbo; 5980 5981 virtual long Setup() 5982 { 5983 glGenTextures(1, &m_texture); 5984 glGenProgramPipelines(2, m_pipeline); 5985 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 5986 5987 const char* const glsl_vs = 5988 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL 5989 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 5990 const char* const glsl_fs0 = 5991 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL 5992 " for (int i = 0; i < g_image.length(); ++i) {" NL 5993 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL " }" NL " discard;" NL "}"; 5994 const char* const glsl_fs1 = 5995 "#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL 5996 " for (int i = 0; i < g_image.length(); ++i) {" NL 5997 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL " }" NL " discard;" NL "}"; 5998 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs); 5999 m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0); 6000 m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1); 6001 6002 return NO_ERROR; 6003 } 6004 6005 virtual long Run() 6006 { 6007 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0); 6008 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2); 6009 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4); 6010 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6); 6011 6012 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1); 6013 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3); 6014 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5); 6015 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7); 6016 6017 glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp); 6018 glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0); 6019 6020 glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp); 6021 glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1); 6022 6023 int width = getWindowWidth(); 6024 int height = getWindowHeight(); 6025 scaleDimensionsToMemory(width, height, 8, 8, 16, 16); 6026 6027 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 6028 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 6029 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 8, 0, GL_RGBA, GL_FLOAT, NULL); 6030 6031 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6032 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F); 6033 glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F); 6034 glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F); 6035 glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F); 6036 glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F); 6037 glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F); 6038 glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F); 6039 6040 glBindVertexArray(m_vao); 6041 6042 glViewport(0, 0, width, height); 6043 glBindProgramPipeline(m_pipeline[0]); 6044 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0); 6045 6046 glBindProgramPipeline(m_pipeline[1]); 6047 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 6048 6049 std::vector<vec4> data(width * height * 8); 6050 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]); 6051 6052 for (int layer = 0; layer < 8; ++layer) 6053 { 6054 for (int h = 0; h < height; ++h) 6055 { 6056 for (int w = 0; w < width; ++w) 6057 { 6058 const vec4 c = data[layer * width * height + h * width + w]; 6059 if (layer % 2) 6060 { 6061 if (!IsEqual(c, vec4(2.0f))) 6062 { 6063 return ERROR; 6064 } 6065 } 6066 else 6067 { 6068 if (!IsEqual(c, vec4(1.0f))) 6069 { 6070 return ERROR; 6071 } 6072 } 6073 } 6074 } 6075 } 6076 return NO_ERROR; 6077 } 6078 6079 virtual long Cleanup() 6080 { 6081 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 6082 glDeleteBuffers(1, &m_vbo); 6083 glDeleteTextures(1, &m_texture); 6084 glDeleteProgram(m_vsp); 6085 glDeleteProgram(m_fsp0); 6086 glDeleteProgram(m_fsp1); 6087 glDeleteVertexArrays(1, &m_vao); 6088 glDeleteProgramPipelines(2, m_pipeline); 6089 return NO_ERROR; 6090 } 6091}; 6092//----------------------------------------------------------------------------- 6093// 2.4.2 AdvancedSSOAtomicCounters 6094//----------------------------------------------------------------------------- 6095class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase 6096{ 6097 GLuint m_buffer, m_buffer_tex; 6098 GLuint m_counter_buffer; 6099 GLuint m_transform_buffer; 6100 GLuint m_pipeline; 6101 GLuint m_vao, m_vbo; 6102 GLuint m_vsp, m_fsp; 6103 6104 virtual long Setup() 6105 { 6106 m_vao = 0; 6107 m_vbo = 0; 6108 m_vsp = 0; 6109 m_fsp = 0; 6110 glGenBuffers(1, &m_buffer); 6111 glGenTextures(1, &m_buffer_tex); 6112 glGenBuffers(1, &m_counter_buffer); 6113 glGenBuffers(1, &m_transform_buffer); 6114 glGenProgramPipelines(1, &m_pipeline); 6115 return NO_ERROR; 6116 } 6117 6118 virtual long Run() 6119 { 6120 if (!SupportedInVS(1)) 6121 return NOT_SUPPORTED; 6122 6123 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 6124 const char* const glsl_vs = 6125 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 6126 "layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL 6127 "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL 6128 " mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL 6129 "layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL 6130 " gl_Position = g_transform.mvp * i_position;" NL " o_color = i_color;" NL 6131 " const uint index = atomicCounterIncrement(g_counter);" NL 6132 " imageStore(g_buffer, int(index), gl_Position);" NL "}"; 6133 const char* const glsl_fs = 6134 "#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL 6135 "layout(location = 0) out vec4 o_color;" NL "void main() {" NL " o_color = i_color;" NL "}"; 6136 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs); 6137 m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs); 6138 6139 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp); 6140 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp); 6141 6142 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 6143 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW); 6144 6145 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex); 6146 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer); 6147 6148 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer); 6149 vec4 zero(0); 6150 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW); 6151 6152 glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer); 6153 mat4 identity(1); 6154 glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW); 6155 6156 glClear(GL_COLOR_BUFFER_BIT); 6157 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer); 6158 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer); 6159 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6160 glBindVertexArray(m_vao); 6161 glBindProgramPipeline(m_pipeline); 6162 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0); 6163 6164 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 6165 { 6166 return ERROR; 6167 } 6168 6169 std::vector<vec4> data(4); 6170 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer); 6171 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]); 6172 6173 for (int i = 0; i < 4; ++i) 6174 { 6175 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)) && 6176 !IsEqual(data[i], vec4(-1.0f, 1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, 1.0f, 0.0f, 1.0f))) 6177 { 6178 return ERROR; 6179 } 6180 } 6181 6182 return NO_ERROR; 6183 } 6184 6185 virtual long Cleanup() 6186 { 6187 glDeleteBuffers(1, &m_buffer); 6188 glDeleteBuffers(1, &m_vbo); 6189 glDeleteBuffers(1, &m_counter_buffer); 6190 glDeleteBuffers(1, &m_transform_buffer); 6191 glDeleteTextures(1, &m_buffer_tex); 6192 glDeleteProgram(m_vsp); 6193 glDeleteProgram(m_fsp); 6194 glDeleteVertexArrays(1, &m_vao); 6195 glDeleteProgramPipelines(1, &m_pipeline); 6196 return NO_ERROR; 6197 } 6198}; 6199//----------------------------------------------------------------------------- 6200// 2.4.3 AdvancedSSOSubroutine 6201//----------------------------------------------------------------------------- 6202class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase 6203{ 6204 GLuint m_texture; 6205 GLuint m_attribless_vao; 6206 GLuint m_program; 6207 GLint m_draw_buffer; 6208 6209 virtual long Setup() 6210 { 6211 glGenTextures(1, &m_texture); 6212 glGenVertexArrays(1, &m_attribless_vao); 6213 6214 const char* const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL 6215 "const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL 6216 "void main() {" NL " gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}"; 6217 const char* const glsl_fs = 6218 "#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL 6219 "writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL 6220 "subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL 6221 " imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL 6222 " imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL 6223 " imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL 6224 "subroutine(Brush) void Brush1(ivec2 coord) {" NL 6225 " imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL 6226 " imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL 6227 " imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL 6228 " g_brush(ivec2(gl_FragCoord));" NL "}"; 6229 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 6230 6231 return NO_ERROR; 6232 } 6233 6234 virtual long Run() 6235 { 6236 int width = getWindowWidth(); 6237 int height = getWindowHeight(); 6238 scaleDimensionsToMemory(width, height, 3, 3, 16, 16); 6239 6240 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1); 6241 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1); 6242 6243 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 6244 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 6245 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 3, 0, GL_RGBA, GL_FLOAT, NULL); 6246 6247 glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer); 6248 6249 glDrawBuffer(GL_NONE); 6250 glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F); 6251 glUseProgram(m_program); 6252 glBindVertexArray(m_attribless_vao); 6253 6254 const GLuint indices[2] = { glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"), 6255 glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1") }; 6256 6257 glViewport(0, 0, width, height); 6258 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]); 6259 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0); 6260 6261 std::vector<vec4> data(width * height * 3); 6262 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 6263 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]); 6264 6265 for (int layer = 0; layer < 3; ++layer) 6266 { 6267 for (int h = 0; h < height; ++h) 6268 { 6269 for (int w = 0; w < width; ++w) 6270 { 6271 const vec4 c = data[layer * width * height + h * width + w]; 6272 if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f))) 6273 { 6274 m_context.getTestContext().getLog() 6275 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6276 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage; 6277 return ERROR; 6278 } 6279 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f))) 6280 { 6281 m_context.getTestContext().getLog() 6282 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6283 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage; 6284 return ERROR; 6285 } 6286 else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f))) 6287 { 6288 m_context.getTestContext().getLog() 6289 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6290 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage; 6291 return ERROR; 6292 } 6293 } 6294 } 6295 } 6296 6297 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]); 6298 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0); 6299 6300 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 6301 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]); 6302 6303 for (int layer = 0; layer < 3; ++layer) 6304 { 6305 for (int h = 0; h < height; ++h) 6306 { 6307 for (int w = 0; w < width; ++w) 6308 { 6309 const vec4 c = data[layer * width * height + h * width + w]; 6310 if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f))) 6311 { 6312 m_context.getTestContext().getLog() 6313 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6314 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage; 6315 return ERROR; 6316 } 6317 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f))) 6318 { 6319 m_context.getTestContext().getLog() 6320 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6321 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage; 6322 return ERROR; 6323 } 6324 else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f))) 6325 { 6326 m_context.getTestContext().getLog() 6327 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6328 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage; 6329 return ERROR; 6330 } 6331 } 6332 } 6333 } 6334 return NO_ERROR; 6335 } 6336 6337 virtual long Cleanup() 6338 { 6339 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 6340 glDrawBuffer(m_draw_buffer); 6341 glDeleteTextures(1, &m_texture); 6342 glUseProgram(0); 6343 glDeleteProgram(m_program); 6344 glDeleteVertexArrays(1, &m_attribless_vao); 6345 return NO_ERROR; 6346 } 6347}; 6348//----------------------------------------------------------------------------- 6349// 2.4.4 AdvancedSSOPerSample 6350//----------------------------------------------------------------------------- 6351class AdvancedSSOPerSample : public ShaderImageLoadStoreBase 6352{ 6353 GLuint m_texture; 6354 GLuint m_pipeline; 6355 GLuint m_vao, m_vbo, m_ebo; 6356 GLuint m_vsp, m_store_fsp, m_load_fsp; 6357 6358 virtual long Setup() 6359 { 6360 m_vao = 0; 6361 m_vbo = 0; 6362 m_ebo = 0; 6363 m_vsp = 0; 6364 m_store_fsp = 0; 6365 m_load_fsp = 0; 6366 glGenTextures(1, &m_texture); 6367 glGenProgramPipelines(1, &m_pipeline); 6368 6369 return NO_ERROR; 6370 } 6371 6372 virtual long Run() 6373 { 6374 if (!SupportedSamples(4)) 6375 return NOT_SUPPORTED; 6376 6377 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 6378 6379 const char* const glsl_vs = 6380 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL 6381 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 6382 const char* const glsl_store_fs = 6383 "#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL 6384 " imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}"; 6385 const char* const glsl_load_fs = 6386 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 6387 "layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL 6388 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != " 6389 "vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}"; 6390 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs); 6391 m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs); 6392 m_load_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs); 6393 6394 int width = getWindowWidth(); 6395 int height = getWindowHeight(); 6396 scaleDimensionsToMemory(width, height, 1, 1, /* bpp*samples */ 16 * 4, 16); 6397 6398 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture); 6399 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, width, height, GL_FALSE); 6400 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); 6401 6402 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp); 6403 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp); 6404 6405 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6406 6407 glClear(GL_COLOR_BUFFER_BIT); 6408 glViewport(0, 0, width, height); 6409 glBindVertexArray(m_vao); 6410 glBindProgramPipeline(m_pipeline); 6411 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0); 6412 6413 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 6414 6415 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp); 6416 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0); 6417 6418 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1))) 6419 { 6420 return ERROR; 6421 } 6422 return NO_ERROR; 6423 } 6424 6425 virtual long Cleanup() 6426 { 6427 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 6428 glDeleteBuffers(1, &m_vbo); 6429 glDeleteBuffers(1, &m_ebo); 6430 glDeleteTextures(1, &m_texture); 6431 glDeleteProgram(m_vsp); 6432 glDeleteProgram(m_store_fsp); 6433 glDeleteProgram(m_load_fsp); 6434 glDeleteVertexArrays(1, &m_vao); 6435 glDeleteProgramPipelines(1, &m_pipeline); 6436 return NO_ERROR; 6437 } 6438}; 6439 6440//----------------------------------------------------------------------------- 6441// 2.5 AdvancedCopyImage 6442//----------------------------------------------------------------------------- 6443class AdvancedCopyImage : public ShaderImageLoadStoreBase 6444{ 6445 GLuint m_texture[2]; 6446 GLuint m_program; 6447 GLuint m_vao, m_vbo, m_ebo; 6448 6449 virtual long Setup() 6450 { 6451 glGenTextures(2, m_texture); 6452 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 6453 6454 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 6455 "void main() {" NL " gl_Position = i_position;" NL "}"; 6456 const char* const glsl_fs = 6457 "#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL 6458 "layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL 6459 " ivec2 coord = ivec2(gl_FragCoord);" NL 6460 " imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL " discard;" NL "}"; 6461 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 6462 6463 return NO_ERROR; 6464 } 6465 6466 virtual long Run() 6467 { 6468 int width = getWindowWidth(); 6469 int height = getWindowHeight(); 6470 scaleDimensionsToMemory(width, height, 2, 2, 16, 16); 6471 6472 glUseProgram(m_program); 6473 glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0); 6474 glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1); 6475 6476 std::vector<vec4> data(width * height, vec4(7.0f)); 6477 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 6478 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 6479 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]); 6480 6481 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 6482 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 6483 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL); 6484 6485 glBindTexture(GL_TEXTURE_2D, 0); 6486 6487 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); 6488 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 6489 6490 glClear(GL_COLOR_BUFFER_BIT); 6491 glViewport(0, 0, width, height); 6492 glBindVertexArray(m_vao); 6493 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0); 6494 6495 std::vector<vec4> rdata(width * height); 6496 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 6497 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]); 6498 6499 for (int h = 0; h < height; ++h) 6500 { 6501 for (int w = 0; w < width; ++w) 6502 { 6503 if (!IsEqual(rdata[h * width + w], vec4(7.0f))) 6504 { 6505 return ERROR; 6506 } 6507 } 6508 } 6509 return NO_ERROR; 6510 } 6511 6512 virtual long Cleanup() 6513 { 6514 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 6515 glUseProgram(0); 6516 glDeleteBuffers(1, &m_vbo); 6517 glDeleteBuffers(1, &m_ebo); 6518 glDeleteTextures(2, m_texture); 6519 glDeleteProgram(m_program); 6520 glDeleteVertexArrays(1, &m_vao); 6521 return NO_ERROR; 6522 } 6523}; 6524//----------------------------------------------------------------------------- 6525// 2.6 AdvancedAllMips 6526//----------------------------------------------------------------------------- 6527class AdvancedAllMips : public ShaderImageLoadStoreBase 6528{ 6529 GLuint m_texture; 6530 GLuint m_store_program, m_load_program; 6531 GLuint m_vao, m_vbo, m_ebo; 6532 6533 virtual long Setup() 6534 { 6535 glGenTextures(1, &m_texture); 6536 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 6537 6538 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 6539 "void main() {" NL " gl_Position = i_position;" NL "}"; 6540 const char* const glsl_store_fs = 6541 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL 6542 " for (int i = 0; i < 6; ++i) {" NL " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL " }" NL 6543 " discard;" NL "}"; 6544 const char* const glsl_load_fs = 6545 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 6546 "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL 6547 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " for (int i = 0; i < 6; ++i) {" NL 6548 " const ivec2 coord = ivec2(gl_FragCoord);" NL " const vec4 c = imageLoad(g_image[i], coord);" NL 6549 " if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " }" NL "}"; 6550 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs); 6551 m_load_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs); 6552 6553 return NO_ERROR; 6554 } 6555 6556 virtual long Run() 6557 { 6558 glUseProgram(m_store_program); 6559 glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0); 6560 glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1); 6561 glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2); 6562 glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3); 6563 glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4); 6564 glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5); 6565 glUseProgram(0); 6566 6567 glUseProgram(m_load_program); 6568 glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0); 6569 glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1); 6570 glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2); 6571 glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3); 6572 glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4); 6573 glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5); 6574 glUseProgram(0); 6575 6576 glBindTexture(GL_TEXTURE_2D, m_texture); 6577 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL); 6578 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL); 6579 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL); 6580 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL); 6581 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL); 6582 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL); 6583 glBindTexture(GL_TEXTURE_2D, 0); 6584 6585 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6586 glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6587 glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6588 glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6589 glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6590 glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 6591 6592 glViewport(0, 0, 32, 32); 6593 glBindVertexArray(m_vao); 6594 6595 glClear(GL_COLOR_BUFFER_BIT); 6596 glUseProgram(m_store_program); 6597 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0); 6598 6599 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 6600 6601 glUseProgram(m_load_program); 6602 glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0); 6603 6604 if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1))) 6605 { 6606 return ERROR; 6607 } 6608 return NO_ERROR; 6609 } 6610 6611 virtual long Cleanup() 6612 { 6613 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 6614 glUseProgram(0); 6615 glDeleteBuffers(1, &m_vbo); 6616 glDeleteBuffers(1, &m_ebo); 6617 glDeleteTextures(1, &m_texture); 6618 glDeleteProgram(m_store_program); 6619 glDeleteProgram(m_load_program); 6620 glDeleteVertexArrays(1, &m_vao); 6621 return NO_ERROR; 6622 } 6623}; 6624//----------------------------------------------------------------------------- 6625// 2.7 AdvancedCast 6626//----------------------------------------------------------------------------- 6627class AdvancedCast : public ShaderImageLoadStoreBase 6628{ 6629 GLuint m_texture[2]; 6630 GLuint m_program; 6631 GLuint m_vao, m_vbo, m_ebo; 6632 6633 virtual long Setup() 6634 { 6635 glGenTextures(2, m_texture); 6636 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 6637 6638 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 6639 "void main() {" NL " gl_Position = i_position;" NL "}"; 6640 const char* const glsl_fs = 6641 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 6642 "layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL 6643 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " ivec2 coord = ivec2(gl_FragCoord);" NL 6644 " if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 6645 " if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 6646 " if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 6647 " if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}"; 6648 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 6649 6650 return NO_ERROR; 6651 } 6652 6653 virtual long Run() 6654 { 6655 glUseProgram(m_program); 6656 glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0); 6657 glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1); 6658 6659 { 6660 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4); 6661 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 6662 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 6663 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 6664 &data[0]); 6665 6666 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 6667 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 6668 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 6669 &data[0]); 6670 6671 glBindTexture(GL_TEXTURE_2D, 0); 6672 } 6673 6674 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I); 6675 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); 6676 6677 glClear(GL_COLOR_BUFFER_BIT); 6678 glBindVertexArray(m_vao); 6679 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0); 6680 6681 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4); 6682 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 6683 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 6684 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); 6685 6686 for (int h = 0; h < getWindowHeight(); ++h) 6687 { 6688 for (int w = 0; w < getWindowWidth(); ++w) 6689 { 6690 const GLubyte c[4] = { 6691 data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1], 6692 data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3], 6693 }; 6694 if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0) 6695 { 6696 m_context.getTestContext().getLog() 6697 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6698 << ") should be (1 0 0 0)" << tcu::TestLog::EndMessage; 6699 return ERROR; 6700 } 6701 } 6702 } 6703 6704 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 6705 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); 6706 6707 for (int h = 0; h < getWindowHeight(); ++h) 6708 { 6709 for (int w = 0; w < getWindowWidth(); ++w) 6710 { 6711 const GLubyte c[4] = { 6712 data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1], 6713 data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3], 6714 }; 6715 if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0) 6716 { 6717 m_context.getTestContext().getLog() 6718 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3] 6719 << ") should be (3 0 0 0)" << tcu::TestLog::EndMessage; 6720 return ERROR; 6721 } 6722 } 6723 } 6724 6725 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1))) 6726 { 6727 return ERROR; 6728 } 6729 return NO_ERROR; 6730 } 6731 6732 virtual long Cleanup() 6733 { 6734 glUseProgram(0); 6735 glDeleteBuffers(1, &m_vbo); 6736 glDeleteBuffers(1, &m_ebo); 6737 glDeleteTextures(2, m_texture); 6738 glDeleteProgram(m_program); 6739 glDeleteVertexArrays(1, &m_vao); 6740 return NO_ERROR; 6741 } 6742}; 6743 6744/** Test "imageLoad() and imageStore() for single-byte data alignment" description follows. 6745 * 6746 * Steps: 6747 * - create two textures: "source" and "destination". Fill "source" 6748 * texture with unique values. Fill "destination" texture with zeros, 6749 * - prepare a program object that will read texel from "source" image at given 6750 * coordinates and write its value to "destination" image at same 6751 * coordinates, 6752 * - bind "source" and "destination" textures as "source" and "destination" 6753 * image uniforms, 6754 * - render "full screen" quad (left bottom corner at -1,-1 and right top 6755 * corner at 1,1), 6756 * - verify that texel values in "destination" texture match those in 6757 * "source" texture (use glGetTexImage). 6758 * 6759 * Test with 2D R8UI textures with following dimensions: 6760 * - 16x16, 6761 * - 16x17, 6762 * - 17x16, 6763 * - 17x17, 6764 * - 16x18, 6765 * - 18x16, 6766 * - 18x18, 6767 * - 19x16, 6768 * - 16x19, 6769 * - 19x19. 6770 * 6771 * Note that default data alignment should cause problems with packing/ 6772 * /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters 6773 * of pixel storage mode have to be changed to one byte alignment. 6774 * 6775 * Program should consist of vertex and fragment shader. Vertex shader should 6776 * pass vertex position through. Fragment shader should do imageLoad() and 6777 * imageStore() operations at coordinates gl_FragCoord. 6778 **/ 6779class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase 6780{ 6781private: 6782 /* Structures */ 6783 struct TextureDimensions 6784 { 6785 GLuint m_width; 6786 GLuint m_height; 6787 6788 TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height) 6789 { 6790 } 6791 }; 6792 6793 /* Typedefs */ 6794 typedef std::deque<TextureDimensions> TextureDimensionsList; 6795 6796 /* Fields */ 6797 GLuint m_destination_texture_id; 6798 GLuint m_program_id; 6799 TextureDimensionsList m_texture_dimensions; 6800 GLuint m_source_texture_id; 6801 GLuint m_vertex_array_object_id; 6802 GLuint m_vertex_buffer_id; 6803 6804public: 6805 /* Constructor */ 6806 ImageLoadStoreDataAlignmentTest() 6807 : m_destination_texture_id(0) 6808 , m_program_id(0) 6809 , m_source_texture_id(0) 6810 , m_vertex_array_object_id(0) 6811 , m_vertex_buffer_id(0) 6812 { 6813 /* Nothing to be done here */ 6814 } 6815 6816 /* Methods inherited from SubcaseBase */ 6817 virtual long Setup() 6818 { 6819 /* Shaders code */ 6820 const char* const vertex_shader_code = "#version 400 core\n" 6821 "#extension GL_ARB_shader_image_load_store : require\n" 6822 "\n" 6823 "precision highp float;\n" 6824 "\n" 6825 "in vec4 vs_in_position;\n" 6826 "\n" 6827 "void main()\n" 6828 "{\n" 6829 " gl_Position = vs_in_position;\n" 6830 "}\n"; 6831 6832 const char* const fragment_shader_code = 6833 "#version 400 core\n" 6834 "#extension GL_ARB_shader_image_load_store : require\n" 6835 "\n" 6836 "precision highp float;\n" 6837 "\n" 6838 "layout(r8ui) writeonly uniform uimage2D u_destination_image;\n" 6839 "layout(r8ui) readonly uniform uimage2D u_source_image;\n" 6840 "\n" 6841 "void main()\n" 6842 "{\n" 6843 " uvec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n" 6844 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n" 6845 "\n" 6846 " discard;\n" 6847 "}\n"; 6848 6849 /* Vertex postions for "full screen" quad, made with triangle strip */ 6850 static const GLfloat m_vertex_buffer_data[] = { 6851 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */ 6852 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */ 6853 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */ 6854 1.0f, 1.0f, 0.0f, 1.0f, /* right top */ 6855 }; 6856 6857 /* Result of BuildProgram operation */ 6858 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */ 6859 6860 /* Add all tested texture dimensions */ 6861 m_texture_dimensions.push_back(TextureDimensions(16, 16)); 6862 m_texture_dimensions.push_back(TextureDimensions(16, 17)); 6863 m_texture_dimensions.push_back(TextureDimensions(17, 16)); 6864 m_texture_dimensions.push_back(TextureDimensions(17, 17)); 6865 m_texture_dimensions.push_back(TextureDimensions(16, 18)); 6866 m_texture_dimensions.push_back(TextureDimensions(18, 16)); 6867 m_texture_dimensions.push_back(TextureDimensions(18, 18)); 6868 m_texture_dimensions.push_back(TextureDimensions(16, 19)); 6869 m_texture_dimensions.push_back(TextureDimensions(19, 16)); 6870 m_texture_dimensions.push_back(TextureDimensions(19, 19)); 6871 6872 /* Clean previous error */ 6873 glGetError(); 6874 6875 /* Set single-byte data alignment */ 6876 glPixelStorei(GL_PACK_ALIGNMENT, 1); 6877 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 6878 GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei"); 6879 6880 /* Prepare buffer with vertex positions of "full screen" quad" */ 6881 glGenBuffers(1, &m_vertex_buffer_id); 6882 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers"); 6883 6884 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id); 6885 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer"); 6886 6887 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW); 6888 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData"); 6889 6890 /* Generate vertex array object */ 6891 glGenVertexArrays(1, &m_vertex_array_object_id); 6892 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays"); 6893 6894 /* Prepare program object */ 6895 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */, 6896 fragment_shader_code, &is_program_correct); 6897 if (false == is_program_correct) 6898 { 6899 return ERROR; 6900 } 6901 6902 /* Done */ 6903 return NO_ERROR; 6904 } 6905 6906 virtual long Cleanup() 6907 { 6908 /* Reset OpenGL state */ 6909 glBindBuffer(GL_ARRAY_BUFFER, 0); 6910 glBindTexture(GL_TEXTURE_2D, 0); 6911 glBindVertexArray(0); 6912 glUseProgram(0); 6913 6914 /* Delete program */ 6915 if (0 != m_program_id) 6916 { 6917 glDeleteProgram(m_program_id); 6918 m_program_id = 0; 6919 } 6920 6921 /* Delete textures */ 6922 if (0 != m_destination_texture_id) 6923 { 6924 glDeleteTextures(1, &m_destination_texture_id); 6925 m_destination_texture_id = 0; 6926 } 6927 6928 if (0 != m_source_texture_id) 6929 { 6930 glDeleteTextures(1, &m_source_texture_id); 6931 m_source_texture_id = 0; 6932 } 6933 6934 /* Delete vertex array object */ 6935 if (0 != m_vertex_array_object_id) 6936 { 6937 glDeleteVertexArrays(1, &m_vertex_array_object_id); 6938 m_vertex_array_object_id = 0; 6939 } 6940 6941 /* Delete buffer */ 6942 if (0 != m_vertex_buffer_id) 6943 { 6944 glDeleteBuffers(1, &m_vertex_buffer_id); 6945 m_vertex_buffer_id = 0; 6946 } 6947 6948 /* Done */ 6949 return NO_ERROR; 6950 } 6951 6952 virtual long Run() 6953 { 6954 bool result = true; 6955 6956 /* For each dimension */ 6957 for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it; 6958 ++it) 6959 { 6960 /* Prepare "source" and "destination" textures */ 6961 GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id), 6962 "Create2DR8UIDestinationTexture"); 6963 GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id), 6964 "Create2DR8UISourceTexture"); 6965 6966 /* Copy texture data with imageLoad() and imageStore() operations */ 6967 Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id); 6968 6969 /* Compare "source" and "destination" textures */ 6970 if (false == 6971 Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height)) 6972 { 6973 m_context.getTestContext().getLog() 6974 << tcu::TestLog::Message 6975 << "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height 6976 << ". Source and destination textures are different" << tcu::TestLog::EndMessage; 6977 6978 result = false; 6979 } 6980 6981 /* Destroy "source" and "destination" textures */ 6982 glDeleteTextures(1, &m_destination_texture_id); 6983 glDeleteTextures(1, &m_source_texture_id); 6984 6985 m_destination_texture_id = 0; 6986 m_source_texture_id = 0; 6987 } 6988 6989 if (false == result) 6990 { 6991 return ERROR; 6992 } 6993 6994 /* Done */ 6995 return NO_ERROR; 6996 } 6997 6998private: 6999 /* Private methods */ 7000 7001 /** Binds a texture to user-specified image unit and updates relevant sampler uniform 7002 * 7003 * @param program_id Program object id 7004 * @param texture_id Texture id 7005 * @param image_unit Index of image unit 7006 * @param uniform_name Name of image uniform 7007 **/ 7008 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char* uniform_name) 7009 { 7010 /* Uniform location and invalid value */ 7011 static const GLint invalid_uniform_location = -1; 7012 GLint image_uniform_location = 0; 7013 7014 /* Get uniform location */ 7015 image_uniform_location = glGetUniformLocation(program_id, uniform_name); 7016 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation"); 7017 if (invalid_uniform_location == image_uniform_location) 7018 { 7019 throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__); 7020 } 7021 7022 /* Bind texture to image unit */ 7023 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI); 7024 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture"); 7025 7026 /* Set uniform to image unit */ 7027 glUniform1i(image_uniform_location, image_unit); 7028 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 7029 } 7030 7031 /** Compare two 2D R8UI textures 7032 * 7033 * @param left_texture_id Id of "left" texture object 7034 * @param right_texture_id Id of "right" texture object 7035 * @param width Width of the textures 7036 * @param height Height of the textures 7037 * 7038 * @return true when texture data is identical, false otherwise 7039 **/ 7040 bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height) 7041 { 7042 /* Size of textures */ 7043 const GLuint texture_data_size = width * height; 7044 7045 /* Storage for texture data */ 7046 std::vector<GLubyte> left_texture_data; 7047 std::vector<GLubyte> right_texture_data; 7048 7049 /* Alocate memory for texture data */ 7050 left_texture_data.resize(texture_data_size); 7051 right_texture_data.resize(texture_data_size); 7052 7053 /* Get "left" texture data */ 7054 glBindTexture(GL_TEXTURE_2D, left_texture_id); 7055 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 7056 7057 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]); 7058 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 7059 7060 /* Get "right" texture data */ 7061 glBindTexture(GL_TEXTURE_2D, right_texture_id); 7062 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 7063 7064 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]); 7065 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 7066 7067 /* Compare texels */ 7068 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size)); 7069 } 7070 7071 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations 7072 * 7073 * @param destination_texture_id Id of "destination" texture object 7074 * @param source_texture_id Id of "source" texture object 7075 **/ 7076 void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id) 7077 { 7078 /* Uniform names */ 7079 static const char* const destination_image_uniform_name = "u_destination_image"; 7080 static const char* const source_image_uniform_name = "u_source_image"; 7081 7082 /* Attribute name */ 7083 static const char* const position_attribute_name = "vs_in_position"; 7084 7085 /* Attribute location and invalid value */ 7086 static const GLint invalid_attribute_location = -1; 7087 GLint position_attribute_location = 0; 7088 7089 /* Set current program */ 7090 glUseProgram(m_program_id); 7091 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram"); 7092 7093 /* Bind vertex array object */ 7094 glBindVertexArray(m_vertex_array_object_id); 7095 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray"); 7096 7097 /* Bind buffer with quad vertex positions */ 7098 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id); 7099 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer"); 7100 7101 /* Set up position attribute */ 7102 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name); 7103 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation"); 7104 if (invalid_attribute_location == position_attribute_location) 7105 { 7106 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__, 7107 __LINE__); 7108 } 7109 7110 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */, 7111 0 /* stride */, 0); 7112 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer"); 7113 7114 glEnableVertexAttribArray(position_attribute_location); 7115 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray"); 7116 7117 /* Set up textures as source and destination images */ 7118 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name); 7119 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name); 7120 7121 /* Execute draw */ 7122 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */); 7123 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 7124 } 7125 7126 /** Create 2D R8UI texture and fills it with zeros 7127 * 7128 * @param width Width of created texture 7129 * @param height Height of created texture 7130 * @param out_texture_id Id of created texture, not modified if operation fails 7131 * 7132 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 7133 **/ 7134 GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint& out_texture_id) 7135 { 7136 /* Texture size */ 7137 const GLuint texture_size = width * height; 7138 7139 /* Prepare storage for texture data */ 7140 std::vector<GLubyte> texture_data; 7141 texture_data.resize(texture_size); 7142 7143 /* Set all texels */ 7144 for (GLuint i = 0; i < texture_size; ++i) 7145 { 7146 texture_data[i] = 0; 7147 } 7148 7149 /* Create texture */ 7150 return Create2DR8UITexture(width, height, texture_data, out_texture_id); 7151 } 7152 7153 /** Create 2D R8UI texture and fills it with increasing values, starting from 0 7154 * 7155 * @param width Width of created texture 7156 * @param height Height of created texture 7157 * @param out_texture_id Id of created texture, not modified if operation fails 7158 * 7159 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 7160 **/ 7161 GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint& out_texture_id) 7162 { 7163 /* Texture size */ 7164 const GLuint texture_size = width * height; 7165 7166 /* Value of texel */ 7167 GLubyte texel_value = 0; 7168 7169 /* Prepare storage for texture data */ 7170 std::vector<GLubyte> texture_data; 7171 texture_data.resize(texture_size); 7172 7173 /* Set all texels */ 7174 for (GLuint i = 0; i < texture_size; ++i) 7175 { 7176 texture_data[i] = texel_value++; 7177 } 7178 7179 /* Create texture */ 7180 return Create2DR8UITexture(width, height, texture_data, out_texture_id); 7181 } 7182 7183 /** Create 2D R8UI texture and fills it with user-provided data 7184 * 7185 * @param width Width of created texture 7186 * @param height Height of created texture 7187 * @param texture_data Texture data 7188 * @param out_texture_id Id of created texture, not modified if operation fails 7189 * 7190 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 7191 **/ 7192 GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte>& texture_data, 7193 GLuint& out_texture_id) 7194 { 7195 GLenum err = 0; 7196 GLuint texture_id = 0; 7197 7198 /* Generate texture */ 7199 glGenTextures(1, &texture_id); 7200 err = glGetError(); 7201 if (GL_NO_ERROR != err) 7202 { 7203 return err; 7204 } 7205 7206 /* Bind texture */ 7207 glBindTexture(GL_TEXTURE_2D, texture_id); 7208 err = glGetError(); 7209 if (GL_NO_ERROR != err) 7210 { 7211 glDeleteTextures(1, &texture_id); 7212 return err; 7213 } 7214 7215 /* Allocate storage and fill texture */ 7216 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER, 7217 GL_UNSIGNED_BYTE, &texture_data[0]); 7218 err = glGetError(); 7219 if (GL_NO_ERROR != err) 7220 { 7221 glDeleteTextures(1, &texture_id); 7222 return err; 7223 } 7224 7225 /* Make texture complete */ 7226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 7227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 7228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 7229 err = glGetError(); 7230 if (GL_NO_ERROR != err) 7231 { 7232 glDeleteTextures(1, &texture_id); 7233 return err; 7234 } 7235 7236 /* Set out_texture_id */ 7237 out_texture_id = texture_id; 7238 7239 /* Done */ 7240 return GL_NO_ERROR; 7241 } 7242}; 7243 7244/** Test "imageLoad() and imageStore() for non-layered image bindings" description follows. 7245 * 7246 * Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest). 7247 * 7248 * Test non-layered image bindings (BindImageTexture <layered>: false) with: 7249 * | Type | Dimensions | 7250 * | 2D_ARRAY | 64x64x6 | 7251 * | 3D | 64x64x6 | 7252 * | CUBE_MAP | 64 | 7253 * | CUBE_MAP_ARRAY | 64x3 | 7254 * 7255 * Use RGBA8 format. All layers shall be tested. 7256 * 7257 * Program should consist of vertex and fragment shader. Vertex shader should 7258 * pass vertex position through. Fragment shader should do imageLoad() and 7259 * imageStore() operations at coordinates gl_FragCoord. Fragment shader should 7260 * use image2D as image type. 7261 **/ 7262class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase 7263{ 7264private: 7265 /* Structures */ 7266 struct TextureShapeDefinition 7267 { 7268 GLuint m_edge; 7269 GLuint m_n_elements; 7270 GLenum m_type; 7271 7272 TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type) 7273 : m_edge(edge), m_n_elements(n_elements), m_type(type) 7274 { 7275 } 7276 }; 7277 7278 /* Typedefs */ 7279 typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList; 7280 7281 /* Fields */ 7282 GLuint m_destination_texture_id; 7283 GLuint m_program_id; 7284 TextureShapeDefinitionList m_texture_shape_definitions; 7285 GLuint m_source_texture_id; 7286 GLuint m_vertex_array_object_id; 7287 GLuint m_vertex_buffer_id; 7288 7289public: 7290 /* Constructor */ 7291 ImageLoadStoreNonLayeredBindingTest() 7292 : m_destination_texture_id(0) 7293 , m_program_id(0) 7294 , m_source_texture_id(0) 7295 , m_vertex_array_object_id(0) 7296 , m_vertex_buffer_id(0) 7297 { 7298 /* Nothing to be done here */ 7299 } 7300 7301 /* Methods inherited from SubcaseBase */ 7302 virtual long Setup() 7303 { 7304 /* Shaders code */ 7305 const char* const vertex_shader_code = "#version 400 core\n" 7306 "#extension GL_ARB_shader_image_load_store : require\n" 7307 "\n" 7308 "precision highp float;\n" 7309 "\n" 7310 "in vec4 vs_in_position;\n" 7311 "\n" 7312 "void main()\n" 7313 "{\n" 7314 " gl_Position = vs_in_position;\n" 7315 "}\n"; 7316 7317 const char* const fragment_shader_code = 7318 "#version 400 core\n" 7319 "#extension GL_ARB_shader_image_load_store : require\n" 7320 "\n" 7321 "precision highp float;\n" 7322 "\n" 7323 "layout(rgba8) writeonly uniform image2D u_destination_image;\n" 7324 "layout(rgba8) readonly uniform image2D u_source_image;\n" 7325 "\n" 7326 "void main()\n" 7327 "{\n" 7328 " vec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n" 7329 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n" 7330 "\n" 7331 " discard;\n" 7332 "}\n"; 7333 7334 /* Vertex postions for "full screen" quad, defined as a triangle strip */ 7335 static const GLfloat m_vertex_buffer_data[] = { 7336 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */ 7337 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */ 7338 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */ 7339 1.0f, 1.0f, 0.0f, 1.0f, /* right top */ 7340 }; 7341 7342 /* Result of BuildProgram operation */ 7343 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */ 7344 7345 /* Add all tested texture shapes */ 7346 int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth())); 7347 m_texture_shape_definitions.push_back( 7348 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY)); 7349 m_texture_shape_definitions.push_back( 7350 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D)); 7351 m_texture_shape_definitions.push_back( 7352 TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP)); 7353 m_texture_shape_definitions.push_back( 7354 TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY)); 7355 7356 /* Prepare buffer with vertex positions of "full screen" quad" */ 7357 glGenBuffers(1, &m_vertex_buffer_id); 7358 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers"); 7359 7360 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id); 7361 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer"); 7362 7363 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW); 7364 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData"); 7365 7366 /* Generate vertex array object */ 7367 glGenVertexArrays(1, &m_vertex_array_object_id); 7368 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays"); 7369 7370 /* Prepare program object */ 7371 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */, 7372 fragment_shader_code, &is_program_correct); 7373 if (false == is_program_correct) 7374 { 7375 return ERROR; 7376 } 7377 7378 /* Done */ 7379 return NO_ERROR; 7380 } 7381 7382 virtual long Cleanup() 7383 { 7384 /* Reset OpenGL state */ 7385 glBindBuffer(GL_ARRAY_BUFFER, 0); 7386 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 7387 glBindTexture(GL_TEXTURE_3D, 0); 7388 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 7389 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); 7390 glBindVertexArray(0); 7391 glUseProgram(0); 7392 7393 /* Delete program */ 7394 if (0 != m_program_id) 7395 { 7396 glDeleteProgram(m_program_id); 7397 m_program_id = 0; 7398 } 7399 7400 /* Delete textures */ 7401 if (0 != m_destination_texture_id) 7402 { 7403 glDeleteTextures(1, &m_destination_texture_id); 7404 m_destination_texture_id = 0; 7405 } 7406 7407 if (0 != m_source_texture_id) 7408 { 7409 glDeleteTextures(1, &m_source_texture_id); 7410 m_source_texture_id = 0; 7411 } 7412 7413 /* Delete vertex array object */ 7414 if (0 != m_vertex_array_object_id) 7415 { 7416 glDeleteVertexArrays(1, &m_vertex_array_object_id); 7417 m_vertex_array_object_id = 0; 7418 } 7419 7420 /* Delete buffer */ 7421 if (0 != m_vertex_buffer_id) 7422 { 7423 glDeleteBuffers(1, &m_vertex_buffer_id); 7424 m_vertex_buffer_id = 0; 7425 } 7426 7427 /* Done */ 7428 return NO_ERROR; 7429 } 7430 7431 virtual long Run() 7432 { 7433 bool result = true; 7434 7435 /* For each shape */ 7436 for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin(); 7437 m_texture_shape_definitions.end() != it; ++it) 7438 { 7439 const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type); 7440 7441 /* Prepare "source" and "destination" textures */ 7442 GLU_EXPECT_NO_ERROR( 7443 CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id), 7444 "Create2DR8UIDestinationTexture"); 7445 GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id), 7446 "Create2DR8UISourceTexture"); 7447 7448 /* Copy texture data with imageLoad() and imageStore() operations */ 7449 CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers); 7450 7451 /* Compare "source" and "destination" textures */ 7452 if (false == 7453 CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type)) 7454 { 7455 const char* texture_type = ""; 7456 switch (it->m_type) 7457 { 7458 case GL_TEXTURE_2D_ARRAY: 7459 texture_type = "2d array"; 7460 break; 7461 case GL_TEXTURE_3D: 7462 texture_type = "3d"; 7463 break; 7464 case GL_TEXTURE_CUBE_MAP: 7465 texture_type = "Cube map"; 7466 break; 7467 case GL_TEXTURE_CUBE_MAP_ARRAY: 7468 texture_type = "Cube map array"; 7469 break; 7470 } 7471 7472 m_context.getTestContext().getLog() 7473 << tcu::TestLog::Message 7474 << "Copy with imageLoad and imageStore failed for texture type: " << texture_type 7475 << ". Source and destination textures are different" << tcu::TestLog::EndMessage; 7476 7477 result = false; 7478 } 7479 7480 /* Destroy "source" and "destination" textures */ 7481 glDeleteTextures(1, &m_destination_texture_id); 7482 glDeleteTextures(1, &m_source_texture_id); 7483 7484 m_destination_texture_id = 0; 7485 m_source_texture_id = 0; 7486 } 7487 7488 if (false == result) 7489 { 7490 return ERROR; 7491 } 7492 7493 /* Done */ 7494 return NO_ERROR; 7495 } 7496 7497private: 7498 /* Private methods */ 7499 7500 /** Binds a texture to user-specified image unit and update relevant sampler uniform 7501 * 7502 * @param program_id Program object id 7503 * @param texture_id Texture id 7504 * @param image_unit Index of image unit 7505 * @param layer Index of layer bound to unit 7506 * @param uniform_name Name of image uniform 7507 **/ 7508 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer, 7509 const char* uniform_name) 7510 { 7511 static const GLint invalid_uniform_location = -1; 7512 GLint image_uniform_location = 0; 7513 7514 /* Get uniform location */ 7515 image_uniform_location = glGetUniformLocation(program_id, uniform_name); 7516 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation"); 7517 if (invalid_uniform_location == image_uniform_location) 7518 { 7519 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__); 7520 } 7521 7522 /* Bind texture to image unit */ 7523 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE, 7524 GL_RGBA8); 7525 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture"); 7526 7527 /* Set uniform to image unit */ 7528 glUniform1i(image_uniform_location, image_unit); 7529 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 7530 } 7531 7532 /** Compare two 2D R8UI textures 7533 * 7534 * @param left_texture_id Id of "left" texture object 7535 * @param right_texture_id Id of "right" texture object 7536 * @param edge Length of texture edge 7537 * @param n_layers Number of layers to compare 7538 * @param type Type of texture 7539 * 7540 * @return true when texture data is found identical, false otherwise 7541 **/ 7542 bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers, 7543 GLenum type) 7544 { 7545 static const GLuint n_components = 4; /* RGBA */ 7546 const GLuint texture_data_size = edge * edge * n_layers * n_components; 7547 7548 /* Storage for texture data */ 7549 std::vector<GLubyte> left_texture_data; 7550 std::vector<GLubyte> right_texture_data; 7551 7552 ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data); 7553 ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data); 7554 7555 /* Compare texels */ 7556 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size)); 7557 } 7558 7559 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations 7560 * 7561 * @param destination_texture_id Id of "destination" texture object 7562 * @param source_texture_id Id of "source" texture object 7563 * @param n_layers Number of layers 7564 **/ 7565 void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers) 7566 { 7567 for (GLuint layer = 0; layer < n_layers; ++layer) 7568 { 7569 CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer); 7570 } 7571 } 7572 7573 /** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations 7574 * 7575 * @param destination_texture_id Id of "destination" texture object 7576 * @param source_texture_id Id of "source" texture object 7577 * @param layer Index of layer 7578 **/ 7579 void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer) 7580 { 7581 /* Uniform names */ 7582 static const char* const destination_image_uniform_name = "u_destination_image"; 7583 static const char* const source_image_uniform_name = "u_source_image"; 7584 7585 /* Attribute name */ 7586 static const char* const position_attribute_name = "vs_in_position"; 7587 7588 /* Attribute location and invalid value */ 7589 static const GLint invalid_attribute_location = -1; 7590 GLint position_attribute_location = 0; 7591 7592 /* Set current program */ 7593 glUseProgram(m_program_id); 7594 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram"); 7595 7596 /* Bind vertex array object */ 7597 glBindVertexArray(m_vertex_array_object_id); 7598 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray"); 7599 7600 /* Bind buffer with quad vertex positions */ 7601 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id); 7602 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer"); 7603 7604 /* Set up vertex attribute array for position attribute */ 7605 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name); 7606 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation"); 7607 if (invalid_attribute_location == position_attribute_location) 7608 { 7609 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__, 7610 __LINE__); 7611 } 7612 7613 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */, 7614 0 /* stride */, 0 /* pointer */); 7615 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer"); 7616 7617 glEnableVertexAttribArray(position_attribute_location); 7618 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray"); 7619 7620 /* Set up textures as source and destination image samplers */ 7621 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer, 7622 destination_image_uniform_name); 7623 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name); 7624 7625 /* Execute draw */ 7626 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */); 7627 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 7628 } 7629 7630 /** Creates RGBA8 texture of given type and fills it with zeros 7631 * 7632 * @param edge Edge of created texture 7633 * @param n_elements Number of elements in texture array 7634 * @param target Target of created texture 7635 * @param out_texture_id Id of created texture, not modified if operation fails 7636 * 7637 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 7638 **/ 7639 GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id) 7640 { 7641 /* Constasts to calculate texture size */ 7642 static const GLuint n_components = 4; /* RGBA */ 7643 const GLuint layer_size = edge * edge * n_components; 7644 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target); 7645 const GLuint texture_size = layer_size * n_layers; 7646 7647 /* Prepare storage for texture data */ 7648 std::vector<GLubyte> texture_data; 7649 texture_data.resize(texture_size); 7650 7651 /* Set all texels */ 7652 for (GLuint i = 0; i < texture_size; ++i) 7653 { 7654 texture_data[i] = 0; 7655 } 7656 7657 /* Create texture */ 7658 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id); 7659 } 7660 7661 /** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa] 7662 * 7663 * @param edge Edge of created texture 7664 * @param n_elements Number of elements in texture array 7665 * @param target Target of created texture 7666 * @param out_texture_id Id of created texture, not modified if operation fails 7667 * 7668 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 7669 **/ 7670 GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id) 7671 { 7672 /* Constants to calculate texture size */ 7673 static const GLuint n_components = 4; /* RGBA */ 7674 const GLuint layer_size = edge * edge * n_components; 7675 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target); 7676 const GLuint texture_size = layer_size * n_layers; 7677 7678 /* Value of texel */ 7679 GLubyte texel[4] = { 0, 0, 0, 0xaa }; 7680 7681 /* Prepare storage for texture data */ 7682 std::vector<GLubyte> texture_data; 7683 texture_data.resize(texture_size); 7684 7685 /* Set all texels */ 7686 for (GLuint layer = 0; layer < n_layers; ++layer) 7687 { 7688 const GLuint layer_offset = layer_size * layer; 7689 7690 texel[2] = static_cast<GLubyte>(layer); 7691 7692 for (GLuint y = 0; y < edge; ++y) 7693 { 7694 const GLuint line_offset = y * edge * n_components + layer_offset; 7695 7696 texel[1] = static_cast<GLubyte>(y); 7697 7698 for (GLuint x = 0; x < edge; ++x) 7699 { 7700 const GLuint texel_offset = x * n_components + line_offset; 7701 texel[0] = static_cast<GLubyte>(x); 7702 7703 for (GLuint component = 0; component < n_components; ++component) 7704 { 7705 texture_data[texel_offset + component] = texel[component]; 7706 } 7707 } 7708 } 7709 } 7710 7711 /* Create texture */ 7712 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id); 7713 } 7714 7715 /** Creates RGBA8 texture of given type and fills it provided data 7716 * 7717 * @param edge Edge of created texture 7718 * @param n_elements Number of elements in texture array 7719 * @param target Target of created texture 7720 * @param texture_data Texture data 7721 * @param out_texture_id Id of created texture, not modified if operation fails 7722 * 7723 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 7724 **/ 7725 GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte>& texture_data, 7726 GLuint& out_texture_id) 7727 { 7728 GLenum err = 0; 7729 GLuint texture_id = 0; 7730 7731 /* Generate texture */ 7732 glGenTextures(1, &texture_id); 7733 err = glGetError(); 7734 if (GL_NO_ERROR != err) 7735 { 7736 return err; 7737 } 7738 7739 /* Bind texture */ 7740 glBindTexture(target, texture_id); 7741 err = glGetError(); 7742 if (GL_NO_ERROR != err) 7743 { 7744 glDeleteTextures(1, &texture_id); 7745 return err; 7746 } 7747 7748 /* Allocate storage and fill texture */ 7749 if (GL_TEXTURE_CUBE_MAP != target) 7750 { 7751 glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA, 7752 GL_UNSIGNED_BYTE, &texture_data[0]); 7753 } 7754 else 7755 { 7756 const GLuint n_components = 4; 7757 const GLuint layer_size = edge * edge * n_components; 7758 7759 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA, 7760 GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]); 7761 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA, 7762 GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]); 7763 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA, 7764 GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]); 7765 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA, 7766 GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]); 7767 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA, 7768 GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]); 7769 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA, 7770 GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]); 7771 } 7772 err = glGetError(); 7773 if (GL_NO_ERROR != err) 7774 { 7775 glDeleteTextures(1, &texture_id); 7776 return err; 7777 } 7778 7779 /* Make texture complete */ 7780 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0); 7781 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0); 7782 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 7783 err = glGetError(); 7784 if (GL_NO_ERROR != err) 7785 { 7786 glDeleteTextures(1, &texture_id); 7787 return err; 7788 } 7789 7790 /* Set out_texture_id */ 7791 out_texture_id = texture_id; 7792 7793 /* Done */ 7794 return GL_NO_ERROR; 7795 } 7796 7797 /** Extracts texture data 7798 * 7799 * @param texture_id Id of texture object 7800 * @param edge Length of texture edge 7801 * @param n_layers Number of layers 7802 * @param target Target of texture 7803 * @param texture_data Extracted texture data 7804 **/ 7805 void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target, 7806 std::vector<GLubyte>& texture_data) 7807 { 7808 static const GLuint n_components = 4; /* RGBA */ 7809 const GLuint texture_data_size = edge * edge * n_layers * n_components; 7810 7811 /* Alocate memory for texture data */ 7812 texture_data.resize(texture_data_size); 7813 7814 /* Bind texture */ 7815 glBindTexture(target, texture_id); 7816 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 7817 7818 /* Get data */ 7819 if (GL_TEXTURE_CUBE_MAP != target) 7820 { 7821 glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); 7822 } 7823 else 7824 { 7825 const GLuint layer_size = edge * edge * n_components; 7826 7827 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]); 7828 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]); 7829 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]); 7830 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]); 7831 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]); 7832 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]); 7833 } 7834 7835 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 7836 } 7837 7838 /** Get number of layers per single element for given type of texture 7839 * 7840 * @param target Target of texture 7841 * 7842 * @return Number of layers 7843 **/ 7844 GLuint GetLayersPerElement(GLenum target) 7845 { 7846 switch (target) 7847 { 7848 case GL_TEXTURE_2D_ARRAY: 7849 case GL_TEXTURE_3D: 7850 return 1; 7851 case GL_TEXTURE_CUBE_MAP: 7852 case GL_TEXTURE_CUBE_MAP_ARRAY: 7853 return 6; 7854 default: 7855 throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__); 7856 } 7857 } 7858 7859 /** Get total number of layers in texture of given type and number of array elements 7860 * 7861 * @param n_elements Number of elements in texture array 7862 * @param target Target of texture 7863 * 7864 * @return Number of layers 7865 **/ 7866 GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target) 7867 { 7868 return GetLayersPerElement(target) * n_elements; 7869 } 7870}; 7871 7872/** Test "imageLoad() and imageStore() for incomplete textures" description follows. 7873 * 7874 * Load from incomplete textures should return 0. 7875 * Store to incomplete textures should be ignored. 7876 * 7877 * Steps: 7878 * - create two incomplete textures: "incomplete_source" and 7879 * "incomplete_destination", 7880 * - create two complete textures: "complete_source" and 7881 * "complete_destination", 7882 * - fill all textures with unique values, 7883 * - prepare program that will: 7884 * * load texel from "incomplete_source" and store its value to 7885 * "complete_destination", 7886 * * load texel from "complete_source" and store its value to 7887 * "incomplete_destination". 7888 * - bind textures to corresponding image uniforms 7889 * - execute program for all texels, 7890 * - verify that "incomplete_destination" was not modified and 7891 * "complete_destination" is filled with zeros. 7892 * 7893 * Texture is considered incomplete when it has enabled mipmaping (see below) 7894 * and does not have all mipmap levels defined. But for the case of Image 7895 * accessing, it is considered invalid if it is mipmap-incomplete and the 7896 * level is different to the base level (base-incomplete). 7897 * 7898 * Creation of incomplete texture: 7899 * - generate and bind texture object id, 7900 * - call TexImage2D with <level>: 0, 7901 * - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make 7902 * sure, it should be initial value), 7903 * - set GL_TEXTURE_BASE_LEVEL parameter to 0. 7904 * - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width, 7905 * height)). 7906 * 7907 * Creation of complete texture: 7908 * - generate and bind texture object id, 7909 * - call TexImage2D with <level>: 0, 7910 * - set GL_TEXTURE_BASE_LEVEL parameter to 0. 7911 * - set GL_TEXTURE_MAX_LEVEL parameter to 0. 7912 * 7913 * Binding: 7914 * - Set level == base_level for complete destinations. 7915 * - Set level != base_level for incomplete destinations that are using 7916 * mipmap-incomplete textures. 7917 * 7918 * Test with 2D 64x64 RGBA8 textures. 7919 * 7920 * Program should consist of vertex and fragment shader. Vertex shader should 7921 * pass vertex position through. Fragment shader should do imageLoad() and 7922 * imageStore() operations at coordinates gl_FragCoord. 7923 **/ 7924class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase 7925{ 7926private: 7927 /* Constants */ 7928 /* Magic numbers that will identify textures, which will be used as their 7929 * texel value. 7930 */ 7931 static const GLubyte m_complete_destination_magic_number = 0x11; 7932 static const GLubyte m_complete_source_magic_number = 0x22; 7933 static const GLubyte m_incomplete_destination_magic_number = 0x33; 7934 static const GLubyte m_incomplete_source_magic_number = 0x44; 7935 7936 /* Texture edge */ 7937 GLuint m_texture_edge; 7938 7939 /* Fields */ 7940 GLuint m_complete_destination_texture_id; 7941 GLuint m_complete_source_texture_id; 7942 GLuint m_incomplete_destination_texture_id; 7943 GLuint m_incomplete_source_texture_id; 7944 GLuint m_program_id; 7945 GLuint m_vertex_array_object_id; 7946 GLuint m_vertex_buffer_id; 7947 7948public: 7949 /* Constructor */ 7950 ImageLoadStoreIncompleteTexturesTest() 7951 : m_texture_edge(0) 7952 , m_complete_destination_texture_id(0) 7953 , m_complete_source_texture_id(0) 7954 , m_incomplete_destination_texture_id(0) 7955 , m_incomplete_source_texture_id(0) 7956 , m_program_id(0) 7957 , m_vertex_array_object_id(0) 7958 , m_vertex_buffer_id(0) 7959 { 7960 /* Nothing to be done here */ 7961 } 7962 7963 /* Methods inherited from SubcaseBase */ 7964 virtual long Setup() 7965 { 7966 /* Shaders code */ 7967 const char* const vertex_shader_code = "#version 400 core\n" 7968 "#extension GL_ARB_shader_image_load_store : require\n" 7969 "\n" 7970 "precision highp float;\n" 7971 "\n" 7972 "in vec4 vs_in_position;\n" 7973 "\n" 7974 "void main()\n" 7975 "{\n" 7976 " gl_Position = vs_in_position;\n" 7977 "}\n"; 7978 7979 const char* const fragment_shader_code = 7980 "#version 400 core\n" 7981 "#extension GL_ARB_shader_image_load_store : require\n" 7982 "\n" 7983 "precision highp float;\n" 7984 "\n" 7985 "layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n" 7986 "layout(rgba8) readonly uniform image2D u_complete_source_image;\n" 7987 "layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n" 7988 "layout(rgba8) readonly uniform image2D u_incomplete_source_image;\n" 7989 "\n" 7990 "void main()\n" 7991 "{\n" 7992 " vec4 complete_loaded_color = imageLoad (u_complete_source_image, ivec2(gl_FragCoord));\n" 7993 " vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n" 7994 7995 " imageStore(u_complete_destination_image,\n" 7996 " ivec2(gl_FragCoord),\n" 7997 " incomplete_loaded_color);\n" 7998 " imageStore(u_incomplete_destination_image,\n" 7999 " ivec2(gl_FragCoord),\n" 8000 " complete_loaded_color);\n" 8001 "\n" 8002 " discard;\n" 8003 "}\n"; 8004 8005 /* Vertex postions for "full screen" quad, made with triangle strip */ 8006 static const GLfloat m_vertex_buffer_data[] = { 8007 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */ 8008 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */ 8009 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */ 8010 1.0f, 1.0f, 0.0f, 1.0f, /* right top */ 8011 }; 8012 8013 /* Result of BuildProgram operation */ 8014 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */ 8015 8016 /* Clean previous error */ 8017 glGetError(); 8018 8019 m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth())); 8020 8021 /* Prepare textures */ 8022 GLU_EXPECT_NO_ERROR( 8023 Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id), 8024 "Create2DRGBA8CompleteTexture"); 8025 GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id), 8026 "Create2DRGBA8CompleteTexture"); 8027 GLU_EXPECT_NO_ERROR( 8028 Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id), 8029 "Create2DRGBA8IncompleteTexture"); 8030 GLU_EXPECT_NO_ERROR( 8031 Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id), 8032 "Create2DRGBA8IncompleteTexture"); 8033 8034 /* Prepare buffer with vertex positions of "full screen" quad" */ 8035 glGenBuffers(1, &m_vertex_buffer_id); 8036 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers"); 8037 8038 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id); 8039 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer"); 8040 8041 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW); 8042 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData"); 8043 8044 /* Generate vertex array object */ 8045 glGenVertexArrays(1, &m_vertex_array_object_id); 8046 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays"); 8047 8048 /* Prepare program object */ 8049 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */, 8050 fragment_shader_code, &is_program_correct); 8051 8052 if (false == is_program_correct) 8053 { 8054 return ERROR; 8055 } 8056 8057 /* Done */ 8058 return NO_ERROR; 8059 } 8060 8061 virtual long Cleanup() 8062 { 8063 /* Reset OpenGL state */ 8064 glBindBuffer(GL_ARRAY_BUFFER, 0); 8065 glBindTexture(GL_TEXTURE_2D, 0); 8066 glBindVertexArray(0); 8067 glUseProgram(0); 8068 8069 /* Delete program */ 8070 if (0 != m_program_id) 8071 { 8072 glDeleteProgram(m_program_id); 8073 m_program_id = 0; 8074 } 8075 8076 /* Delete textures */ 8077 if (0 != m_complete_destination_texture_id) 8078 { 8079 glDeleteTextures(1, &m_complete_destination_texture_id); 8080 m_complete_destination_texture_id = 0; 8081 } 8082 8083 if (0 != m_complete_source_texture_id) 8084 { 8085 glDeleteTextures(1, &m_complete_source_texture_id); 8086 m_complete_source_texture_id = 0; 8087 } 8088 8089 if (0 != m_incomplete_destination_texture_id) 8090 { 8091 glDeleteTextures(1, &m_incomplete_destination_texture_id); 8092 m_incomplete_destination_texture_id = 0; 8093 } 8094 8095 if (0 != m_incomplete_source_texture_id) 8096 { 8097 glDeleteTextures(1, &m_incomplete_source_texture_id); 8098 m_incomplete_source_texture_id = 0; 8099 } 8100 8101 /* Delete vertex array object */ 8102 if (0 != m_vertex_array_object_id) 8103 { 8104 glDeleteVertexArrays(1, &m_vertex_array_object_id); 8105 m_vertex_array_object_id = 0; 8106 } 8107 8108 /* Delete buffer */ 8109 if (0 != m_vertex_buffer_id) 8110 { 8111 glDeleteBuffers(1, &m_vertex_buffer_id); 8112 m_vertex_buffer_id = 0; 8113 } 8114 8115 /* Done */ 8116 return NO_ERROR; 8117 } 8118 8119 virtual long Run() 8120 { 8121 bool result = true; 8122 8123 /* Copy textures data with imageLoad() and imageStore() operations */ 8124 Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id, 8125 m_complete_source_texture_id, m_incomplete_source_texture_id); 8126 8127 glMemoryBarrier(GL_ALL_BARRIER_BITS); 8128 8129 /* Verify that store to "incomplete destination" was ignored */ 8130 if (true == 8131 CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number)) 8132 { 8133 m_context.getTestContext().getLog() 8134 << tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture" 8135 << tcu::TestLog::EndMessage; 8136 8137 result = false; 8138 } 8139 8140 /* Verify that load from "incomplete source" returned 0 */ 8141 if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id)) 8142 { 8143 m_context.getTestContext().getLog() 8144 << tcu::TestLog::Message 8145 << "Problem with imageLoad, operation returned non 0 result for incomplete texture" 8146 << tcu::TestLog::EndMessage; 8147 8148 result = false; 8149 } 8150 8151 if (false == result) 8152 { 8153 return ERROR; 8154 } 8155 8156 /* Done */ 8157 return NO_ERROR; 8158 } 8159 8160private: 8161 /* Private methods */ 8162 8163 /** Bind texture to image unit and sets image uniform to that unit 8164 * 8165 * @param program_id Program object id 8166 * @param texture_id Texture id 8167 * @param level Texture level 8168 * @param image_unit Index of image unit 8169 * @param uniform_name Name of image uniform 8170 **/ 8171 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit, const char* uniform_name) 8172 { 8173 /* Uniform location and invalid value */ 8174 static const GLint invalid_uniform_location = -1; 8175 GLint image_uniform_location = 0; 8176 8177 /* Get uniform location */ 8178 image_uniform_location = glGetUniformLocation(program_id, uniform_name); 8179 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation"); 8180 if (invalid_uniform_location == image_uniform_location) 8181 { 8182 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__); 8183 } 8184 8185 /* Bind texture to image unit */ 8186 glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8); 8187 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture"); 8188 8189 /* Set uniform to image unit */ 8190 glUniform1i(image_uniform_location, image_unit); 8191 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 8192 } 8193 8194 /** Check if texture is filled with black color, zeros 8195 * 8196 * @param texture_id Id of texture object 8197 * 8198 * @return true when texture is fully black, false otherwise 8199 **/ 8200 bool CheckIfTextureIsBlack(GLuint texture_id) 8201 { 8202 /* Constants to calculate size of texture */ 8203 static const GLuint n_components = 4; /* RGBA */ 8204 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components; 8205 8206 /* Storage for texture data */ 8207 std::vector<GLubyte> black_texture_data; 8208 std::vector<GLubyte> texture_data; 8209 8210 /* Allocate memory */ 8211 black_texture_data.resize(texture_data_size); 8212 texture_data.resize(texture_data_size); 8213 8214 /* Set all texels to black */ 8215 for (GLuint i = 0; i < texture_data_size; ++i) 8216 { 8217 black_texture_data[i] = 0; 8218 } 8219 8220 /* Bind texture */ 8221 glBindTexture(GL_TEXTURE_2D, texture_id); 8222 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 8223 8224 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); 8225 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 8226 8227 /* Compare texels */ 8228 return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size)); 8229 } 8230 8231 /** Check if texture was modified 8232 * 8233 * @param texture_id Id of texture object 8234 * @param nagic_number Magic number that was to create texture 8235 * 8236 * @return true if texture contents match expected values, false otherwise 8237 **/ 8238 bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number) 8239 { 8240 /* Constants to calculate size of texture */ 8241 static const GLuint n_components = 4; /* RGBA */ 8242 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components; 8243 8244 /* Storage for texture data */ 8245 std::vector<GLubyte> expected_texture_data; 8246 std::vector<GLubyte> texture_data; 8247 8248 /* Allocate memory */ 8249 expected_texture_data.resize(texture_data_size); 8250 texture_data.resize(texture_data_size); 8251 8252 /* Prepare expected texels */ 8253 for (GLuint y = 0; y < m_texture_edge; ++y) 8254 { 8255 const GLuint line_offset = y * m_texture_edge * n_components; 8256 8257 for (GLuint x = 0; x < m_texture_edge; ++x) 8258 { 8259 const GLuint texel_offset = x * n_components + line_offset; 8260 8261 SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), 8262 magic_number); 8263 } 8264 } 8265 8266 /* Bind texture */ 8267 glBindTexture(GL_TEXTURE_2D, texture_id); 8268 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 8269 8270 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); 8271 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 8272 8273 /* Compare texels, true when textures are different */ 8274 return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size)); 8275 } 8276 8277 /** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations 8278 * 8279 * @param complete_destination_texture_id Id of "complete destination" texture object 8280 * @param incomplete_destination_texture_id Id of "incomplete destination" texture object 8281 * @param complete_source_texture_id Id of "complete source" texture object 8282 * @param incomplete_source_texture_id Id of "incomplete source" texture object 8283 **/ 8284 void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id, 8285 GLuint complete_source_texture_id, GLuint incomplete_source_texture_id) 8286 { 8287 /* Uniform names */ 8288 static const char* const complete_destination_image_uniform_name = "u_complete_destination_image"; 8289 static const char* const complete_source_image_uniform_name = "u_complete_source_image"; 8290 static const char* const incomplete_destination_image_uniform_name = "u_incomplete_destination_image"; 8291 static const char* const incomplete_source_image_uniform_name = "u_incomplete_source_image"; 8292 8293 /* Attribute name */ 8294 static const char* const position_attribute_name = "vs_in_position"; 8295 8296 /* Attribute location and invalid value */ 8297 static const GLint invalid_attribute_location = -1; 8298 GLint position_attribute_location = 0; 8299 8300 /* Set current program */ 8301 glUseProgram(m_program_id); 8302 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram"); 8303 8304 /* Bind vertex array object */ 8305 glBindVertexArray(m_vertex_array_object_id); 8306 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray"); 8307 8308 /* Bind buffer with quad vertex positions */ 8309 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id); 8310 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer"); 8311 8312 /* Setup position attribute */ 8313 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name); 8314 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation"); 8315 if (invalid_attribute_location == position_attribute_location) 8316 { 8317 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__, 8318 __LINE__); 8319 } 8320 8321 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0); 8322 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer"); 8323 8324 glEnableVertexAttribArray(position_attribute_location); 8325 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray"); 8326 8327 /* Setup textures as source and destination images */ 8328 BindTextureToImage(m_program_id, complete_destination_texture_id, 8329 0 /* texture level */, 0 /* image_unit */, 8330 complete_destination_image_uniform_name); 8331 BindTextureToImage(m_program_id, complete_source_texture_id, 8332 0 /* texture level */, 1 /* image_unit */, 8333 complete_source_image_uniform_name); 8334 BindTextureToImage(m_program_id, incomplete_destination_texture_id, 8335 2 /* texture level */, 2 /* image_unit */, 8336 incomplete_destination_image_uniform_name); 8337 BindTextureToImage(m_program_id, incomplete_source_texture_id, 8338 2 /* texture level */, 3 /* image_unit */, 8339 incomplete_source_image_uniform_name); 8340 8341 /* Execute draw */ 8342 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */); 8343 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 8344 } 8345 8346 /** Create complete 2D RGBA8 texture. 8347 * 8348 * @param magic_number Magic number of texture 8349 * @param out_texture_id Id of created texture, not modified if operation fails 8350 * 8351 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 8352 **/ 8353 GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint& out_texture_id) 8354 { 8355 /* Constants to calculate size of texture */ 8356 static const GLuint n_components = 4; /* RGBA */ 8357 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components; 8358 8359 /* Error code */ 8360 GLenum err = 0; 8361 8362 /* Texture id */ 8363 GLuint texture_id = 0; 8364 8365 /* Prepare storage for texture data */ 8366 std::vector<GLubyte> texture_data; 8367 texture_data.resize(texture_data_size); 8368 8369 /* Prepare texture data */ 8370 for (GLuint y = 0; y < m_texture_edge; ++y) 8371 { 8372 const GLuint line_offset = y * m_texture_edge * n_components; 8373 8374 for (GLuint x = 0; x < m_texture_edge; ++x) 8375 { 8376 const GLuint texel_offset = x * n_components + line_offset; 8377 8378 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number); 8379 } 8380 } 8381 8382 /* Generate texture */ 8383 glGenTextures(1, &texture_id); 8384 err = glGetError(); 8385 if (GL_NO_ERROR != err) 8386 { 8387 return err; 8388 } 8389 8390 /* Bind texture */ 8391 glBindTexture(GL_TEXTURE_2D, texture_id); 8392 err = glGetError(); 8393 if (GL_NO_ERROR != err) 8394 { 8395 glDeleteTextures(1, &texture_id); 8396 return err; 8397 } 8398 8399 /* Allocate storage and fill texture */ 8400 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA, 8401 GL_UNSIGNED_BYTE, &texture_data[0]); 8402 err = glGetError(); 8403 if (GL_NO_ERROR != err) 8404 { 8405 glDeleteTextures(1, &texture_id); 8406 return err; 8407 } 8408 8409 /* Make texture complete */ 8410 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 8411 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 8412 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 8413 err = glGetError(); 8414 if (GL_NO_ERROR != err) 8415 { 8416 glDeleteTextures(1, &texture_id); 8417 return err; 8418 } 8419 8420 /* Set out_texture_id */ 8421 out_texture_id = texture_id; 8422 8423 /* Done */ 8424 return GL_NO_ERROR; 8425 } 8426 8427 /** Create incomplete 2D RGBA8 texture 8428 * 8429 * @param magic_number Magic number of texture 8430 * @param out_texture_id Id of created texture, not modified if operation fails 8431 * 8432 * @return GL_NO_ERROR if operation was successful, GL error code otherwise 8433 **/ 8434 GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint& out_texture_id) 8435 { 8436 /* Constants to calculate size of texture */ 8437 static const GLuint n_components = 4; /* RGBA */ 8438 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components; 8439 8440 /* Error code */ 8441 GLenum err = 0; 8442 8443 /* Texture id */ 8444 GLuint texture_id = 0; 8445 8446 /* Prepare storage for texture data */ 8447 std::vector<GLubyte> texture_data; 8448 texture_data.resize(texture_data_size); 8449 8450 /* Prepare texture data */ 8451 for (GLuint y = 0; y < m_texture_edge; ++y) 8452 { 8453 const GLuint line_offset = y * m_texture_edge * n_components; 8454 8455 for (GLuint x = 0; x < m_texture_edge; ++x) 8456 { 8457 const GLuint texel_offset = x * n_components + line_offset; 8458 8459 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number); 8460 } 8461 } 8462 8463 /* Generate texture */ 8464 glGenTextures(1, &texture_id); 8465 err = glGetError(); 8466 if (GL_NO_ERROR != err) 8467 { 8468 return err; 8469 } 8470 8471 /* Bind texture */ 8472 glBindTexture(GL_TEXTURE_2D, texture_id); 8473 err = glGetError(); 8474 if (GL_NO_ERROR != err) 8475 { 8476 glDeleteTextures(1, &texture_id); 8477 return err; 8478 } 8479 8480 /* Allocate storage and fill texture */ 8481 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA, 8482 GL_UNSIGNED_BYTE, &texture_data[0]); 8483 err = glGetError(); 8484 if (GL_NO_ERROR != err) 8485 { 8486 glDeleteTextures(1, &texture_id); 8487 return err; 8488 } 8489 8490 /* Make texture incomplete */ 8491 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 8492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7); 8493 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); 8494 err = glGetError(); 8495 if (GL_NO_ERROR != err) 8496 { 8497 glDeleteTextures(1, &texture_id); 8498 return err; 8499 } 8500 8501 /* Set out_texture_id */ 8502 out_texture_id = texture_id; 8503 8504 /* Done */ 8505 return GL_NO_ERROR; 8506 } 8507 8508 /** Prepare "unique" texels. 8509 * Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc]. 8510 * 8511 * @param texel Storage of texel 8512 * @param x_coordinate X coordiante of texel 8513 * @param y_coordinate Y coordinate of texel 8514 * @param magic_number Magic number of texture 8515 **/ 8516 void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number) 8517 { 8518 texel[0] = x_coordinate; 8519 texel[1] = y_coordinate; 8520 texel[2] = magic_number; 8521 texel[3] = 0xcc; 8522 } 8523}; 8524 8525/** Test "Refer to the same image unit using multiple uniforms", description follows. 8526 * 8527 * Steps: 8528 * - prepare program object, see details below, 8529 * - prepare 2D R32I texture, width should be equal to the number of image 8530 * uniforms used by program object, height should be 2, fill first row with 8531 * unique values, fill second row with zeros, 8532 * - bind texture to first image unit, 8533 * - set all image uniforms to first image unit, 8534 * - execute program for a single vertex, 8535 * - verify that: 8536 * - values in first row were negated, 8537 * - values from first row were copied to second row, 8538 * 8539 * Repeat steps to test all shader stages that support at least 2 image 8540 * uniforms. 8541 * 8542 * Program has to contain all necessary shader stages. Use boilerplate shaders 8543 * for shader stages that are not important for the test. 8544 * 8545 * Tested shader stage should: 8546 * - Use as many different image formats as possible, image formats compatible 8547 * with R32I: 8548 * * rg16f 8549 * * r11f_g11f_b10f 8550 * * r32f 8551 * * rgb10_a2ui 8552 * * rgba8ui 8553 * * rg16ui 8554 * * r32ui 8555 * * rgba8i 8556 * * rg16i 8557 * * r32i 8558 * * rgb10_a2 8559 * * rgba8 8560 * * rg16 8561 * * rgba8_snorm 8562 * * rg16_snorm. 8563 * - Declare maximum allowed number of image uniforms, 8564 * 8565 * layout(format) uniform gimage2D u_image; 8566 * 8567 * where <format> is selected image format, <gimage2D> is type of 2D image 8568 * compatible with <format> and <u_image> is unique name of uniform. 8569 * Note that image uniforms cannot be declared as array, due to different image 8570 * formats. Therefore separate uniforms have to be used. 8571 * - Include following code snippet: 8572 * for (int i = 0; i < gl_Max*ImageUniforms; ++i) 8573 * { 8574 * vec row_1_coord(i,0); 8575 * vec row_2_coord(i,1); 8576 * 8577 * row_1_value = imageLoad(u_image[i], row_1_coord); 8578 * imageStore(u_image[i], row_1_coord, -row_1_value); 8579 * imageStore(u_image[i], row_2_coord, row_1_value); 8580 * } 8581 * where gl_Max*ImageUniforms is the constant corresponding to tested shader 8582 * stage. 8583 **/ 8584class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase 8585{ 8586private: 8587 /* Types */ 8588 /** Details of image format 8589 * 8590 **/ 8591 struct imageFormatDetails 8592 { 8593 typedef bool (*verificationRoutine)(GLint, GLint, GLint); 8594 8595 const char* m_image_format; 8596 const char* m_image_type; 8597 const char* m_color_type; 8598 GLenum m_image_unit_format; 8599 verificationRoutine m_verification_routine; 8600 }; 8601 8602 template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)> 8603 struct Masks 8604 { 8605 /** Get mask of bits used to store in bit-field 8606 * 8607 * @return Mask 8608 **/ 8609 static inline T RawMask() 8610 { 8611 static const T mask = ValueMask() << OFFSET; 8612 8613 return mask; 8614 } 8615 8616 /** Get mask of bits used to store value. 8617 * 8618 * @return Mask 8619 **/ 8620 static inline T ValueMask() 8621 { 8622 static const T mask = (1 << SIZE) - 1; 8623 8624 return mask; 8625 } 8626 8627 /** Get offset. 8628 * 8629 * @return offset 8630 **/ 8631 static inline T Offset() 8632 { 8633 return OFFSET; 8634 } 8635 }; 8636 8637 template <typename T, GLuint SIZE, GLuint OFFSET> 8638 struct Masks<T, SIZE, OFFSET, false> 8639 { 8640 /** Get mask of bits used to store in bit-field 8641 * 8642 * @return Mask 8643 **/ 8644 static inline T RawMask() 8645 { 8646 DE_ASSERT(DE_FALSE && "Shouldn't be called"); 8647 return 0; 8648 } 8649 8650 /** Get mask of bits used to store value. 8651 * 8652 * @return Mask 8653 **/ 8654 static inline T ValueMask() 8655 { 8656 DE_ASSERT(DE_FALSE && "Shouldn't be called"); 8657 return 0; 8658 } 8659 8660 /** Get offset. 8661 * 8662 * @return offset 8663 **/ 8664 static inline T Offset() 8665 { 8666 DE_ASSERT(DE_FALSE && "Shouldn't be called"); 8667 return 0; 8668 } 8669 }; 8670 8671 /** Template class for accessing integer values stored in bit-fields 8672 * 8673 **/ 8674 template <typename T, GLuint SIZE, GLuint OFFSET> 8675 class Integer 8676 { 8677 public: 8678 /** Constructor 8679 * 8680 **/ 8681 Integer(T raw) : m_raw(raw) 8682 { 8683 } 8684 8685 /** Extract value from bit-field 8686 * 8687 * @return Value 8688 **/ 8689 T Get() const 8690 { 8691 const T mask = Masks<T, SIZE, OFFSET>::RawMask(); 8692 8693 const T bits = m_raw & mask; 8694 const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset(); 8695 8696 return result; 8697 } 8698 8699 /** Extract value from bit-field and negate it 8700 * 8701 * @return Negated value 8702 **/ 8703 T GetNegated() const 8704 { 8705 const T mask = Masks<T, SIZE, OFFSET>::ValueMask(); 8706 const T value = Get(); 8707 8708 return Clamp((~value) + 1) & mask; 8709 } 8710 8711 T Clamp(T n) const 8712 { 8713 const bool isUnsigned = (T(0) < T(-1)); 8714 const T min = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1))); 8715 const T max = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L); 8716 const T x = n > max ? max : n; 8717 return x < min ? min : x; 8718 } 8719 8720 private: 8721 T m_raw; 8722 }; 8723 8724 /* Enums */ 8725 /** Shader stage identification 8726 * 8727 **/ 8728 enum shaderStage 8729 { 8730 fragmentShaderStage = 2, 8731 geometryShaderStage = 4, 8732 tesselationControlShaderStage = 8, 8733 tesselationEvalutaionShaderStage = 16, 8734 vertexShaderStage = 32, 8735 }; 8736 8737 /** Test result 8738 * 8739 **/ 8740 enum testResult 8741 { 8742 testFailed = -1, 8743 testNotSupported = 1, 8744 testPassed = 0 8745 }; 8746 8747 /* Constants */ 8748 static const GLint m_min_required_image_uniforms = 2; 8749 8750 /* Fields */ 8751 GLuint m_program_to_test_fs_stage_id; 8752 GLuint m_program_to_test_gs_stage_id; 8753 GLuint m_program_to_test_tcs_stage_id; 8754 GLuint m_program_to_test_tes_stage_id; 8755 GLuint m_program_to_test_vs_stage_id; 8756 GLuint m_texture_to_test_fs_stage_id; 8757 GLuint m_texture_to_test_gs_stage_id; 8758 GLuint m_texture_to_test_tcs_stage_id; 8759 GLuint m_texture_to_test_tes_stage_id; 8760 GLuint m_texture_to_test_vs_stage_id; 8761 GLuint m_vertex_array_object_id; 8762 8763public: 8764 /* Constructor */ 8765 ImageLoadStoreMultipleUniformsTest() 8766 : m_program_to_test_fs_stage_id(0) 8767 , m_program_to_test_gs_stage_id(0) 8768 , m_program_to_test_tcs_stage_id(0) 8769 , m_program_to_test_tes_stage_id(0) 8770 , m_program_to_test_vs_stage_id(0) 8771 , m_texture_to_test_fs_stage_id(0) 8772 , m_texture_to_test_gs_stage_id(0) 8773 , m_texture_to_test_tcs_stage_id(0) 8774 , m_texture_to_test_tes_stage_id(0) 8775 , m_texture_to_test_vs_stage_id(0) 8776 , m_vertex_array_object_id(0) 8777 { 8778 /* Nothing to be done here */ 8779 } 8780 8781 /* Methods inherited from SubcaseBase */ 8782 virtual long Setup() 8783 { 8784 /* Prepare programs */ 8785 m_program_to_test_fs_stage_id = buildProgramToTestShaderStage(fragmentShaderStage); 8786 m_program_to_test_gs_stage_id = buildProgramToTestShaderStage(geometryShaderStage); 8787 m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage); 8788 m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage); 8789 m_program_to_test_vs_stage_id = buildProgramToTestShaderStage(vertexShaderStage); 8790 8791 /* Prepare textures */ 8792 m_texture_to_test_fs_stage_id = createTextureToTestShaderStage(fragmentShaderStage); 8793 m_texture_to_test_gs_stage_id = createTextureToTestShaderStage(geometryShaderStage); 8794 m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage); 8795 m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage); 8796 m_texture_to_test_vs_stage_id = createTextureToTestShaderStage(vertexShaderStage); 8797 8798 /* Generate vertex array object */ 8799 glGenVertexArrays(1, &m_vertex_array_object_id); 8800 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays"); 8801 8802 /* Bind vertex array object */ 8803 glBindVertexArray(m_vertex_array_object_id); 8804 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray"); 8805 8806 /* Set vertices number for patches */ 8807 glPatchParameteri(GL_PATCH_VERTICES, 1); 8808 8809 /* Done */ 8810 return NO_ERROR; 8811 } 8812 8813 virtual long Cleanup() 8814 { 8815 glUseProgram(0); 8816 8817 /* Delete programs */ 8818 if (0 != m_program_to_test_fs_stage_id) 8819 { 8820 glDeleteProgram(m_program_to_test_fs_stage_id); 8821 m_program_to_test_fs_stage_id = 0; 8822 } 8823 8824 if (0 != m_program_to_test_gs_stage_id) 8825 { 8826 glDeleteProgram(m_program_to_test_gs_stage_id); 8827 m_program_to_test_gs_stage_id = 0; 8828 } 8829 8830 if (0 != m_program_to_test_tcs_stage_id) 8831 { 8832 glDeleteProgram(m_program_to_test_tcs_stage_id); 8833 m_program_to_test_tcs_stage_id = 0; 8834 } 8835 8836 if (0 != m_program_to_test_tes_stage_id) 8837 { 8838 glDeleteProgram(m_program_to_test_tes_stage_id); 8839 m_program_to_test_tes_stage_id = 0; 8840 } 8841 8842 if (0 != m_program_to_test_vs_stage_id) 8843 { 8844 glDeleteProgram(m_program_to_test_vs_stage_id); 8845 m_program_to_test_vs_stage_id = 0; 8846 } 8847 8848 /* Delete textures */ 8849 if (0 != m_texture_to_test_fs_stage_id) 8850 { 8851 glDeleteTextures(1, &m_texture_to_test_fs_stage_id); 8852 m_texture_to_test_fs_stage_id = 0; 8853 } 8854 8855 if (0 != m_texture_to_test_gs_stage_id) 8856 { 8857 glDeleteTextures(1, &m_texture_to_test_gs_stage_id); 8858 m_texture_to_test_gs_stage_id = 0; 8859 } 8860 8861 if (0 != m_texture_to_test_tcs_stage_id) 8862 { 8863 glDeleteTextures(1, &m_texture_to_test_tcs_stage_id); 8864 m_texture_to_test_tcs_stage_id = 0; 8865 } 8866 8867 if (0 != m_texture_to_test_tes_stage_id) 8868 { 8869 glDeleteTextures(1, &m_texture_to_test_tes_stage_id); 8870 m_texture_to_test_tes_stage_id = 0; 8871 } 8872 8873 if (0 != m_texture_to_test_vs_stage_id) 8874 { 8875 glDeleteTextures(1, &m_texture_to_test_vs_stage_id); 8876 m_texture_to_test_vs_stage_id = 0; 8877 } 8878 8879 /* Delete vertex array object id */ 8880 if (0 != m_vertex_array_object_id) 8881 { 8882 glDeleteVertexArrays(1, &m_vertex_array_object_id); 8883 m_vertex_array_object_id = 0; 8884 } 8885 8886 /* Done */ 8887 return NO_ERROR; 8888 } 8889 8890 virtual long Run() 8891 { 8892 bool result = true; 8893 8894 if (testFailed == testShaderStage(fragmentShaderStage)) 8895 { 8896 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with fragment shader stage!" 8897 << tcu::TestLog::EndMessage; 8898 8899 result = false; 8900 } 8901 8902 if (testFailed == testShaderStage(geometryShaderStage)) 8903 { 8904 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with geometry shader stage!" 8905 << tcu::TestLog::EndMessage; 8906 8907 result = false; 8908 } 8909 8910 if (testFailed == testShaderStage(tesselationControlShaderStage)) 8911 { 8912 m_context.getTestContext().getLog() << tcu::TestLog::Message 8913 << "Problems with tesselation control shader stage!" 8914 << tcu::TestLog::EndMessage; 8915 8916 result = false; 8917 } 8918 8919 if (testFailed == testShaderStage(tesselationEvalutaionShaderStage)) 8920 { 8921 m_context.getTestContext().getLog() << tcu::TestLog::Message 8922 << "Problems with tesselation evaluation shader stage!" 8923 << tcu::TestLog::EndMessage; 8924 8925 result = false; 8926 } 8927 8928 if (testFailed == testShaderStage(vertexShaderStage)) 8929 { 8930 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with vertex shader stage!" 8931 << tcu::TestLog::EndMessage; 8932 8933 result = false; 8934 } 8935 8936 if (false == result) 8937 { 8938 return ERROR; 8939 } 8940 8941 /* Done */ 8942 return NO_ERROR; 8943 } 8944 8945private: 8946 /* Static routines */ 8947 /** Provide image format details for given index 8948 * 8949 * @param index Index 8950 * @param out_details Image format detail instance 8951 **/ 8952 static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails& out_details) 8953 { 8954 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = { 8955 "r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger 8956 }; 8957 8958 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = { 8959 { "rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort> }, 8960 { "r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F, 8961 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> }, 8962 { "r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint> }, 8963 { "rgb10_a2", "image2D", "vec4", GL_RGB10_A2, 8964 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> }, 8965 { "rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> }, 8966 { "rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> }, 8967 { "rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM, 8968 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte> }, 8969 { "rg16_snorm", "image2D", "vec4", GL_RG16_SNORM, 8970 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort> }, 8971 { "rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI, 8972 ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint> }, 8973 { "rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI, 8974 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint> }, 8975 { "rg16ui", "uimage2D", "uvec4", GL_RG16UI, 8976 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint> }, 8977 { "r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger }, 8978 { "rgba8i", "iimage2D", "ivec4", GL_RGBA8I, 8979 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint> }, 8980 { "rg16i", "iimage2D", "ivec4", GL_RG16I, 8981 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint> } 8982 }; 8983 8984 static const GLuint n_imageUniformFormatDetails = 8985 sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails); 8986 8987 if (n_imageUniformFormatDetails <= index) 8988 { 8989 out_details = default_format_details; 8990 } 8991 else 8992 { 8993 out_details = format_details[index]; 8994 } 8995 } 8996 8997 /** Write name of image uniform at given index to output stream 8998 * 8999 * @param stream Output stream 9000 * @param index Index 9001 **/ 9002 static void writeImageUniformNameToStream(std::ostream& stream, GLuint index) 9003 { 9004 /* u_image_0 */ 9005 stream << "u_image_" << index; 9006 } 9007 9008 /** Write name of variable used to store value loaded from image at given index to output stream 9009 * 9010 * @param stream Output stream 9011 * @param index Index 9012 **/ 9013 static void writeLoadedValueVariableNameToStream(std::ostream& stream, GLuint index) 9014 { 9015 /* loaded_value_0 */ 9016 stream << "loaded_value_" << index; 9017 } 9018 9019 /** Write name of variable used to store coordinate of texel at given row to output stream 9020 * 9021 * @param stream Output stream 9022 * @param index Index of image uniform 9023 * @param row Row of image 9024 **/ 9025 static void writeCoordinatesVariableNameToStream(std::ostream& stream, GLuint index, GLuint row) 9026 { 9027 /* row_0_coordinates_0 */ 9028 stream << "row_" << row << "_coordinates_" << index; 9029 } 9030 9031 struct imageUniformDeclaration 9032 { 9033 imageUniformDeclaration(GLuint index) : m_index(index) 9034 { 9035 } 9036 9037 GLuint m_index; 9038 }; 9039 9040 /** Write declaration of image uniform at given index to output stream 9041 * 9042 * @param stream Output stream 9043 * @param imageUniformDeclaration Declaration details 9044 * 9045 * @return stream 9046 **/ 9047 friend std::ostream& operator<<(std::ostream& stream, const imageUniformDeclaration& declaration) 9048 { 9049 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details; 9050 getImageUniformDeclarationDetails(declaration.m_index, format_details); 9051 9052 /* layout(r32f) uniform image2D u_image_0; */ 9053 stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " "; 9054 9055 ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index); 9056 9057 stream << ";"; 9058 9059 return stream; 9060 } 9061 9062 struct imageLoadCall 9063 { 9064 imageLoadCall(GLuint index) : m_index(index) 9065 { 9066 } 9067 9068 GLuint m_index; 9069 }; 9070 9071 /* Stream operators */ 9072 /** Write code that execute imageLoad routine for image at given index to output stream 9073 * 9074 * @param stream Output stream 9075 * @param load imageLoad call details 9076 * 9077 * @return stream 9078 **/ 9079 friend std::ostream& operator<<(std::ostream& stream, const imageLoadCall& load) 9080 { 9081 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details; 9082 getImageUniformDeclarationDetails(load.m_index, format_details); 9083 9084 /* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */ 9085 stream << format_details.m_color_type << " "; 9086 9087 writeLoadedValueVariableNameToStream(stream, load.m_index); 9088 9089 stream << " = imageLoad("; 9090 9091 writeImageUniformNameToStream(stream, load.m_index); 9092 9093 stream << ", "; 9094 9095 writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */); 9096 9097 stream << ");"; 9098 9099 return stream; 9100 } 9101 9102 struct imageStoreCall 9103 { 9104 imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row) 9105 { 9106 } 9107 9108 GLuint m_index; 9109 GLuint m_row; 9110 }; 9111 9112 /** Write code that execute imageStore to image at given index to output stream 9113 * 9114 * @param stream Output stream 9115 * @param store imageStore call details 9116 * 9117 * @return stream 9118 **/ 9119 friend std::ostream& operator<<(std::ostream& stream, const imageStoreCall& store) 9120 { 9121 /* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */ 9122 stream << "imageStore("; 9123 9124 writeImageUniformNameToStream(stream, store.m_index); 9125 9126 stream << ", "; 9127 9128 writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row); 9129 9130 if (0 == store.m_row) 9131 { 9132 stream << ", -"; 9133 } 9134 else 9135 { 9136 stream << ", "; 9137 } 9138 9139 writeLoadedValueVariableNameToStream(stream, store.m_index); 9140 stream << ");"; 9141 9142 return stream; 9143 } 9144 9145 struct coordinatesVariableDeclaration 9146 { 9147 coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row) 9148 { 9149 } 9150 GLuint m_index; 9151 GLuint m_row; 9152 }; 9153 9154 /** Write declaration of variable for coordinate at given row to output stream 9155 * 9156 * @param stream Output stream 9157 * @param declaration Declaration details 9158 * 9159 * @return stream 9160 **/ 9161 friend std::ostream& operator<<(std::ostream& stream, const coordinatesVariableDeclaration& declaration) 9162 { 9163 stream << "const ivec2 "; 9164 9165 writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row); 9166 9167 stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");"; 9168 9169 return stream; 9170 } 9171 9172 /* Methods */ 9173 /** Build program to test specified shader stage 9174 * 9175 * Throws exception in case of any failure 9176 * 9177 * @param stage Stage id 9178 * 9179 * @return Program id 9180 **/ 9181 GLuint buildProgramToTestShaderStage(shaderStage stage) 9182 { 9183 static const char* const boilerplate_fragment_shader_code = 9184 "#version 400 core\n" 9185 "#extension GL_ARB_shader_image_load_store : require\n" 9186 "\n" 9187 "precision highp float;\n" 9188 "\n" 9189 "void main()\n" 9190 "{\n" 9191 " discard;\n" 9192 "}\n"; 9193 9194 static const char* const boilerplate_tesselation_evaluation_shader_code = 9195 "#version 400 core\n" 9196 "#extension GL_ARB_shader_image_load_store : require\n" 9197 "\n" 9198 "precision highp float;\n" 9199 "\n" 9200 "layout(quads, equal_spacing, ccw) in;\n" 9201 "\n" 9202 "void main()\n" 9203 "{\n" 9204 "\n" 9205 "}\n"; 9206 9207 static const char* const boilerplate_vertex_shader_code = 9208 "#version 400 core\n" 9209 "#extension GL_ARB_shader_image_load_store : require\n" 9210 "\n" 9211 "precision highp float;\n" 9212 "\n" 9213 "layout(location = 0) in vec4 i_position;\n" 9214 "\n" 9215 "void main()\n" 9216 "{\n" 9217 " gl_Position = i_position;\n" 9218 "}\n"; 9219 9220 const char* fragment_shader_code = boilerplate_fragment_shader_code; 9221 const char* geometry_shader_code = 0; 9222 bool is_program_built = true; 9223 GLuint program_object_id = 0; 9224 const char* tesselation_control_shader_code = 0; 9225 const char* tesselation_evaluation_shader_code = 0; 9226 std::string tested_shader_stage_code; 9227 const char* vertex_shader_code = boilerplate_vertex_shader_code; 9228 9229 /* Get source code for tested shader stage */ 9230 prepareShaderForTestedShaderStage(stage, tested_shader_stage_code); 9231 9232 if (true == tested_shader_stage_code.empty()) 9233 { 9234 return 0; 9235 } 9236 9237 /* Set up source code for all required stages */ 9238 switch (stage) 9239 { 9240 case fragmentShaderStage: 9241 fragment_shader_code = tested_shader_stage_code.c_str(); 9242 break; 9243 9244 case geometryShaderStage: 9245 geometry_shader_code = tested_shader_stage_code.c_str(); 9246 break; 9247 9248 case tesselationControlShaderStage: 9249 tesselation_control_shader_code = tested_shader_stage_code.c_str(); 9250 tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code; 9251 break; 9252 9253 case tesselationEvalutaionShaderStage: 9254 tesselation_evaluation_shader_code = tested_shader_stage_code.c_str(); 9255 break; 9256 9257 case vertexShaderStage: 9258 vertex_shader_code = tested_shader_stage_code.c_str(); 9259 break; 9260 9261 default: 9262 TCU_FAIL("Invalid shader stage"); 9263 } 9264 9265 /* Build program */ 9266 program_object_id = 9267 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code, 9268 geometry_shader_code, fragment_shader_code, &is_program_built); 9269 9270 /* Check if program was built */ 9271 if (false == is_program_built) 9272 { 9273 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__); 9274 } 9275 9276 /* Done */ 9277 return program_object_id; 9278 } 9279 9280 /** Create texture to test given shader stage 9281 * 9282 * Throws exception in case of any failure 9283 * 9284 * @param stage Stage id 9285 * 9286 * @return Texture id 9287 **/ 9288 GLuint createTextureToTestShaderStage(shaderStage stage) 9289 { 9290 GLenum error = glGetError(); 9291 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage); 9292 GLuint texture_id = 0; 9293 std::vector<GLint> texture_data; 9294 9295 const GLsizei height = 2; 9296 const GLsizei width = max_image_uniforms; 9297 9298 if (m_min_required_image_uniforms > max_image_uniforms) 9299 { 9300 return 0; 9301 } 9302 9303 /* Generate texture id */ 9304 glGenTextures(1, &texture_id); 9305 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures"); 9306 9307 /* Bind texture */ 9308 glBindTexture(GL_TEXTURE_2D, texture_id); 9309 error = glGetError(); 9310 if (GL_NO_ERROR != error) 9311 { 9312 glDeleteTextures(1, &texture_id); 9313 GLU_EXPECT_NO_ERROR(error, "BindTexture"); 9314 } 9315 9316 /* Prepare storage for texture data */ 9317 texture_data.resize(width * height); 9318 for (GLint i = 0; i < max_image_uniforms; ++i) 9319 { 9320 texture_data[i] = getExpectedValue(i); 9321 texture_data[i + width] = 0; 9322 } 9323 9324 /* Create first level of texture */ 9325 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT, 9326 &texture_data[0]); 9327 error = glGetError(); 9328 if (GL_NO_ERROR != error) 9329 { 9330 glDeleteTextures(1, &texture_id); 9331 GLU_EXPECT_NO_ERROR(error, "TexImage2D"); 9332 } 9333 9334 /* Make texture complete */ 9335 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); 9336 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 9337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 9338 error = glGetError(); 9339 if (GL_NO_ERROR != error) 9340 { 9341 glDeleteTextures(1, &texture_id); 9342 GLU_EXPECT_NO_ERROR(error, "TexParameteri"); 9343 } 9344 9345 /* Done */ 9346 return texture_id; 9347 } 9348 9349 /** Get value of texel for image at given index 9350 * 9351 * @param index Index of image uniform 9352 * 9353 * @return Value of texel 9354 **/ 9355 GLint getExpectedValue(GLint index) 9356 { 9357 // To fix denorm issues with r32f, rg16f and r11f_g11f_b10f 9358 // we set one bit in the exponent of each component of those pixel format 9359 return 0x40104200 + index; 9360 } 9361 9362 /** Get name of uniform at given index 9363 * 9364 * @param index Index of uniform 9365 * @param out_name Name of uniform 9366 **/ 9367 void getImageUniformName(GLuint index, std::string& out_name) 9368 { 9369 std::stringstream stream; 9370 9371 writeImageUniformNameToStream(stream, index); 9372 9373 out_name = stream.str(); 9374 } 9375 9376 /** Get maximum number of image uniforms allowed for given shader stage 9377 * 9378 * @param stage Stage id 9379 * 9380 * @return Maximum allowed image uniforms 9381 **/ 9382 GLint getMaximumImageUniformsForStage(shaderStage stage) 9383 { 9384 GLint max_image_uniforms = 0; 9385 GLenum pname = 0; 9386 9387 switch (stage) 9388 { 9389 case fragmentShaderStage: 9390 pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS; 9391 break; 9392 9393 case geometryShaderStage: 9394 pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS; 9395 break; 9396 9397 case tesselationControlShaderStage: 9398 pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS; 9399 break; 9400 9401 case tesselationEvalutaionShaderStage: 9402 pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS; 9403 break; 9404 9405 case vertexShaderStage: 9406 pname = GL_MAX_VERTEX_IMAGE_UNIFORMS; 9407 break; 9408 9409 default: 9410 TCU_FAIL("Invalid shader stage"); 9411 } 9412 9413 glGetIntegerv(pname, &max_image_uniforms); 9414 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv"); 9415 9416 return max_image_uniforms; 9417 } 9418 9419 /** Prepare source for tested shader stage 9420 * 9421 * @param stage Stage id 9422 * @param out_code Source code 9423 **/ 9424 void prepareShaderForTestedShaderStage(shaderStage stage, std::string& out_code) 9425 { 9426 GLint max_image_uniforms = getMaximumImageUniformsForStage(stage); 9427 const char* stage_specific_layout = ""; 9428 const char* stage_specific_predicate = "true"; 9429 std::stringstream stream; 9430 9431 if (m_min_required_image_uniforms > max_image_uniforms) 9432 { 9433 return; 9434 } 9435 9436 /* Expected result follows 9437 * 9438 * #version 400 core 9439 * #extension GL_ARB_shader_image_load_store : require 9440 * 9441 * precision highp float; 9442 * 9443 * stage_specific_layout goes here 9444 * 9445 * Uniform declarations go here 9446 * 9447 * void main() 9448 * { 9449 * const ivec2 row_0_coordinates(0, 0); 9450 * const ivec2 row_1_coordinates(0, 1); 9451 * 9452 * For each index <0, GL_MAX_*_IMAGE_UNIFORMS> 9453 * 9454 * vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates); 9455 * 9456 * imageStore(u_image_0, row_0_coordinates, -loaded_value_0); 9457 * imageStore(u_image_0, row_1_coordinates, loaded_value_0); 9458 * } 9459 */ 9460 9461 /* Get piece of code specific for stage */ 9462 switch (stage) 9463 { 9464 case fragmentShaderStage: 9465 break; 9466 9467 case geometryShaderStage: 9468 stage_specific_layout = "layout(points) in;\n" 9469 "layout(points, max_vertices = 1) out;\n" 9470 "\n"; 9471 break; 9472 9473 case tesselationControlShaderStage: 9474 stage_specific_layout = "layout(vertices = 4) out;\n" 9475 "\n"; 9476 stage_specific_predicate = "gl_InvocationID == 0"; 9477 break; 9478 9479 case tesselationEvalutaionShaderStage: 9480 stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n" 9481 "\n"; 9482 break; 9483 9484 case vertexShaderStage: 9485 break; 9486 9487 default: 9488 TCU_FAIL("Invalid shader stage"); 9489 } 9490 9491 /* Preamble */ 9492 stream << "#version 400 core\n" 9493 "#extension GL_ARB_shader_image_load_store : require\n" 9494 "\n" 9495 "precision highp float;\n" 9496 "\n" 9497 << stage_specific_layout; 9498 9499 /* Image uniforms declarations */ 9500 for (GLint i = 0; i < max_image_uniforms; ++i) 9501 { 9502 stream << imageUniformDeclaration(i) << "\n"; 9503 } 9504 9505 /* Main opening */ 9506 stream << "\n" 9507 "void main()\n" 9508 "{\n"; 9509 9510 stream << " if (" << stage_specific_predicate << ")\n"; 9511 stream << " {\n"; 9512 9513 /* imageLoad and imageStores for each uniform */ 9514 for (GLint i = 0; i < max_image_uniforms; ++i) 9515 { 9516 stream << " " << coordinatesVariableDeclaration(i, 0) << "\n" 9517 << " " << coordinatesVariableDeclaration(i, 1) << "\n" 9518 << "\n" 9519 << " " << imageLoadCall(i) << "\n" 9520 << "\n" 9521 << " " << imageStoreCall(i, 0) << "\n" 9522 << " " << imageStoreCall(i, 1) << "\n"; 9523 9524 if (max_image_uniforms > i + 1) 9525 { 9526 stream << "\n"; 9527 } 9528 } 9529 9530 stream << " }\n"; 9531 9532 /* Main closing */ 9533 stream << "}\n\n"; 9534 9535 /* Done */ 9536 out_code = stream.str(); 9537 } 9538 9539 /** Test given shader stage 9540 * 9541 * @param stage Stage id 9542 * 9543 * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms; 9544 * testFailed when test result is negative; 9545 * m_test_passed when test result is positive; 9546 **/ 9547 testResult testShaderStage(shaderStage stage) 9548 { 9549 std::string image_uniform_name; 9550 static const GLint invalid_uniform_location = -1; 9551 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage); 9552 GLenum primitive_mode = GL_POINTS; 9553 GLuint program_id = 0; 9554 testResult result = testPassed; 9555 std::vector<GLint> texture_data; 9556 GLuint texture_id = 0; 9557 9558 static const GLuint height = 2; 9559 const GLuint width = max_image_uniforms; 9560 9561 const GLuint positive_value_index = width; 9562 static const GLuint negated_value_index = 0; 9563 9564 if (m_min_required_image_uniforms > max_image_uniforms) 9565 { 9566 return testNotSupported; 9567 } 9568 9569 /* Select program and texture ids for given stage */ 9570 switch (stage) 9571 { 9572 case fragmentShaderStage: 9573 program_id = m_program_to_test_fs_stage_id; 9574 texture_id = m_texture_to_test_fs_stage_id; 9575 break; 9576 9577 case geometryShaderStage: 9578 program_id = m_program_to_test_gs_stage_id; 9579 texture_id = m_texture_to_test_gs_stage_id; 9580 break; 9581 9582 case tesselationControlShaderStage: 9583 primitive_mode = GL_PATCHES; 9584 program_id = m_program_to_test_tcs_stage_id; 9585 texture_id = m_texture_to_test_tcs_stage_id; 9586 break; 9587 9588 case tesselationEvalutaionShaderStage: 9589 primitive_mode = GL_PATCHES; 9590 program_id = m_program_to_test_tes_stage_id; 9591 texture_id = m_texture_to_test_tes_stage_id; 9592 break; 9593 9594 case vertexShaderStage: 9595 program_id = m_program_to_test_vs_stage_id; 9596 texture_id = m_texture_to_test_vs_stage_id; 9597 break; 9598 9599 default: 9600 TCU_FAIL("Invalid shader stage"); 9601 } 9602 9603 /* Set program */ 9604 glUseProgram(program_id); 9605 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram"); 9606 9607 /* Bind texture to image units */ 9608 for (GLint i = 0; i < max_image_uniforms; ++i) 9609 { 9610 imageFormatDetails format_details; 9611 getImageUniformDeclarationDetails(i, format_details); 9612 9613 glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */, 9614 GL_READ_WRITE, format_details.m_image_unit_format); 9615 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture"); 9616 } 9617 9618 /* Set all image uniforms to corresponding image units */ 9619 for (GLint i = 0; i < max_image_uniforms; ++i) 9620 { 9621 /* Get name */ 9622 getImageUniformName(i, image_uniform_name); 9623 9624 /* Get location */ 9625 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str()); 9626 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation"); 9627 9628 if (invalid_uniform_location == image_uniform_location) 9629 { 9630 throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__, 9631 __LINE__); 9632 } 9633 9634 /* Set uniform value */ 9635 glUniform1i(image_uniform_location, i /* image_unit */); 9636 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 9637 } 9638 9639 /* Execute draw */ 9640 glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */); 9641 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 9642 9643 glMemoryBarrier(GL_ALL_BARRIER_BITS); 9644 9645 texture_data.resize(width * height); 9646 9647 /* Get texture data */ 9648 glBindTexture(GL_TEXTURE_2D, texture_id); 9649 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 9650 9651 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]); 9652 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 9653 9654 /* Verify each image uniform */ 9655 for (GLint i = 0; i < max_image_uniforms; ++i) 9656 { 9657 imageFormatDetails format_details; 9658 getImageUniformDeclarationDetails(i, format_details); 9659 9660 if (false == 9661 format_details.m_verification_routine(getExpectedValue(i), texture_data[positive_value_index + i], 9662 texture_data[negated_value_index + i])) 9663 { 9664 m_context.getTestContext().getLog() 9665 << tcu::TestLog::Message << "Invalid result!" 9666 << " Image format: " << format_details.m_image_format << " Original value: " 9667 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i) 9668 << " Copied value: " 9669 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) 9670 << texture_data[positive_value_index + i] << " Negated value: " 9671 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) 9672 << texture_data[negated_value_index + i] << tcu::TestLog::EndMessage; 9673 9674 result = testFailed; 9675 } 9676 } 9677 9678 /* Done */ 9679 return result; 9680 } 9681 9682 /** Verifies if original_value, positive_value and negated_value match 9683 * 9684 * @tparam T Type used during verification process, it should match float values by size 9685 * 9686 * @param original_value Original value of texel, used when creating a texture 9687 * @param positive_value Value stored by shader as read 9688 * @param negated_value Value stored by shader after negation 9689 * 9690 * @return true if values match, false otherwise 9691 **/ 9692 template <typename T> 9693 static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value) 9694 { 9695 if (original_value != positive_value) 9696 { 9697 return false; 9698 } 9699 9700 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */ 9701 static const GLuint sign_bit_index = sizeof(T) * 8 - 1; /* 7, 15, 31 */ 9702 static const T sign_bit_mask = 1 << sign_bit_index; /* 0x80.. */ 9703 static const T sign_bit_inv_mask = (T)~sign_bit_mask; /* 0x7f.. */ 9704 9705 const T* positive_elements = (T*)&positive_value; 9706 const T* negated_elements = (T*)&negated_value; 9707 9708 for (GLuint i = 0; i < n_elements; ++i) 9709 { 9710 const T positive_element = positive_elements[i]; 9711 const T negated_element = negated_elements[i]; 9712 9713 const T positive_sign_bit = positive_element & sign_bit_mask; 9714 const T negated_sign_bit = negated_element & sign_bit_mask; 9715 9716 const T positive_data = positive_element & sign_bit_inv_mask; 9717 const T negated_data = negated_element & sign_bit_inv_mask; 9718 9719 /* Compare data bits */ 9720 if (positive_data != negated_data) 9721 { 9722 return false; 9723 } 9724 9725 /* Verify that sign bit is inverted */ 9726 if (positive_sign_bit == negated_sign_bit) 9727 { 9728 return false; 9729 } 9730 } 9731 9732 return true; 9733 } 9734 9735 /** Verifies if original_value, positive_value and negated_value match 9736 * 9737 * @tparam T Type used during verification process, it should match float values by size 9738 * 9739 * @param original_value Original value of texel, used when creating a texture 9740 * @param positive_value Value stored by shader as read 9741 * @param negated_value Value stored by shader after negation 9742 * 9743 * @return true if values match, false otherwise 9744 **/ 9745 template <typename T> 9746 static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value) 9747 { 9748 if (original_value != positive_value) 9749 { 9750 return false; 9751 } 9752 9753 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */ 9754 9755 const T* positive_elements = (T*)&positive_value; 9756 const T* negated_elements = (T*)&negated_value; 9757 9758 for (GLuint i = 0; i < n_elements; ++i) 9759 { 9760 const T positive_element = positive_elements[i]; 9761 const T negated_element = negated_elements[i]; 9762 9763 /* Compare data bits */ 9764 if (positive_element != -negated_element) 9765 { 9766 return false; 9767 } 9768 } 9769 9770 return true; 9771 } 9772 9773 /** Verifies if original_value, positive_value and negated_value match 9774 * 9775 * @tparam R Number of bits for red channel 9776 * @tparam G Number of bits for green channel 9777 * @tparam B Number of bits for blue channel 9778 * @tparam A Number of bits for alpha channel 9779 * 9780 * @param original_value Original value of texel, used when creating a texture 9781 * @param positive_value Value stored by shader as read 9782 * @param negated_value Value stored by shader after negation 9783 * 9784 * @return true if values match, false otherwise 9785 **/ 9786 template <GLuint R, GLuint G, GLuint B, GLuint A, typename T> 9787 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value) 9788 { 9789 if (original_value != positive_value) 9790 { 9791 return false; 9792 } 9793 9794 Integer<T, R, 0> positive_red(positive_value); 9795 Integer<T, R, 0> negated_red(negated_value); 9796 9797 Integer<T, G, R> positive_green(positive_value); 9798 Integer<T, G, R> negated_green(negated_value); 9799 9800 Integer<T, B, R + G> positive_blue(positive_value); 9801 Integer<T, B, R + G> negated_blue(negated_value); 9802 9803 Integer<T, A, R + G + B> positive_alpha(positive_value); 9804 Integer<T, A, R + G + B> negated_alpha(negated_value); 9805 9806 if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) || 9807 ((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) || 9808 ((0 != G) && (positive_green.GetNegated() != negated_green.Get())) || 9809 ((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get()))) 9810 { 9811 return false; 9812 } 9813 9814 return true; 9815 } 9816 9817 /** Verifies if original_value, positive_value and negated_value match 9818 * 9819 * @param original_value Original value of texel, used when creating a texture 9820 * @param positive_value Value stored by shader as read 9821 * @param negated_value Value stored by shader after negation 9822 * 9823 * @return true if values match, false otherwise 9824 **/ 9825 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value) 9826 { 9827 if (original_value != positive_value) 9828 { 9829 return false; 9830 } 9831 9832 if (positive_value != -negated_value) 9833 { 9834 return false; 9835 } 9836 9837 return true; 9838 } 9839 9840 /** Verifies if original_value, positive_value and negated_value match 9841 * 9842 * @param original_value Original value of texel, used when creating a texture 9843 * @param positive_value Value stored by shader as read 9844 * @param negated_value Value stored by shader after negation 9845 * 9846 * @return true if values match, false otherwise 9847 **/ 9848 template <typename T> 9849 static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value) 9850 { 9851 if (original_value != positive_value) 9852 { 9853 return false; 9854 } 9855 9856 if (0 != negated_value) 9857 { 9858 return false; 9859 } 9860 9861 return true; 9862 } 9863}; 9864 9865/** Test "Early fragment tests" description follows. 9866 * 9867 * BasicGLSLEarlyFragTests verifies that: 9868 * - early z test is applied when enabled, 9869 * - early z test is not applied when disabled. 9870 * 9871 * Proposed modifications: 9872 * - verify that early z test does not discard all fragments when enabled, 9873 * - verify that early stencil test is applied when enabled, 9874 * - verify that early stencil test does not discard all fragments when 9875 * enabled, 9876 * - verify that early stencil test is not applied when disabled. 9877 * 9878 * Steps: 9879 * - prepare 2 programs that store 1.0 at red channel to image in fragment 9880 * shader stage: 9881 * a) one program should enable early fragment tests 9882 * ("layout(early_fragment_tests) in;"), 9883 * b) second program should disable early fragment tests, 9884 * - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL 9885 * depth-stencil attachments, 9886 * - prepare 2D texture 64x64 R32F, 9887 * - enable depth test, 9888 * - verify that early z test is applied when enabled: 9889 * - use program enabling early fragment tests, 9890 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5, 9891 * - fill texture with zeros, 9892 * - bind texture to image uniform, 9893 * - draw "full screen" quad (left bottom corner at -1,-1 and right top 9894 * corner at 1,1) at z: 0.75 9895 * - verify that texture is still filled with zeros, 9896 * - verify that early z test does not discard all fragments: 9897 * - use program enabling early fragment tests, 9898 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5, 9899 * - fill texture with zeros, 9900 * - bind texture to image uniform, 9901 * - draw "full screen" quad at z: 0.25 9902 * - verify that texture is now filled with 1.0, 9903 * -verify that early z test is not applied when disabled: 9904 * - use program disabling early fragment tests, 9905 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5, 9906 * - fill texture with zeros, 9907 * - bind texture to image uniform, 9908 * - draw "full screen" quad at z: 0.75 9909 * - verify that texture is now filled with 1.0. 9910 * - disable depth test 9911 * - enable stencil test 9912 * - verify that early stencil test is applied when enabled: 9913 * - use program enabling early fragment tests, 9914 * - clean frame buffer with color: 0, stencil: 0 and depth 1, 9915 * - fill texture with zeros, 9916 * - set stencil test to: 9917 * - <func> to GL_LESS, 9918 * - <ref> to 128, 9919 * - <mask> 0xffffffff, 9920 * - bind texture to image uniform, 9921 * - draw "full screen" quad at z: 0, 9922 * - verify that texture is still filled with zeros, 9923 * - verify that early stencil test does not discard all fragments: 9924 * - use program enabling early fragment tests, 9925 * - clean frame buffer with color: 0, stencil: 128 and depth 1, 9926 * - fill texture with zeros, 9927 * - set stencil test to: 9928 * - <func> to GL_LESS, 9929 * - <ref> to 0, 9930 * - <mask> 0xffffffff, 9931 * - bind texture to image uniform, 9932 * - draw "full screen" quad at z: 0, 9933 * - verify that texture is now filled with 1.0, 9934 * - verify that early stencil test is not applied when disabled: 9935 * - use program disabling early fragment tests, 9936 * - clean frame buffer with color: 0, stencil: 0 and depth 1, 9937 * - fill texture with zeros, 9938 * - set stencil test to: 9939 * - <func> to GL_LESS, 9940 * - <ref> to 128, 9941 * - <mask> 0xffffffff, 9942 * - bind texture to image uniform, 9943 * - draw "full screen" quad at z: 0, 9944 * - verify that texture is now filled with 1.0 9945 **/ 9946class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase 9947{ 9948private: 9949 /* Constants */ 9950 GLuint m_image_edge; 9951 static const GLint m_invalid_uniform_location = -1; 9952 9953 /* Types */ 9954 /** Store id and uniform locations for a single program object 9955 * 9956 **/ 9957 struct programDetails 9958 { 9959 GLint m_depth_uniform_location; 9960 GLint m_image_uniform_location; 9961 GLuint m_program_id; 9962 9963 programDetails() 9964 : m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location) 9965 , m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location) 9966 , m_program_id(0) 9967 { 9968 /* Nothing to be done here */ 9969 } 9970 }; 9971 9972 /* Fileds */ 9973 /* Storage for texture data */ 9974 std::vector<GLfloat> m_clean_texture_data; 9975 std::vector<GLfloat> m_extracted_texture_data; 9976 9977 /* Program details */ 9978 programDetails m_disabled_early_tests; 9979 programDetails m_enabled_early_tests; 9980 9981 /* Ids of GL objects */ 9982 GLuint m_color_renderbuffer_id; 9983 GLuint m_depth_stencil_renderbuffer_id; 9984 GLuint m_framebuffer_id; 9985 GLuint m_texture_id; 9986 GLuint m_vertex_array_object_id; 9987 9988public: 9989 /* Constructor */ 9990 ImageLoadStoreEarlyFragmentTestsTest() 9991 : m_image_edge(0) 9992 , m_color_renderbuffer_id(0) 9993 , m_depth_stencil_renderbuffer_id(0) 9994 , m_framebuffer_id(0) 9995 , m_texture_id(0) 9996 , m_vertex_array_object_id(0) 9997 { 9998 /* Nothing to be done here */ 9999 } 10000 10001 /* Methods inherited from SubcaseBase */ 10002 virtual long Cleanup() 10003 { 10004 /* Restore defaults */ 10005 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 10006 glBindRenderbuffer(GL_RENDERBUFFER, 0); 10007 glBindTexture(GL_TEXTURE_2D, 0); 10008 glBindVertexArray(0); 10009 glDisable(GL_DEPTH_TEST); 10010 glDisable(GL_STENCIL_TEST); 10011 glUseProgram(0); 10012 10013 /* Delete objects */ 10014 if (0 != m_disabled_early_tests.m_program_id) 10015 { 10016 glDeleteProgram(m_disabled_early_tests.m_program_id); 10017 m_disabled_early_tests.m_program_id = 0; 10018 } 10019 10020 if (0 != m_enabled_early_tests.m_program_id) 10021 { 10022 glDeleteProgram(m_enabled_early_tests.m_program_id); 10023 m_enabled_early_tests.m_program_id = 0; 10024 } 10025 10026 if (0 != m_color_renderbuffer_id) 10027 { 10028 glDeleteRenderbuffers(1, &m_color_renderbuffer_id); 10029 m_color_renderbuffer_id = 0; 10030 } 10031 10032 if (0 != m_depth_stencil_renderbuffer_id) 10033 { 10034 glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id); 10035 m_depth_stencil_renderbuffer_id = 0; 10036 } 10037 10038 if (0 != m_framebuffer_id) 10039 { 10040 glDeleteFramebuffers(1, &m_framebuffer_id); 10041 m_framebuffer_id = 0; 10042 } 10043 10044 if (0 != m_texture_id) 10045 { 10046 glDeleteTextures(1, &m_texture_id); 10047 m_texture_id = 0; 10048 } 10049 10050 if (0 != m_vertex_array_object_id) 10051 { 10052 glDeleteVertexArrays(1, &m_vertex_array_object_id); 10053 m_vertex_array_object_id = 0; 10054 } 10055 10056 /* Done */ 10057 return NO_ERROR; 10058 } 10059 10060 virtual long Run() 10061 { 10062 bool result = true; 10063 10064 /* Bind texture to first image unit */ 10065 glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */, 10066 GL_READ_WRITE, GL_R32F); 10067 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture"); 10068 10069 /* Run tests for depth test */ 10070 if (false == testEarlyZ()) 10071 { 10072 result = false; 10073 } 10074 10075 /* Run tests for stencil test */ 10076 if (false == testEarlyStencil()) 10077 { 10078 result = false; 10079 } 10080 10081 /* Return ERROR if any problem was found */ 10082 if (false == result) 10083 { 10084 return ERROR; 10085 } 10086 10087 /* Done */ 10088 return NO_ERROR; 10089 } 10090 10091 virtual long Setup() 10092 { 10093 m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth())); 10094 10095 /* Prepare storage for texture data */ 10096 m_clean_texture_data.resize(m_image_edge * m_image_edge); 10097 m_extracted_texture_data.resize(m_image_edge * m_image_edge); 10098 10099 /* Prepare programs, framebuffer and texture */ 10100 buildPrograms(); 10101 createFramebuffer(); 10102 createTexture(); 10103 10104 /* Generate vertex array object */ 10105 glGenVertexArrays(1, &m_vertex_array_object_id); 10106 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays"); 10107 10108 /* Bind vertex array object */ 10109 glBindVertexArray(m_vertex_array_object_id); 10110 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray"); 10111 10112 /* Set clear color */ 10113 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 10114 GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor"); 10115 10116 /* Done */ 10117 return NO_ERROR; 10118 } 10119 10120private: 10121 /** Build two programs: with enabled and disabled early fragment tests 10122 * 10123 **/ 10124 void buildPrograms() 10125 { 10126 static const char* const fragment_shader_with_disabled_early_tests = 10127 "#version 400 core\n" 10128 "#extension GL_ARB_shader_image_load_store : require\n" 10129 "\n" 10130 "precision highp float;\n" 10131 "\n" 10132 "layout(r32f) uniform image2D u_image;\n" 10133 "\n" 10134 "void main()\n" 10135 "{\n" 10136 " vec4 color = vec4(1.0, 0, 0, 0);\n" 10137 "\n" 10138 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n" 10139 "\n" 10140 " discard;\n" 10141 "}\n\n"; 10142 10143 static const char* const fragment_shader_with_enabled_early_tests = 10144 "#version 400 core\n" 10145 "#extension GL_ARB_shader_image_load_store : require\n" 10146 "\n" 10147 "precision highp float;\n" 10148 "\n" 10149 "layout(early_fragment_tests) in;\n" 10150 "\n" 10151 "layout(r32f) uniform image2D u_image;\n" 10152 "\n" 10153 "void main()\n" 10154 "{\n" 10155 " vec4 color = vec4(1.0, 0, 0, 0);\n" 10156 "\n" 10157 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n" 10158 "\n" 10159 " discard;\n" 10160 "}\n\n"; 10161 10162 static const char* const geometry_shader_code = "#version 400 core\n" 10163 "#extension GL_ARB_shader_image_load_store : require\n" 10164 "\n" 10165 "precision highp float;\n" 10166 "\n" 10167 "layout(points) in;\n" 10168 "layout(triangle_strip, max_vertices = 4) out;\n" 10169 "\n" 10170 "uniform float u_depth;\n" 10171 "\n" 10172 "void main()\n" 10173 "{\n" 10174 " // Left-bottom\n" 10175 " gl_Position = vec4(-1, -1, u_depth, 1);\n" 10176 " EmitVertex();\n" 10177 "\n" 10178 " // Left-top\n" 10179 " gl_Position = vec4(-1, 1, u_depth, 1);\n" 10180 " EmitVertex();\n" 10181 "\n" 10182 " // Right-bottom\n" 10183 " gl_Position = vec4( 1, -1, u_depth, 1);\n" 10184 " EmitVertex();\n" 10185 "\n" 10186 " // Right-top\n" 10187 " gl_Position = vec4( 1, 1, u_depth, 1);\n" 10188 " EmitVertex();\n" 10189 "}\n\n"; 10190 10191 static const char* const vertex_shader_code = "#version 400 core\n" 10192 "#extension GL_ARB_shader_image_load_store : require\n" 10193 "\n" 10194 "precision highp float;\n" 10195 "\n" 10196 "void main()\n" 10197 "{\n" 10198 "}\n\n"; 10199 10200 prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code, 10201 m_disabled_early_tests); 10202 10203 prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code, 10204 m_enabled_early_tests); 10205 } 10206 10207 /** Fill texture with zeros 10208 * 10209 **/ 10210 void cleanTexture() 10211 { 10212 glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge, 10213 GL_RED, GL_FLOAT, &m_clean_texture_data[0]); 10214 GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D"); 10215 } 10216 10217 /** Create and bind (draw) framebuffer with color and depth-stencil attachments 10218 * 10219 **/ 10220 void createFramebuffer() 10221 { 10222 /* Generate render buffers */ 10223 glGenRenderbuffers(1, &m_color_renderbuffer_id); 10224 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers"); 10225 10226 glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id); 10227 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers"); 10228 10229 /* Generate and bind framebuffer object */ 10230 glGenFramebuffers(1, &m_framebuffer_id); 10231 GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers"); 10232 10233 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id); 10234 GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer"); 10235 10236 /* Prepare color render buffer */ 10237 glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id); 10238 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer"); 10239 10240 glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge); 10241 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage"); 10242 10243 /* Set up color attachment */ 10244 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id); 10245 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer"); 10246 10247 /* Prepare depth-stencil render buffer */ 10248 glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id); 10249 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer"); 10250 10251 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge); 10252 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage"); 10253 10254 /* Set up depth-stencil attachment */ 10255 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 10256 m_depth_stencil_renderbuffer_id); 10257 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer"); 10258 } 10259 10260 /** Create 2D R32F texture 10261 * 10262 **/ 10263 void createTexture() 10264 { 10265 glGenTextures(1, &m_texture_id); 10266 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures"); 10267 10268 glBindTexture(GL_TEXTURE_2D, m_texture_id); 10269 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture"); 10270 10271 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge); 10272 GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D"); 10273 } 10274 10275 /** Extracts red channel from texture and verify if all texels are set to specified value 10276 * 10277 * @param value Expected value 10278 * 10279 * @return true if all texel match expected value, false otherwise 10280 **/ 10281 bool isTextureFilledWithValue(GLfloat value) 10282 { 10283 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]); 10284 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage"); 10285 10286 for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i) 10287 { 10288 if (value != m_extracted_texture_data[i]) 10289 { 10290 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i 10291 << " has invalid value: " << m_extracted_texture_data[i] 10292 << " expected: " << value << tcu::TestLog::EndMessage; 10293 10294 return false; 10295 } 10296 } 10297 10298 return true; 10299 } 10300 10301 /** Build program, extract location of uniforms and store results in programDetails instance 10302 * 10303 * Throws tcu::InternalError if uniforms are inactive 10304 * 10305 * @param fragment_shader_code Source of fragment shader 10306 * @param geometry_shader_code Source of geometry shader 10307 * @param vertex_shader_code Source of vertex shader 10308 * @param out_program_details Instance of programDetails 10309 **/ 10310 void prepareProgramDetails(const char* fragment_shader_code, const char* geometry_shader_code, 10311 const char* vertex_shader_code, programDetails& out_program_details) 10312 { 10313 static const char* const depth_uniform_name = "u_depth"; 10314 static const char* const image_uniform_name = "u_image"; 10315 bool is_program_built = true; 10316 10317 GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code, 10318 fragment_shader_code, &is_program_built); 10319 10320 if (false == is_program_built) 10321 { 10322 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__); 10323 } 10324 10325 /* Get depth uniform location */ 10326 GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name); 10327 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation"); 10328 10329 if (m_invalid_uniform_location == depth_uniform_location) 10330 { 10331 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__); 10332 } 10333 10334 /* Get image uniform location */ 10335 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name); 10336 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation"); 10337 10338 if (m_invalid_uniform_location == image_uniform_location) 10339 { 10340 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__); 10341 } 10342 10343 /* Store results */ 10344 out_program_details.m_depth_uniform_location = depth_uniform_location; 10345 out_program_details.m_image_uniform_location = image_uniform_location; 10346 out_program_details.m_program_id = program_id; 10347 } 10348 10349 /** Test if early fragment stencil test works as expected. 10350 * 10351 * @return true if successful, false otherwise 10352 **/ 10353 bool testEarlyStencil() 10354 { 10355 bool result = true; 10356 10357 glEnable(GL_STENCIL_TEST); 10358 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable"); 10359 10360 glClearDepthf(1.0f); 10361 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf"); 10362 10363 /* verify that early stencil test is applied when enabled */ 10364 { 10365 glUseProgram(m_enabled_early_tests.m_program_id); 10366 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram"); 10367 10368 glClearStencil(0); 10369 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil"); 10370 10371 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 10372 GLU_EXPECT_NO_ERROR(glGetError(), "Clear"); 10373 10374 cleanTexture(); 10375 10376 glStencilFunc(GL_LESS, 128, 0xffffffff); 10377 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc"); 10378 10379 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */); 10380 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 10381 10382 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */); 10383 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f"); 10384 10385 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */); 10386 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 10387 10388 glMemoryBarrier(GL_ALL_BARRIER_BITS); 10389 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier"); 10390 10391 if (false == isTextureFilledWithValue(0.0f)) 10392 { 10393 m_context.getTestContext().getLog() << tcu::TestLog::Message 10394 << "Problem with early stencil test. It is not applied" 10395 << tcu::TestLog::EndMessage; 10396 10397 result = false; 10398 } 10399 } 10400 10401 /* verify that early stencil test does not discard all fragments */ 10402 { 10403 glClearStencil(128); 10404 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil"); 10405 10406 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 10407 GLU_EXPECT_NO_ERROR(glGetError(), "Clear"); 10408 10409 cleanTexture(); 10410 10411 glStencilFunc(GL_LESS, 0, 0xffffffff); 10412 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc"); 10413 10414 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */); 10415 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 10416 10417 glMemoryBarrier(GL_ALL_BARRIER_BITS); 10418 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier"); 10419 10420 if (false == isTextureFilledWithValue(1.0f)) 10421 { 10422 m_context.getTestContext().getLog() 10423 << tcu::TestLog::Message 10424 << "Problem with early stencil test. It discards fragments, that shall be drawn" 10425 << tcu::TestLog::EndMessage; 10426 10427 result = false; 10428 } 10429 } 10430 10431 /* verify that early stencil test is not applied when disabled */ 10432 { 10433 glUseProgram(m_disabled_early_tests.m_program_id); 10434 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram"); 10435 10436 glClearStencil(0); 10437 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil"); 10438 10439 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 10440 GLU_EXPECT_NO_ERROR(glGetError(), "Clear"); 10441 10442 cleanTexture(); 10443 10444 glStencilFunc(GL_LESS, 128, 0xffffffff); 10445 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc"); 10446 10447 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */); 10448 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 10449 10450 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */); 10451 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f"); 10452 10453 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */); 10454 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 10455 10456 glMemoryBarrier(GL_ALL_BARRIER_BITS); 10457 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier"); 10458 10459 if (false == isTextureFilledWithValue(1.0f)) 10460 { 10461 m_context.getTestContext().getLog() << tcu::TestLog::Message 10462 << "Problem with early stencil test. It is applied when disabled" 10463 << tcu::TestLog::EndMessage; 10464 10465 result = false; 10466 } 10467 } 10468 10469 glDisable(GL_STENCIL_TEST); 10470 GLU_EXPECT_NO_ERROR(glGetError(), "Disable"); 10471 10472 /* Done */ 10473 return result; 10474 } 10475 10476 /** Test if early fragment depth test works as expected. 10477 * 10478 * @return true if successful, false otherwise 10479 **/ 10480 bool testEarlyZ() 10481 { 10482 bool result = true; 10483 10484 glEnable(GL_DEPTH_TEST); 10485 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable"); 10486 10487 glClearDepthf(0.5f); 10488 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf"); 10489 10490 glClearStencil(0); 10491 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil"); 10492 10493 /* verify that early z test is applied when enabled */ 10494 { 10495 glUseProgram(m_enabled_early_tests.m_program_id); 10496 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram"); 10497 10498 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 10499 GLU_EXPECT_NO_ERROR(glGetError(), "Clear"); 10500 10501 cleanTexture(); 10502 10503 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */); 10504 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 10505 10506 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */); 10507 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f"); 10508 10509 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */); 10510 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 10511 10512 glMemoryBarrier(GL_ALL_BARRIER_BITS); 10513 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier"); 10514 10515 if (false == isTextureFilledWithValue(0.0f)) 10516 { 10517 m_context.getTestContext().getLog() << tcu::TestLog::Message 10518 << "Problem with early z test. It is not applied" 10519 << tcu::TestLog::EndMessage; 10520 10521 result = false; 10522 } 10523 } 10524 10525 /* verify that early z test does not discard all fragments */ 10526 { 10527 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 10528 GLU_EXPECT_NO_ERROR(glGetError(), "Clear"); 10529 10530 cleanTexture(); 10531 10532 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */); 10533 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 10534 10535 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */); 10536 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f"); 10537 10538 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */); 10539 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 10540 10541 glMemoryBarrier(GL_ALL_BARRIER_BITS); 10542 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier"); 10543 10544 if (false == isTextureFilledWithValue(1.0f)) 10545 { 10546 m_context.getTestContext().getLog() 10547 << tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn" 10548 << tcu::TestLog::EndMessage; 10549 10550 result = false; 10551 } 10552 } 10553 10554 /* verify that early z test is not applied when disabled */ 10555 { 10556 glUseProgram(m_disabled_early_tests.m_program_id); 10557 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram"); 10558 10559 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 10560 GLU_EXPECT_NO_ERROR(glGetError(), "Clear"); 10561 10562 cleanTexture(); 10563 10564 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */); 10565 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i"); 10566 10567 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */); 10568 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f"); 10569 10570 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */); 10571 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays"); 10572 10573 glMemoryBarrier(GL_ALL_BARRIER_BITS); 10574 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier"); 10575 10576 if (false == isTextureFilledWithValue(1.0f)) 10577 { 10578 m_context.getTestContext().getLog() << tcu::TestLog::Message 10579 << "Problem with early z test. It is applied when disabled" 10580 << tcu::TestLog::EndMessage; 10581 10582 result = false; 10583 } 10584 } 10585 10586 glDisable(GL_DEPTH_TEST); 10587 GLU_EXPECT_NO_ERROR(glGetError(), "Disable"); 10588 10589 /* Done */ 10590 return result; 10591 } 10592}; 10593 10594//----------------------------------------------------------------------------- 10595// 4.1 NegativeUniform 10596//----------------------------------------------------------------------------- 10597class NegativeUniform : public ShaderImageLoadStoreBase 10598{ 10599 GLuint m_program; 10600 10601 virtual long Setup() 10602 { 10603 m_program = 0; 10604 return NO_ERROR; 10605 } 10606 10607 virtual long Run() 10608 { 10609 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL 10610 " gl_Position = i_position;" NL "}"; 10611 const char* glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL 10612 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(0.0));" NL 10613 " discard;" NL "}"; 10614 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs); 10615 10616 GLint max_image_units; 10617 glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units); 10618 glUseProgram(m_program); 10619 10620 glUniform1i(glGetUniformLocation(m_program, "g_image"), -1); 10621 if (glGetError() != GL_INVALID_VALUE) 10622 { 10623 m_context.getTestContext().getLog() 10624 << tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero." 10625 << tcu::TestLog::EndMessage; 10626 return ERROR; 10627 } 10628 glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units); 10629 if (glGetError() != GL_INVALID_VALUE) 10630 { 10631 m_context.getTestContext().getLog() 10632 << tcu::TestLog::Message 10633 << "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of " 10634 << "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage; 10635 return ERROR; 10636 } 10637 10638 GLint i = -3; 10639 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i); 10640 if (glGetError() != GL_INVALID_VALUE) 10641 { 10642 m_context.getTestContext().getLog() 10643 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero." 10644 << tcu::TestLog::EndMessage; 10645 return ERROR; 10646 } 10647 i = max_image_units + 1; 10648 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i); 10649 if (glGetError() != GL_INVALID_VALUE) 10650 { 10651 m_context.getTestContext().getLog() 10652 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is greater " 10653 "than or equal to the value of MAX_IMAGE_UNITS." 10654 << tcu::TestLog::EndMessage; 10655 return ERROR; 10656 } 10657 10658 glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0); 10659 if (glGetError() != GL_INVALID_OPERATION) 10660 { 10661 m_context.getTestContext().getLog() 10662 << tcu::TestLog::Message 10663 << "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable." 10664 << tcu::TestLog::EndMessage; 10665 return ERROR; 10666 } 10667 glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0); 10668 if (glGetError() != GL_INVALID_OPERATION) 10669 { 10670 m_context.getTestContext().getLog() 10671 << tcu::TestLog::Message 10672 << "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable." 10673 << tcu::TestLog::EndMessage; 10674 return ERROR; 10675 } 10676 10677 { 10678 glUseProgram(0); 10679 10680 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1); 10681 if (glGetError() != GL_INVALID_VALUE) 10682 { 10683 m_context.getTestContext().getLog() 10684 << tcu::TestLog::Message 10685 << "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero." 10686 << tcu::TestLog::EndMessage; 10687 return ERROR; 10688 } 10689 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units); 10690 if (glGetError() != GL_INVALID_VALUE) 10691 { 10692 m_context.getTestContext().getLog() 10693 << tcu::TestLog::Message 10694 << "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the " 10695 "value of MAX_IMAGE_UNITS." 10696 << tcu::TestLog::EndMessage; 10697 return ERROR; 10698 } 10699 10700 GLint ii = -3; 10701 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii); 10702 if (glGetError() != GL_INVALID_VALUE) 10703 { 10704 m_context.getTestContext().getLog() 10705 << tcu::TestLog::Message 10706 << "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero." 10707 << tcu::TestLog::EndMessage; 10708 return ERROR; 10709 } 10710 ii = max_image_units + 1; 10711 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii); 10712 if (glGetError() != GL_INVALID_VALUE) 10713 { 10714 m_context.getTestContext().getLog() 10715 << tcu::TestLog::Message << "glProgramUniform1iv should generate INVALID_VALUE when <value> " 10716 "is greater than or equal to the value of MAX_IMAGE_UNITS." 10717 << tcu::TestLog::EndMessage; 10718 return ERROR; 10719 } 10720 10721 glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0); 10722 if (glGetError() != GL_INVALID_OPERATION) 10723 { 10724 m_context.getTestContext().getLog() 10725 << tcu::TestLog::Message << "glProgramUniform1ui should generate INVALID_OPERATION if the " 10726 "location refers to an image variable." 10727 << tcu::TestLog::EndMessage; 10728 return ERROR; 10729 } 10730 glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0); 10731 if (glGetError() != GL_INVALID_OPERATION) 10732 { 10733 m_context.getTestContext().getLog() 10734 << tcu::TestLog::Message << "glProgramUniform2i should generate INVALID_OPERATION if the " 10735 "location refers to an image variable." 10736 << tcu::TestLog::EndMessage; 10737 return ERROR; 10738 } 10739 } 10740 10741 return NO_ERROR; 10742 } 10743 10744 virtual long Cleanup() 10745 { 10746 glUseProgram(0); 10747 glDeleteProgram(m_program); 10748 return NO_ERROR; 10749 } 10750}; 10751//----------------------------------------------------------------------------- 10752// 4.2 NegativeBind 10753//----------------------------------------------------------------------------- 10754class NegativeBind : public ShaderImageLoadStoreBase 10755{ 10756 virtual long Setup() 10757 { 10758 return NO_ERROR; 10759 } 10760 10761 virtual long Run() 10762 { 10763 glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA); 10764 if (glGetError() != GL_INVALID_VALUE) 10765 { 10766 m_context.getTestContext().getLog() 10767 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> is " 10768 "greater than or equal to the value of MAX_IMAGE_UNITS." 10769 << tcu::TestLog::EndMessage; 10770 return ERROR; 10771 } 10772 10773 glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA); 10774 if (glGetError() != GL_INVALID_VALUE) 10775 { 10776 m_context.getTestContext().getLog() 10777 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> is not " 10778 "the name of an existing texture object." 10779 << tcu::TestLog::EndMessage; 10780 return ERROR; 10781 } 10782 10783 glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234); 10784 if (glGetError() != GL_INVALID_VALUE) 10785 { 10786 m_context.getTestContext().getLog() 10787 << tcu::TestLog::Message 10788 << "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format." 10789 << tcu::TestLog::EndMessage; 10790 return ERROR; 10791 } 10792 return NO_ERROR; 10793 } 10794 10795 virtual long Cleanup() 10796 { 10797 return NO_ERROR; 10798 } 10799}; 10800//----------------------------------------------------------------------------- 10801// 4.3 NegativeCompileErrors 10802//----------------------------------------------------------------------------- 10803class NegativeCompileErrors : public ShaderImageLoadStoreBase 10804{ 10805 virtual long Run() 10806 { 10807 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10808 "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL 10809 " o_color = imageLoad(g_image, ivec2(0));" NL "}")) 10810 return ERROR; 10811 10812 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10813 "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL 10814 " o_color = imageLoad(g_image, ivec2(0));" NL "}")) 10815 return ERROR; 10816 10817 if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL 10818 "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL 10819 " imageStore(g_image, ivec2(0), i_color);" NL " o_color = i_color;" NL "}")) 10820 return ERROR; 10821 10822 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL 10823 "void main() {" NL " o_color = imageLoad(g_image, ivec2(0));" NL "}")) 10824 return ERROR; 10825 10826 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10827 "readonly uniform image2D g_image;" NL "void main() {" NL 10828 " o_color = imageLoad(g_image, ivec2(0));" NL "}")) 10829 return ERROR; 10830 10831 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10832 "layout(rg16i) uniform image1D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}")) 10833 return ERROR; 10834 10835 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10836 "layout(rg16) uniform iimage2D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}")) 10837 return ERROR; 10838 10839 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10840 "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL 10841 " imageAtomicAdd(g_image, ivec2(1), 10);" NL " o_color = vec4(1.0);" NL "}")) 10842 return ERROR; 10843 10844 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10845 "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL 10846 " imageAtomicAdd(g_image, ivec2(1), 1u);" NL " o_color = vec4(1.0);" NL "}")) 10847 return ERROR; 10848 10849 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10850 "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL 10851 " imageStore(g_image, ivec3(1), ivec4(1));" NL " o_color = vec4(1.0);" NL "}")) 10852 return ERROR; 10853 10854 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10855 "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL 10856 " imageStore(g_image, ivec3(0), uvec4(1));" NL " o_color = vec4(1.0);" NL "}")) 10857 return ERROR; 10858 10859 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10860 "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL 10861 " return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL " o_color = Load(g_image);" NL 10862 "}")) 10863 return ERROR; 10864 10865 return NO_ERROR; 10866 } 10867 10868 bool Compile(const std::string& source) 10869 { 10870 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER); 10871 10872 const char* const src = source.c_str(); 10873 glShaderSource(sh, 1, &src, NULL); 10874 glCompileShader(sh); 10875 10876 GLchar log[1024]; 10877 glGetShaderInfoLog(sh, sizeof(log), NULL, log); 10878 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n" 10879 << log << tcu::TestLog::EndMessage; 10880 10881 GLint status; 10882 glGetShaderiv(sh, GL_COMPILE_STATUS, &status); 10883 glDeleteShader(sh); 10884 10885 if (status == GL_TRUE) 10886 { 10887 m_context.getTestContext().getLog() 10888 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage; 10889 return false; 10890 } 10891 10892 return true; 10893 } 10894}; 10895//----------------------------------------------------------------------------- 10896// 4.4 NegativeLinkErrors 10897//----------------------------------------------------------------------------- 10898class NegativeLinkErrors : public ShaderImageLoadStoreBase 10899{ 10900 virtual long Run() 10901 { 10902 if (!SupportedInVS(1)) 10903 return NOT_SUPPORTED; 10904 10905 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 10906 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL 10907 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}", 10908 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10909 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL 10910 " imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}")) 10911 return ERROR; 10912 10913 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL 10914 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL 10915 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}", 10916 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL 10917 "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL 10918 " imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}")) 10919 return ERROR; 10920 10921 return NO_ERROR; 10922 } 10923 10924 bool Link(const std::string& vs, const std::string& fs) 10925 { 10926 const GLuint p = glCreateProgram(); 10927 10928 const GLuint vsh = glCreateShader(GL_VERTEX_SHADER); 10929 glAttachShader(p, vsh); 10930 glDeleteShader(vsh); 10931 const char* const vssrc = vs.c_str(); 10932 glShaderSource(vsh, 1, &vssrc, NULL); 10933 glCompileShader(vsh); 10934 10935 const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER); 10936 glAttachShader(p, fsh); 10937 glDeleteShader(fsh); 10938 const char* const fssrc = fs.c_str(); 10939 glShaderSource(fsh, 1, &fssrc, NULL); 10940 glCompileShader(fsh); 10941 10942 GLint status; 10943 glGetShaderiv(vsh, GL_COMPILE_STATUS, &status); 10944 if (status == GL_FALSE) 10945 { 10946 glDeleteProgram(p); 10947 m_context.getTestContext().getLog() 10948 << tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage; 10949 return false; 10950 } 10951 glGetShaderiv(fsh, GL_COMPILE_STATUS, &status); 10952 if (status == GL_FALSE) 10953 { 10954 glDeleteProgram(p); 10955 m_context.getTestContext().getLog() 10956 << tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage; 10957 return false; 10958 } 10959 10960 glLinkProgram(p); 10961 10962 GLchar log[1024]; 10963 glGetProgramInfoLog(p, sizeof(log), NULL, log); 10964 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n" 10965 << log << tcu::TestLog::EndMessage; 10966 10967 glGetProgramiv(p, GL_LINK_STATUS, &status); 10968 glDeleteProgram(p); 10969 10970 if (status == GL_TRUE) 10971 { 10972 m_context.getTestContext().getLog() 10973 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage; 10974 return false; 10975 } 10976 10977 return true; 10978 } 10979}; 10980 10981/** Negative Test "Active image uniform limits", description follows. 10982 * 10983 * Program that exceeds resource limits should not compile and/or link. 10984 * 10985 * Steps: 10986 * - try to compile and link a program that uses too many image uniforms in 10987 * fragment shader stage, 10988 * - try to compile and link a program that uses too many image uniforms in 10989 * vertex shader stage, 10990 * - try to compile and link a program that uses too many image uniforms in 10991 * tessellation control shader stage, 10992 * - try to compile and link a program that uses too many image uniforms in 10993 * tessellation evaluation shader stage, 10994 * - try to compile and link a program that uses too many image uniforms in 10995 * geometry shader stage, 10996 * - try to compile and link a program that uses too many image uniforms in all 10997 * shader stages combined, any single stage should not exceed its limits, this 10998 * step might be impossible to fulfill. 10999 * 11000 * Test should use the following declaration of image uniforms: 11001 * layout(r32i) uniform iimage2D u_image[N_UNIFORMS]; 11002 * 11003 * For cases where limit for single stage is tested, N_UNIFORMS should be 11004 * defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant 11005 * corresponding to tested shader stage. 11006 * 11007 * For case where limit for combined stages is tested: 11008 * - u_image name should be appended with the name of shader stage, like 11009 * u_image_vertex, 11010 * - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where 11011 * gl_Max*ImageUniforms is constant corresponding to tested shader stage, 11012 * - compilation and linking shall succeed, when sum of all 11013 * gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to 11014 * gl_MaxCombinedImageUniforms. 11015 * 11016 * All defined image uniforms have to be active. Each shader stage that declare 11017 * image uniforms should include following code snippet: 11018 * value = 1; 11019 * for (int i = 0; i < N_UNIFORMS; ++i) 11020 * { 11021 * value = imageAtomicAdd(u_image[i], coord, value); 11022 * } 11023 **/ 11024class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase 11025{ 11026private: 11027 /* Fields */ 11028 /* Results */ 11029 bool m_result_for_combined; 11030 bool m_result_for_fragment_shader; 11031 bool m_result_for_geometry_shader; 11032 bool m_result_for_tesselation_control_shader; 11033 bool m_result_for_tesselatioon_evaluation_shader; 11034 bool m_result_for_vertex_shader; 11035 11036public: 11037 /* Constructor */ 11038 ImageLoadStoreUniformLimitsTest() 11039 : m_result_for_combined(false) 11040 , m_result_for_fragment_shader(false) 11041 , m_result_for_geometry_shader(false) 11042 , m_result_for_tesselation_control_shader(false) 11043 , m_result_for_tesselatioon_evaluation_shader(false) 11044 , m_result_for_vertex_shader(false) 11045 { 11046 /* Nothing to be done */ 11047 } 11048 11049 /* Methods inherited from SubcaseBase */ 11050 virtual long Cleanup() 11051 { 11052 /* Done */ 11053 return NO_ERROR; 11054 } 11055 11056 virtual long Run() 11057 { 11058 m_context.getTestContext().getLog() << tcu::TestLog::Message 11059 << "This test tries to build invalid programs, expect error messages about " 11060 "exceeded number of active image uniforms" 11061 << tcu::TestLog::EndMessage; 11062 11063 testFragmentShaderStage(); 11064 testGeometryShaderStage(); 11065 testTesselationControlShaderStage(); 11066 testTesselationEvaluationShaderStage(); 11067 testVertexShaderStage(); 11068 testCombinedShaderStages(); 11069 11070 /* Return error if any stage failed */ 11071 if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) || 11072 (false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) || 11073 (false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader)) 11074 { 11075 return ERROR; 11076 } 11077 11078 /* Done */ 11079 return NO_ERROR; 11080 } 11081 11082 virtual long Setup() 11083 { 11084 /* Done */ 11085 return NO_ERROR; 11086 } 11087 11088private: 11089 /** Test fragment shader stage 11090 * 11091 **/ 11092 void testFragmentShaderStage() 11093 { 11094 static const char* const fragment_shader_code = 11095 "#version 400 core\n" 11096 "#extension GL_ARB_shader_image_load_store : require\n" 11097 "\n" 11098 "precision highp float;\n" 11099 "\n" 11100 "#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n" 11101 "\n" 11102 "flat in ivec2 vs_fs_coord;\n" 11103 "\n" 11104 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n" 11105 "\n" 11106 "void main()\n" 11107 "{\n" 11108 " int value = 1;\n" 11109 "\n" 11110 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11111 " {\n" 11112 " value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n" 11113 " }\n" 11114 "\n" 11115 " discard;\n" 11116 "}\n\n"; 11117 11118 static const char* const vertex_shader_code = "#version 400 core\n" 11119 "#extension GL_ARB_shader_image_load_store : require\n" 11120 "\n" 11121 "precision highp float;\n" 11122 "\n" 11123 " in ivec2 vs_in_coord;\n" 11124 "flat out ivec2 vs_fs_coord;\n" 11125 "\n" 11126 "void main()\n" 11127 "{\n" 11128 " vs_fs_coord = vs_in_coord;\n" 11129 "}\n\n"; 11130 11131 m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, 11132 0 /* tesselation_control_shader_code */, 11133 0 /* tesselation_evaluation_shader_code */, vertex_shader_code); 11134 11135 if (false == m_result_for_fragment_shader) 11136 { 11137 m_context.getTestContext().getLog() 11138 << tcu::TestLog::Message 11139 << "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully." 11140 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n" 11141 << fragment_shader_code << tcu::TestLog::EndMessage; 11142 } 11143 } 11144 11145 /** Test geometry shader stage 11146 * 11147 **/ 11148 void testGeometryShaderStage() 11149 { 11150 static const char* const fragment_shader_code = "#version 400 core\n" 11151 "#extension GL_ARB_shader_image_load_store : require\n" 11152 "\n" 11153 "precision highp float;\n" 11154 "\n" 11155 "void main()\n" 11156 "{\n" 11157 " discard;\n" 11158 "}\n\n"; 11159 11160 static const char* const geometry_shader_code = 11161 "#version 400 core\n" 11162 "#extension GL_ARB_shader_image_load_store : require\n" 11163 "\n" 11164 "precision highp float;\n" 11165 "\n" 11166 "layout(points) in;\n" 11167 "layout(points, max_vertices = 1) out;\n" 11168 "\n" 11169 "#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n" 11170 "\n" 11171 "in ivec2 vs_gs_coord[];\n" 11172 "\n" 11173 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n" 11174 "\n" 11175 "void main()\n" 11176 "{\n" 11177 " int value = 1;\n" 11178 "\n" 11179 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11180 " {\n" 11181 " value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\n" 11182 " }\n" 11183 "}\n\n"; 11184 11185 static const char* const vertex_shader_code = "#version 400 core\n" 11186 "#extension GL_ARB_shader_image_load_store : require\n" 11187 "\n" 11188 "precision highp float;\n" 11189 "\n" 11190 "in ivec2 vs_in_coord;\n" 11191 "out ivec2 vs_gs_coord;\n" 11192 "\n" 11193 "void main()\n" 11194 "{\n" 11195 " vs_gs_coord = vs_in_coord;\n" 11196 "}\n\n"; 11197 11198 m_result_for_geometry_shader = 11199 !doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */, 11200 0 /* tesselation_evaluation_shader_code */, vertex_shader_code); 11201 11202 if (false == m_result_for_geometry_shader) 11203 { 11204 m_context.getTestContext().getLog() 11205 << tcu::TestLog::Message 11206 << "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully." 11207 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n" 11208 << geometry_shader_code << tcu::TestLog::EndMessage; 11209 } 11210 } 11211 11212 /** Test tesselation control shader stage 11213 * 11214 **/ 11215 void testTesselationControlShaderStage() 11216 { 11217 static const char* const fragment_shader_code = "#version 400 core\n" 11218 "#extension GL_ARB_shader_image_load_store : require\n" 11219 "\n" 11220 "precision highp float;\n" 11221 "\n" 11222 "void main()\n" 11223 "{\n" 11224 " discard;\n" 11225 "}\n\n"; 11226 11227 static const char* const tesselation_control_shader_code = 11228 "#version 400 core\n" 11229 "#extension GL_ARB_shader_image_load_store : require\n" 11230 "\n" 11231 "precision highp float;\n" 11232 "\n" 11233 "layout(vertices = 4) out;\n" 11234 "\n" 11235 "#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n" 11236 "\n" 11237 "in ivec2 vs_tcs_coord[];\n" 11238 "\n" 11239 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n" 11240 "\n" 11241 "void main()\n" 11242 "{\n" 11243 " int value = 1;\n" 11244 "\n" 11245 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11246 " {\n" 11247 " value = imageAtomicAdd(u_image[i], vs_tcs_coord[0], value);\n" 11248 " }\n" 11249 "}\n\n"; 11250 11251 static const char* const tesselation_evaluation_shader_code = 11252 "#version 400 core\n" 11253 "#extension GL_ARB_shader_image_load_store : require\n" 11254 "\n" 11255 "precision highp float;\n" 11256 "\n" 11257 "layout(quads, equal_spacing, ccw) in;\n" 11258 "\n" 11259 "void main()\n" 11260 "{\n" 11261 "}\n"; 11262 11263 static const char* const vertex_shader_code = "#version 400 core\n" 11264 "#extension GL_ARB_shader_image_load_store : require\n" 11265 "\n" 11266 "precision highp float;\n" 11267 "\n" 11268 "in ivec2 vs_in_coord;\n" 11269 "out ivec2 vs_tcs_coord;\n" 11270 "\n" 11271 "void main()\n" 11272 "{\n" 11273 " vs_tcs_coord = vs_in_coord;\n" 11274 "}\n\n"; 11275 11276 m_result_for_tesselation_control_shader = 11277 !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code, 11278 tesselation_evaluation_shader_code, vertex_shader_code); 11279 11280 if (false == m_result_for_tesselation_control_shader) 11281 { 11282 m_context.getTestContext().getLog() 11283 << tcu::TestLog::Message 11284 << "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully." 11285 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n" 11286 << tesselation_control_shader_code << tcu::TestLog::EndMessage; 11287 } 11288 } 11289 11290 /** Test teselation evaluation shader stage 11291 * 11292 **/ 11293 void testTesselationEvaluationShaderStage() 11294 { 11295 static const char* const fragment_shader_code = "#version 400 core\n" 11296 "#extension GL_ARB_shader_image_load_store : require\n" 11297 "\n" 11298 "precision highp float;\n" 11299 "\n" 11300 "void main()\n" 11301 "{\n" 11302 " discard;\n" 11303 "}\n\n"; 11304 11305 static const char* const tesselation_evaluation_shader_code = 11306 "#version 400 core\n" 11307 "#extension GL_ARB_shader_image_load_store : require\n" 11308 "\n" 11309 "precision highp float;\n" 11310 "\n" 11311 "layout(quads, equal_spacing, ccw) in;\n" 11312 "\n" 11313 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n" 11314 "\n" 11315 "in ivec2 vs_tes_coord[];\n" 11316 "\n" 11317 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n" 11318 "\n" 11319 "void main()\n" 11320 "{\n" 11321 " int value = 1;\n" 11322 "\n" 11323 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11324 " {\n" 11325 " value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n" 11326 " }\n" 11327 "}\n\n"; 11328 11329 static const char* const vertex_shader_code = "#version 400 core\n" 11330 "#extension GL_ARB_shader_image_load_store : require\n" 11331 "\n" 11332 "precision highp float;\n" 11333 "\n" 11334 "in ivec2 vs_in_coord;\n" 11335 "out ivec2 vs_tes_coord;\n" 11336 "\n" 11337 "void main()\n" 11338 "{\n" 11339 " vs_tes_coord = vs_in_coord;\n" 11340 "}\n\n"; 11341 11342 m_result_for_tesselatioon_evaluation_shader = !doesProgramLink( 11343 fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */, 11344 tesselation_evaluation_shader_code, vertex_shader_code); 11345 11346 if (false == m_result_for_tesselatioon_evaluation_shader) 11347 { 11348 m_context.getTestContext().getLog() 11349 << tcu::TestLog::Message 11350 << "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully." 11351 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n" 11352 << tesselation_evaluation_shader_code << tcu::TestLog::EndMessage; 11353 } 11354 } 11355 11356 /** Test vertex shader stage 11357 * 11358 **/ 11359 void testVertexShaderStage() 11360 { 11361 static const char* const fragment_shader_code = "#version 400 core\n" 11362 "#extension GL_ARB_shader_image_load_store : require\n" 11363 "\n" 11364 "precision highp float;\n" 11365 "\n" 11366 "void main()\n" 11367 "{\n" 11368 " discard;\n" 11369 "}\n\n"; 11370 11371 static const char* const vertex_shader_code = 11372 "#version 400 core\n" 11373 "#extension GL_ARB_shader_image_load_store : require\n" 11374 "\n" 11375 "precision highp float;\n" 11376 "\n" 11377 "in ivec2 vs_in_coord;\n" 11378 "\n" 11379 "#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n" 11380 "\n" 11381 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n" 11382 "\n" 11383 "void main()\n" 11384 "{\n" 11385 " int value = 1;\n" 11386 "\n" 11387 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11388 " {\n" 11389 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n" 11390 " }\n" 11391 "}\n\n"; 11392 11393 m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, 11394 0 /* tesselation_control_shader_code */, 11395 0 /* tesselation_evaluation_shader_code */, vertex_shader_code); 11396 11397 if (false == m_result_for_vertex_shader) 11398 { 11399 m_context.getTestContext().getLog() 11400 << tcu::TestLog::Message 11401 << "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully." 11402 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n" 11403 << vertex_shader_code << tcu::TestLog::EndMessage; 11404 } 11405 } 11406 11407 /** Test combined shader stages 11408 * 11409 **/ 11410 void testCombinedShaderStages() 11411 { 11412 std::string fragment_shader_code = 11413 "#version 400 core\n" 11414 "#extension GL_ARB_shader_image_load_store : require\n" 11415 "\n" 11416 "precision highp float;\n" 11417 "\n" 11418 "#define N_UNIFORMS gl_MaxFragmentImageUniforms\n" 11419 "\n" 11420 "flat in ivec2 gs_fs_coord;\n" 11421 "\n" 11422 "layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n" 11423 "\n" 11424 "void main()\n" 11425 "{\n" 11426 " int value = 1;\n" 11427 "\n" 11428 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11429 " {\n" 11430 " value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n" 11431 " }\n" 11432 "\n" 11433 " discard;\n" 11434 "}\n\n"; 11435 11436 std::string geometry_shader_code = 11437 "#version 400 core\n" 11438 "#extension GL_ARB_shader_image_load_store : require\n" 11439 "\n" 11440 "precision highp float;\n" 11441 "\n" 11442 "layout(points) in;\n" 11443 "layout(points, max_vertices = 1) out;\n" 11444 "\n" 11445 "#define N_UNIFORMS gl_MaxGeometryImageUniforms\n" 11446 "\n" 11447 "flat in ivec2 tes_gs_coord[];\n" 11448 "flat out ivec2 gs_fs_coord;\n" 11449 "\n" 11450 "#ifdef IMAGES\n" 11451 "layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n" 11452 "#endif\n" 11453 "\n" 11454 "void main()\n" 11455 "{\n" 11456 "#ifdef IMAGES\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_geometry[i], tes_gs_coord[0], value);\n" 11462 " }\n" 11463 "\n" 11464 "#endif\n" 11465 " gs_fs_coord = tes_gs_coord[0];\n" 11466 " EmitVertex();\n" 11467 "}\n\n"; 11468 11469 std::string tesselation_control_shader_code = 11470 "#version 400 core\n" 11471 "#extension GL_ARB_shader_image_load_store : require\n" 11472 "\n" 11473 "precision highp float;\n" 11474 "\n" 11475 "layout(vertices = 4) out;\n" 11476 "\n" 11477 "#define N_UNIFORMS gl_MaxTessControlImageUniforms\n" 11478 "\n" 11479 "flat in ivec2 vs_tcs_coord[];\n" 11480 "flat out ivec2 tcs_tes_coord[];\n" 11481 "\n" 11482 "#ifdef IMAGES\n" 11483 "layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n" 11484 "#endif\n" 11485 "\n" 11486 "void main()\n" 11487 "{\n" 11488 "#ifdef IMAGES\n" 11489 " int value = 1;\n" 11490 "\n" 11491 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11492 " {\n" 11493 " value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n" 11494 " }\n" 11495 "\n" 11496 "#endif\n" 11497 " tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n" 11498 "}\n\n"; 11499 11500 std::string tesselation_evaluation_shader_code = 11501 "#version 400 core\n" 11502 "#extension GL_ARB_shader_image_load_store : require\n" 11503 "\n" 11504 "precision highp float;\n" 11505 "\n" 11506 "layout(quads, equal_spacing, ccw) in;\n" 11507 "\n" 11508 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n" 11509 "\n" 11510 "flat in ivec2 tcs_tes_coord[];\n" 11511 "flat out ivec2 tes_gs_coord;\n" 11512 "\n" 11513 "#ifdef IMAGES\n" 11514 "layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n" 11515 "#endif\n" 11516 "\n" 11517 "void main()\n" 11518 "{\n" 11519 "#ifdef IMAGES\n" 11520 " int value = 1;\n" 11521 "\n" 11522 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11523 " {\n" 11524 " value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n" 11525 " }\n" 11526 "\n" 11527 "#endif\n" 11528 " tes_gs_coord = tcs_tes_coord[0];\n" 11529 "}\n\n"; 11530 11531 std::string vertex_shader_code = 11532 "#version 400 core\n" 11533 "#extension GL_ARB_shader_image_load_store : require\n" 11534 "\n" 11535 "precision highp float;\n" 11536 "\n" 11537 " in ivec2 vs_in_coord;\n" 11538 "flat out ivec2 vs_tcs_coord;\n" 11539 "\n" 11540 "#define N_UNIFORMS gl_MaxVertexImageUniforms\n" 11541 "\n" 11542 "#ifdef IMAGES\n" 11543 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n" 11544 "#endif\n" 11545 "\n" 11546 "void main()\n" 11547 "{\n" 11548 "#ifdef IMAGES\n" 11549 " int value = 1;\n" 11550 "\n" 11551 " for (int i = 0; i < N_UNIFORMS; ++i)\n" 11552 " {\n" 11553 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n" 11554 " }\n" 11555 "\n" 11556 "#endif\n" 11557 " vs_tcs_coord = vs_tcs_coord;\n" 11558 "}\n\n"; 11559 11560 /* Active image uniform limits */ 11561 GLint max_combined_image_uniforms = 0; 11562 GLint max_fragment_image_uniforms = 0; 11563 GLint max_geometry_image_uniforms = 0; 11564 GLint max_tesselation_control_image_uniforms = 0; 11565 GLint max_tesselation_evaluation_image_uniforms = 0; 11566 GLint max_vertex_image_uniforms = 0; 11567 11568 /* Get limit values */ 11569 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms); 11570 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms); 11571 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms); 11572 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms); 11573 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms); 11574 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms); 11575 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv"); 11576 11577 if (max_vertex_image_uniforms) 11578 vertex_shader_code.insert(18, "#define IMAGES\n"); 11579 if (max_geometry_image_uniforms) 11580 geometry_shader_code.insert(18, "#define IMAGES\n"); 11581 if (max_tesselation_control_image_uniforms) 11582 tesselation_control_shader_code.insert(18, "#define IMAGES\n"); 11583 if (max_tesselation_evaluation_image_uniforms) 11584 tesselation_evaluation_shader_code.insert(18, "#define IMAGES\n"); 11585 11586 /* Check if program builds */ 11587 m_result_for_combined = 11588 !doesProgramLink(fragment_shader_code.c_str(), 11589 geometry_shader_code.c_str(), 11590 tesselation_control_shader_code.c_str(), 11591 tesselation_evaluation_shader_code.c_str(), 11592 vertex_shader_code.c_str()); 11593 11594 /* Result depends on the limit values */ 11595 if (max_combined_image_uniforms >= 11596 (max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms + 11597 max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms)) 11598 { 11599 /* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */ 11600 m_result_for_combined = !m_result_for_combined; 11601 11602 if (false == m_result_for_combined) 11603 { 11604 m_context.getTestContext().getLog() 11605 << tcu::TestLog::Message << "There was an error while building a program." 11606 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n" 11607 << vertex_shader_code << "\nTesselation control shader code:\n" 11608 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n" 11609 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n" 11610 << geometry_shader_code << "\nFragment shader code:\n" 11611 << fragment_shader_code << tcu::TestLog::EndMessage; 11612 } 11613 } 11614 else 11615 { 11616 /* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */ 11617 if (false == m_result_for_combined) 11618 { 11619 m_context.getTestContext().getLog() 11620 << tcu::TestLog::Message 11621 << "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully." 11622 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n" 11623 << vertex_shader_code << "\nTesselation control shader code:\n" 11624 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n" 11625 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n" 11626 << geometry_shader_code << "\nFragment shader code:\n" 11627 << fragment_shader_code << tcu::TestLog::EndMessage; 11628 } 11629 } 11630 } 11631 11632 /** Check if program builds successfully 11633 * 11634 * @param fragment_shader_code Source code for fragment shader stage 11635 * @param geometry_shader_code Source code for geometry shader stage 11636 * @param tesselation_control_shader_code Source code for tesselation control shader stage 11637 * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage 11638 * @param vertex_shader_code Source code for vertex shader stage 11639 * 11640 * @return true if program was built without errors, false otherwise 11641 **/ 11642 bool doesProgramLink(const char* fragment_shader_code, const char* geometry_shader_code, 11643 const char* tesselation_control_shader_code, const char* tesselation_evaluation_shader_code, 11644 const char* vertex_shader_code) 11645 { 11646 bool is_program_built = true; 11647 GLuint program_id = 0; 11648 11649 program_id = 11650 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code, 11651 geometry_shader_code, fragment_shader_code, &is_program_built); 11652 11653 if (0 != program_id) 11654 { 11655 glDeleteProgram(program_id); 11656 } 11657 11658 return is_program_built; 11659 } 11660}; 11661} 11662 11663ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context& context) 11664 : TestCaseGroup(context, "shader_image_load_store", "") 11665{ 11666} 11667 11668ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void) 11669{ 11670} 11671 11672void ShaderImageLoadStoreTests::init() 11673{ 11674 using namespace deqp; 11675 addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>)); 11676 addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>)); 11677 addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>)); 11678 addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>)); 11679 addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>)); 11680 addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>)); 11681 addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages", 11682 TestSubcase::Create<BasicAllFormatsStoreGeometryStages>)); 11683 addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages", 11684 TestSubcase::Create<BasicAllFormatsLoadGeometryStages>)); 11685 addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage", 11686 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>)); 11687 addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>)); 11688 addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>)); 11689 addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>)); 11690 addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>)); 11691 addChild( 11692 new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>)); 11693 addChild( 11694 new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>)); 11695 addChild( 11696 new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>)); 11697 addChild( 11698 new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>)); 11699 addChild( 11700 new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>)); 11701 addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>)); 11702 addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>)); 11703 addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>)); 11704 addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>)); 11705 addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>)); 11706 addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>)); 11707 addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>)); 11708 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>)); 11709 addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>)); 11710 addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>)); 11711 addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>)); 11712 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>)); 11713 addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>)); 11714 addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>)); 11715 addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation", 11716 TestSubcase::Create<AdvancedMemoryDependentInvocation>)); 11717 addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>)); 11718 addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>)); 11719 addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>)); 11720 addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>)); 11721 addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>)); 11722 addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>)); 11723 addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>)); 11724 addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>)); 11725 addChild( 11726 new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>)); 11727 addChild( 11728 new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>)); 11729 addChild( 11730 new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>)); 11731 addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>)); 11732 addChild( 11733 new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>)); 11734 addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>)); 11735 addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>)); 11736 addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>)); 11737 addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>)); 11738 addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>)); 11739} 11740} 11741