es31cShaderImageLoadStoreTests.cpp revision 48087f5f0eb08759ee763f98daf3b34becb74559
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 "es31cShaderImageLoadStoreTests.hpp" 25#include "gluContextInfo.hpp" 26#include "glwEnums.hpp" 27#include "tcuMatrix.hpp" 28#include "tcuRenderTarget.hpp" 29#include "tcuVectorUtil.hpp" 30#include <assert.h> 31#include <cstdarg> 32#include <map> 33 34namespace glcts 35{ 36using namespace glw; 37namespace 38{ 39typedef tcu::Vec2 vec2; 40typedef tcu::Vec4 vec4; 41typedef tcu::IVec4 ivec4; 42typedef tcu::UVec4 uvec4; 43typedef tcu::Mat4 mat4; 44 45enum Target 46{ 47 T2D = 0, 48 T3D, 49 TCM, 50 T2DA 51}; 52 53static tcu::TestLog* currentLog; 54void setOutput(tcu::TestLog& log) 55{ 56 currentLog = &log; 57} 58 59void Output(const char* format, ...) 60{ 61 va_list args; 62 va_start(args, format); 63 64 const int MAX_OUTPUT_STRING_SIZE = 40000; 65 static char temp[MAX_OUTPUT_STRING_SIZE]; 66 67 vsnprintf(temp, MAX_OUTPUT_STRING_SIZE - 1, format, args); 68 temp[MAX_OUTPUT_STRING_SIZE - 1] = '\0'; 69 70 char* logLine = strtok(temp, "\n"); 71 while (logLine != NULL) 72 { 73 currentLog->writeMessage(logLine); 74 logLine = strtok(NULL, "\n"); 75 } 76 va_end(args); 77} 78 79const char* const kGLSLVer = "#version 310 es"; 80 81const char* const kGLSLSIA = NL "#extension GL_OES_shader_image_atomic : require"; 82 83const char* const kGLSLPrec = 84 NL "precision highp float;" NL "precision highp int;" NL "precision highp sampler2D;" NL 85 "precision highp sampler3D;" NL "precision highp samplerCube;" NL "precision highp sampler2DArray;" NL 86 "precision highp isampler2D;" NL "precision highp isampler3D;" NL "precision highp isamplerCube;" NL 87 "precision highp isampler2DArray;" NL "precision highp usampler2D;" NL "precision highp usampler3D;" NL 88 "precision highp usamplerCube;" NL "precision highp usampler2DArray;" NL "precision highp image2D;" NL 89 "precision highp image3D;" NL "precision highp imageCube;" NL "precision highp image2DArray;" NL 90 "precision highp iimage2D;" NL "precision highp iimage3D;" NL "precision highp iimageCube;" NL 91 "precision highp iimage2DArray;" NL "precision highp uimage2D;" NL "precision highp uimage3D;" NL 92 "precision highp uimageCube;" NL "precision highp uimage2DArray;"; 93 94class ShaderImageLoadStoreBase : public glcts::SubcaseBase 95{ 96public: 97 virtual std::string Title() 98 { 99 return ""; 100 } 101 virtual std::string Purpose() 102 { 103 return ""; 104 } 105 virtual std::string Method() 106 { 107 return ""; 108 } 109 virtual std::string PassCriteria() 110 { 111 return ""; 112 } 113 114 bool IsVSFSAvailable(int requiredVS, int requiredFS) 115 { 116 GLint imagesVS, imagesFS; 117 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS); 118 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &imagesFS); 119 if (imagesVS >= requiredVS && imagesFS >= requiredFS) 120 return true; 121 else 122 { 123 std::ostringstream reason; 124 reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available." 125 << std::endl 126 << "Required " << requiredFS << " FS image uniforms but only " << imagesFS << " available." 127 << std::endl; 128 OutputNotSupported(reason.str()); 129 return false; 130 } 131 } 132 bool IsSSBInVSFSAvailable(int required) 133 { 134 GLint blocksVS, blocksFS; 135 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS); 136 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &blocksFS); 137 if (blocksVS >= required && blocksFS >= required) 138 return true; 139 else 140 { 141 std::ostringstream reason; 142 reason << "Required " << required << " VS storage blocks but only " << blocksVS << " available." 143 << std::endl 144 << "Required " << required << " FS storage blocks but only " << blocksFS << " available." 145 << std::endl; 146 OutputNotSupported(reason.str()); 147 return false; 148 } 149 } 150 151 bool IsImageAtomicSupported() 152 { 153 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_image_atomic")) 154 { 155 std::ostringstream reason; 156 reason << "Required GL_OES_shader_image_atomic is not available." << std::endl; 157 OutputNotSupported(reason.str()); 158 return false; 159 } 160 return true; 161 } 162 163 bool AreOutputsAvailable(int required) 164 { 165 GLint outputs; 166 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &outputs); 167 if (outputs < required) 168 { 169 std::ostringstream reason; 170 reason << "Required " << required << " shader output resources but only " << outputs << " available." 171 << std::endl; 172 OutputNotSupported(reason.str()); 173 return false; 174 } 175 return true; 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 inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon) 191 { 192 if (fabs(c0[0] - c1[0]) > epsilon[0]) 193 return false; 194 if (fabs(c0[1] - c1[1]) > epsilon[1]) 195 return false; 196 if (fabs(c0[2] - c1[2]) > epsilon[2]) 197 return false; 198 if (fabs(c0[3] - c1[3]) > epsilon[3]) 199 return false; 200 return true; 201 } 202 203 bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat) 204 { 205 if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RGBA8) 206 { 207 return ColorEqual(v0, v1, vec4(0.01f)); 208 } 209 return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]); 210 } 211 bool Equal(const ivec4& a, const ivec4& b, GLenum) 212 { 213 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]); 214 } 215 bool Equal(const uvec4& a, const uvec4& b, GLenum) 216 { 217 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]); 218 } 219 220 template <class T> 221 std::string ToString(T v) 222 { 223 std::ostringstream s; 224 s << "["; 225 for (int i = 0; i < 4; ++i) 226 s << v[i] << (i == 3 ? "" : ","); 227 s << "]"; 228 return s.str(); 229 } 230 231 template <typename T> 232 bool CompareValues(T* map_data, int kSize, const T& expected_value, GLenum internalformat = 0, int layers = 1) 233 { 234 for (int i = 0; i < kSize * kSize * layers; ++i) 235 { 236 if (!Equal(map_data[i], expected_value, internalformat)) 237 { 238 Output("[%d] Value is: %s. Value should be: %s.\n", i, ToString(map_data[i]).c_str(), 239 ToString(expected_value).c_str()); 240 return false; 241 } 242 } 243 return true; 244 } 245 template <typename T> 246 bool CompareValues(bool always, T* map_data, int kSize, const T& expected_value, GLenum internalformat = 0, 247 int layers = 1) 248 { 249 (void)internalformat; 250 for (int i = 0; i < kSize * kSize * layers; ++i) 251 { 252 if (always) 253 { 254 Output("[%d] Value is: %s. Value should be: %s.\n", i, ToString(map_data[i]).c_str(), 255 ToString(expected_value).c_str()); 256 } 257 } 258 return true; 259 } 260 261 bool CheckFB(vec4 expected) 262 { 263 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 264 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat(); 265 vec4 g_color_eps = vec4(1.f / static_cast<float>(1 << pixelFormat.redBits), 266 1.f / static_cast<float>(1 << pixelFormat.greenBits), 267 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f); 268 vec4 g_color_max = vec4(255); 269 std::vector<GLubyte> fb(getWindowWidth() * getWindowHeight() * 4); 270 int fb_w = getWindowWidth(); 271 int fb_h = getWindowHeight(); 272 glReadPixels(0, 0, fb_w, fb_h, GL_RGBA, GL_UNSIGNED_BYTE, &fb[0]); 273 for (GLint i = 0, y = 0; y < fb_h; ++y) 274 for (GLint x = 0; x < fb_w; ++x, i += 4) 275 { 276 if (fabs(fb[i + 0] / g_color_max[0] - expected[0]) > g_color_eps[0] || 277 fabs(fb[i + 1] / g_color_max[1] - expected[1]) > g_color_eps[1] || 278 fabs(fb[i + 2] / g_color_max[2] - expected[2]) > g_color_eps[2]) 279 { 280 281 Output("Incorrect framebuffer color at pixel (%d %d). Color is (%f %f %f). " 282 "Color should be (%f %f %f).\n", 283 x, y, fb[i + 0] / g_color_max[0], fb[i + 1] / g_color_max[1], fb[i + 2] / g_color_max[2], 284 expected[0], expected[1], expected[2]); 285 return false; 286 } 287 } 288 return true; 289 } 290 291 bool CompileShader(GLuint shader) 292 { 293 glCompileShader(shader); 294 295 GLint status; 296 glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 297 if (status == GL_FALSE) 298 { 299 GLsizei length; 300 GLchar log[1024]; 301 glGetShaderInfoLog(shader, sizeof(log), &length, log); 302 if (length > 1) 303 { 304 Output("Shader Info Log:\n%s\n", log); 305 } 306 return false; 307 } 308 return true; 309 } 310 311 bool LinkProgram(GLuint program) 312 { 313 glLinkProgram(program); 314 315 GLint status; 316 glGetProgramiv(program, GL_LINK_STATUS, &status); 317 if (status == GL_FALSE) 318 { 319 GLsizei length; 320 GLchar log[1024]; 321 glGetProgramInfoLog(program, sizeof(log), &length, log); 322 if (length > 1) 323 { 324 Output("Program Info Log:\n%s\n", log); 325 } 326 return false; 327 } 328 return true; 329 } 330 331 GLuint BuildProgram(const char* src_vs, const char* src_fs, bool SIAvs = false, bool SIAfs = false) 332 { 333 std::ostringstream osvs, osfs; 334 osvs << kGLSLVer << (SIAvs ? kGLSLSIA : "\n") << kGLSLPrec; 335 osfs << kGLSLVer << (SIAfs ? kGLSLSIA : "\n") << kGLSLPrec; 336 std::string hvs = osvs.str(); 337 std::string hfs = osfs.str(); 338 339 const GLuint p = glCreateProgram(); 340 341 if (src_vs) 342 { 343 GLuint sh = glCreateShader(GL_VERTEX_SHADER); 344 glAttachShader(p, sh); 345 glDeleteShader(sh); 346 const char* const src[2] = { hvs.c_str(), src_vs }; 347 glShaderSource(sh, 2, src, NULL); 348 if (!CompileShader(sh)) 349 { 350 Output("%s%s\n", src[0], src[1]); 351 return p; 352 } 353 } 354 if (src_fs) 355 { 356 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER); 357 glAttachShader(p, sh); 358 glDeleteShader(sh); 359 const char* const src[2] = { hfs.c_str(), src_fs }; 360 glShaderSource(sh, 2, src, NULL); 361 if (!CompileShader(sh)) 362 { 363 Output("%s%s\n", src[0], src[1]); 364 return p; 365 } 366 } 367 if (!LinkProgram(p)) 368 { 369 if (src_vs) 370 Output("%s%s\n", hvs.c_str(), src_vs); 371 if (src_fs) 372 Output("%s%s\n", hfs.c_str(), src_fs); 373 return p; 374 } 375 376 return p; 377 } 378 379 GLuint CreateComputeProgram(const std::string& cs, bool SIA = false) 380 { 381 std::ostringstream oscs; 382 oscs << kGLSLVer << (SIA ? kGLSLSIA : "\n") << kGLSLPrec; 383 std::string hcs = oscs.str(); 384 const GLuint p = glCreateProgram(); 385 386 if (!cs.empty()) 387 { 388 const GLuint sh = glCreateShader(GL_COMPUTE_SHADER); 389 glAttachShader(p, sh); 390 glDeleteShader(sh); 391 const char* const src[2] = { hcs.c_str(), cs.c_str() }; 392 glShaderSource(sh, 2, src, NULL); 393 if (!CompileShader(sh)) 394 { 395 Output("%s%s\n", src[0], src[1]); 396 return p; 397 } 398 } 399 if (!LinkProgram(p)) 400 { 401 if (!cs.empty()) 402 Output("%s%s\n", hcs.c_str(), cs.c_str()); 403 return p; 404 } 405 406 return p; 407 } 408 409 GLuint BuildShaderProgram(GLenum type, const char* src) 410 { 411 const char* const src3[3] = { kGLSLVer, kGLSLPrec, src }; 412 const GLuint p = glCreateShaderProgramv(type, 3, src3); 413 GLint status; 414 glGetProgramiv(p, GL_LINK_STATUS, &status); 415 if (status == GL_FALSE) 416 { 417 GLchar log[1024]; 418 glGetProgramInfoLog(p, sizeof(log), NULL, log); 419 Output("Program Info Log:\n%s\n%s\n%s\n%s\n", log, src3[0], src3[1], src3[2]); 420 } 421 return p; 422 } 423 424 void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo) 425 { 426 assert(vao && vbo); 427 428 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red)) 429 const float v[] = { 430 -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, 431 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, 432 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, 433 }; 434 glGenBuffers(1, vbo); 435 glBindBuffer(GL_ARRAY_BUFFER, *vbo); 436 glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW); 437 glBindBuffer(GL_ARRAY_BUFFER, 0); 438 439 if (ebo) 440 { 441 std::vector<GLushort> index_data(4); 442 for (int i = 0; i < 4; ++i) 443 { 444 index_data[i] = static_cast<GLushort>(i); 445 } 446 glGenBuffers(1, ebo); 447 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo); 448 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW); 449 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 450 } 451 452 glGenVertexArrays(1, vao); 453 glBindVertexArray(*vao); 454 glBindBuffer(GL_ARRAY_BUFFER, *vbo); 455 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0); 456 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2)); 457 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5)); 458 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8)); 459 glBindBuffer(GL_ARRAY_BUFFER, 0); 460 glEnableVertexAttribArray(0); 461 glEnableVertexAttribArray(1); 462 glEnableVertexAttribArray(2); 463 glEnableVertexAttribArray(3); 464 if (ebo) 465 { 466 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo); 467 } 468 glBindVertexArray(0); 469 } 470 471 std::string FormatEnumToString(GLenum e) 472 { 473 switch (e) 474 { 475 case GL_RGBA32F: 476 return "rgba32f"; 477 case GL_RGBA16F: 478 return "rgba16f"; 479 case GL_R32F: 480 return "r32f"; 481 482 case GL_RGBA32UI: 483 return "rgba32ui"; 484 case GL_RGBA16UI: 485 return "rgba16ui"; 486 case GL_RGBA8UI: 487 return "rgba8ui"; 488 case GL_R32UI: 489 return "r32ui"; 490 491 case GL_RGBA32I: 492 return "rgba32i"; 493 case GL_RGBA16I: 494 return "rgba16i"; 495 case GL_RGBA8I: 496 return "rgba8i"; 497 case GL_R32I: 498 return "r32i"; 499 500 case GL_RGBA8: 501 return "rgba8"; 502 503 case GL_RGBA8_SNORM: 504 return "rgba8_snorm"; 505 } 506 507 assert(0); 508 return ""; 509 } 510 511 template <typename T> 512 GLenum Format(); 513 514 template <typename T> 515 GLenum Type(); 516 517 template <typename T> 518 std::string TypePrefix(); 519 520 template <typename T> 521 GLenum ImageType(GLenum target); 522 523 void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color) 524 { 525 glClearBufferfv(buffer, drawbuffer, &color[0]); 526 } 527 void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color) 528 { 529 glClearBufferiv(buffer, drawbuffer, &color[0]); 530 } 531 void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color) 532 { 533 glClearBufferuiv(buffer, drawbuffer, &color[0]); 534 } 535 536 bool CheckMax(GLenum pname, GLint min_value) 537 { 538 GLboolean b; 539 GLint i; 540 GLfloat f; 541 GLint64 i64; 542 543 glGetIntegerv(pname, &i); 544 if (i < min_value) 545 return false; 546 547 glGetBooleanv(pname, &b); 548 if (b != (i ? GL_TRUE : GL_FALSE)) 549 return false; 550 551 glGetFloatv(pname, &f); 552 if (static_cast<GLint>(f) < min_value) 553 return false; 554 555 glGetInteger64v(pname, &i64); 556 if (static_cast<GLint>(i64) < min_value) 557 return false; 558 559 return true; 560 } 561 562 bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, 563 GLenum format) 564 { 565 GLint i; 566 GLboolean b; 567 568 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i); 569 if (static_cast<GLuint>(i) != texture) 570 { 571 Output("GL_IMAGE_BINDING_NAME is %d should be %d.\n", i, texture); 572 return false; 573 } 574 575 glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i); 576 if (i != level) 577 { 578 Output("GL_IMAGE_BINDING_LEVEL is %d should be %d.\n", i, level); 579 return false; 580 } 581 582 glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i); 583 glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b); 584 if (i != layered || b != layered) 585 { 586 Output("GL_IMAGE_BINDING_LAYERED is %d should be %d.\n", i, layered); 587 return false; 588 } 589 590 glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i); 591 if (i != layer) 592 { 593 Output("GL_IMAGE_BINDING_LAYER is %d should be %d.\n", i, layer); 594 return false; 595 } 596 597 glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i); 598 if (static_cast<GLenum>(i) != access) 599 { 600 Output("GL_IMAGE_BINDING_ACCESS is %d should be %d.\n", i, access); 601 return false; 602 } 603 604 glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i); 605 if (static_cast<GLenum>(i) != format) 606 { 607 Output("GL_IMAGE_BINDING_FORMAT is %d should be %d.\n", i, format); 608 return false; 609 } 610 611 return true; 612 } 613 const char* EnumToString(GLenum e) 614 { 615 switch (e) 616 { 617 case GL_TEXTURE_2D: 618 return "GL_TEXTURE_2D"; 619 case GL_TEXTURE_3D: 620 return "GL_TEXTURE_3D"; 621 case GL_TEXTURE_CUBE_MAP: 622 return "GL_TEXTURE_CUBE_MAP"; 623 case GL_TEXTURE_2D_ARRAY: 624 return "GL_TEXTURE_2D_ARRAY"; 625 626 default: 627 assert(0); 628 break; 629 } 630 return NULL; 631 } 632}; 633 634template <> 635GLenum ShaderImageLoadStoreBase::Format<vec4>() 636{ 637 return GL_RGBA; 638} 639template <> 640GLenum ShaderImageLoadStoreBase::Format<ivec4>() 641{ 642 return GL_RGBA_INTEGER; 643} 644template <> 645GLenum ShaderImageLoadStoreBase::Format<uvec4>() 646{ 647 return GL_RGBA_INTEGER; 648} 649template <> 650GLenum ShaderImageLoadStoreBase::Format<GLint>() 651{ 652 return GL_RED_INTEGER; 653} 654template <> 655GLenum ShaderImageLoadStoreBase::Format<GLuint>() 656{ 657 return GL_RED_INTEGER; 658} 659 660template <> 661GLenum ShaderImageLoadStoreBase::Type<vec4>() 662{ 663 return GL_FLOAT; 664} 665template <> 666GLenum ShaderImageLoadStoreBase::Type<ivec4>() 667{ 668 return GL_INT; 669} 670template <> 671GLenum ShaderImageLoadStoreBase::Type<uvec4>() 672{ 673 return GL_UNSIGNED_INT; 674} 675template <> 676GLenum ShaderImageLoadStoreBase::Type<GLint>() 677{ 678 return GL_INT; 679} 680template <> 681GLenum ShaderImageLoadStoreBase::Type<GLuint>() 682{ 683 return GL_UNSIGNED_INT; 684} 685 686template <> 687std::string ShaderImageLoadStoreBase::TypePrefix<vec4>() 688{ 689 return ""; 690} 691template <> 692std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>() 693{ 694 return "i"; 695} 696template <> 697std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>() 698{ 699 return "u"; 700} 701template <> 702std::string ShaderImageLoadStoreBase::TypePrefix<GLint>() 703{ 704 return "i"; 705} 706template <> 707std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>() 708{ 709 return "u"; 710} 711 712template <> 713GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target) 714{ 715 switch (target) 716 { 717 case GL_TEXTURE_2D: 718 return GL_IMAGE_2D; 719 case GL_TEXTURE_3D: 720 return GL_IMAGE_3D; 721 case GL_TEXTURE_CUBE_MAP: 722 return GL_IMAGE_CUBE; 723 case GL_TEXTURE_2D_ARRAY: 724 return GL_IMAGE_2D_ARRAY; 725 } 726 assert(0); 727 return 0; 728} 729 730template <> 731GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target) 732{ 733 switch (target) 734 { 735 case GL_TEXTURE_2D: 736 return GL_INT_IMAGE_2D; 737 case GL_TEXTURE_3D: 738 return GL_INT_IMAGE_3D; 739 case GL_TEXTURE_CUBE_MAP: 740 return GL_INT_IMAGE_CUBE; 741 case GL_TEXTURE_2D_ARRAY: 742 return GL_INT_IMAGE_2D_ARRAY; 743 } 744 assert(0); 745 return 0; 746} 747 748template <> 749GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target) 750{ 751 switch (target) 752 { 753 case GL_TEXTURE_2D: 754 return GL_UNSIGNED_INT_IMAGE_2D; 755 case GL_TEXTURE_3D: 756 return GL_UNSIGNED_INT_IMAGE_3D; 757 case GL_TEXTURE_CUBE_MAP: 758 return GL_UNSIGNED_INT_IMAGE_CUBE; 759 case GL_TEXTURE_2D_ARRAY: 760 return GL_UNSIGNED_INT_IMAGE_2D_ARRAY; 761 } 762 assert(0); 763 return 0; 764} 765 766int Components(GLenum e) 767{ 768 return (e == GL_RED || e == GL_RED_INTEGER) ? 1 : 4; 769} 770 771bool Shorts(GLenum e) 772{ 773 return (e == GL_RGBA16I || e == GL_RGBA16UI); 774} 775 776bool Bytes(GLenum e) 777{ 778 return (e == GL_RGBA8I || e == GL_RGBA8UI || e == GL_RGBA8 || e == GL_RGBA8_SNORM); 779} 780 781template <typename T> 782class ShortByteData 783{ 784public: 785 std::vector<T> data; 786 std::vector<GLshort> datas; 787 std::vector<GLbyte> datab; 788 789 ShortByteData(int size, const T& value, GLenum internalformat, GLenum format) 790 : data(size * size, value), datas(size * size * 4), datab(size * size * 4) 791 { 792 if (Components(format) == 1) 793 for (unsigned i = 0; i < data.size() / 4; ++i) 794 { 795 data[i][0] = data[i * 4][0]; 796 data[i][1] = data[i * 4 + 1][0]; 797 data[i][2] = data[i * 4 + 2][0]; 798 data[i][3] = data[i * 4 + 3][0]; 799 } 800 if (Shorts(internalformat)) 801 { 802 for (unsigned i = 0; i < datas.size(); i += 4) 803 { 804 datas[i] = static_cast<GLshort>(data[i / 4][0]); 805 datas[i + 1] = static_cast<GLshort>(data[i / 4][1]); 806 datas[i + 2] = static_cast<GLshort>(data[i / 4][2]); 807 datas[i + 3] = static_cast<GLshort>(data[i / 4][3]); 808 } 809 } 810 if (Bytes(internalformat)) 811 { 812 for (unsigned i = 0; i < datas.size(); i += 4) 813 { 814 if (internalformat == GL_RGBA8I || internalformat == GL_RGBA8UI) 815 { 816 datab[i] = static_cast<GLbyte>(data[i / 4][0]); 817 datab[i + 1] = static_cast<GLbyte>(data[i / 4][1]); 818 datab[i + 2] = static_cast<GLbyte>(data[i / 4][2]); 819 datab[i + 3] = static_cast<GLbyte>(data[i / 4][3]); 820 } 821 else if (internalformat == GL_RGBA8) 822 { 823 datab[i] = static_cast<GLbyte>(data[i / 4][0] * 255); 824 datab[i + 1] = static_cast<GLbyte>(data[i / 4][1] * 255); 825 datab[i + 2] = static_cast<GLbyte>(data[i / 4][2] * 255); 826 datab[i + 3] = static_cast<GLbyte>(data[i / 4][3] * 255); 827 } 828 else 829 { // GL_RGBA8_SNORM 830 datab[i] = static_cast<GLbyte>(data[i / 4][0] * 127); 831 datab[i + 1] = static_cast<GLbyte>(data[i / 4][1] * 127); 832 datab[i + 2] = static_cast<GLbyte>(data[i / 4][2] * 127); 833 datab[i + 3] = static_cast<GLbyte>(data[i / 4][3] * 127); 834 } 835 } 836 } 837 } 838}; 839 840//----------------------------------------------------------------------------- 841// 1.1.1 BasicAPIGet 842//----------------------------------------------------------------------------- 843class BasicAPIGet : public ShaderImageLoadStoreBase 844{ 845 virtual long Run() 846 { 847 if (!CheckMax(GL_MAX_IMAGE_UNITS, 4)) 848 { 849 Output("GL_MAX_IMAGE_UNITS value is invalid.\n"); 850 return ERROR; 851 } 852 if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 4)) 853 { 854 Output("GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid.\n"); 855 return ERROR; 856 } 857 if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0)) 858 { 859 Output("GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid.\n"); 860 return ERROR; 861 } 862 if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 0)) 863 { 864 Output("GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid.\n"); 865 return ERROR; 866 } 867 if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 4)) 868 { 869 Output("GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid.\n"); 870 return ERROR; 871 } 872 if (!CheckMax(GL_MAX_COMPUTE_IMAGE_UNIFORMS, 4)) 873 { 874 Output("GL_MAX_COMPUTE_IMAGE_UNIFORMS value is invalid.\n"); 875 return ERROR; 876 } 877 return NO_ERROR; 878 } 879}; 880//----------------------------------------------------------------------------- 881// 1.1.2 BasicAPIBind 882//----------------------------------------------------------------------------- 883class BasicAPIBind : public ShaderImageLoadStoreBase 884{ 885 GLuint m_texture; 886 887 virtual long Setup() 888 { 889 m_texture = 0; 890 return NO_ERROR; 891 } 892 virtual long Run() 893 { 894 bool status = true; 895 for (GLuint index = 0; index < 4; ++index) 896 { 897 if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI)) 898 { 899 Output("Binding point %d has invalid default state.\n", index); 900 status = false; 901 } 902 } 903 904 glGenTextures(1, &m_texture); 905 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 906 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RG32F, 16, 16, 4); 907 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 908 909 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); 910 if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F)) 911 status = false; 912 913 glBindImageTexture(3, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8); 914 if (!CheckBinding(3, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8)) 915 status = false; 916 917 glBindImageTexture(1, m_texture, 3, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA8UI); 918 if (!CheckBinding(1, m_texture, 3, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA8UI)) 919 status = false; 920 921 glBindImageTexture(2, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I); 922 if (!CheckBinding(2, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I)) 923 status = false; 924 925 glDeleteTextures(1, &m_texture); 926 m_texture = 0; 927 928 for (GLuint index = 0; index < 4; ++index) 929 { 930 GLint name; 931 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name); 932 if (name != 0) 933 { 934 Output("Binding point %d should be set to 0 after texture deletion.\n", index); 935 status = false; 936 } 937 if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI)) 938 status = false; 939 } 940 941 return status ? NO_ERROR : ERROR; 942 } 943 944 virtual long Cleanup() 945 { 946 glDeleteTextures(1, &m_texture); 947 return NO_ERROR; 948 } 949}; 950//----------------------------------------------------------------------------- 951// 1.1.3 BasicAPIBarrier 952//----------------------------------------------------------------------------- 953class BasicAPIBarrier : public ShaderImageLoadStoreBase 954{ 955 virtual long Run() 956 { 957 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT); 958 glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT); 959 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT); 960 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); 961 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 962 glMemoryBarrier(GL_COMMAND_BARRIER_BIT); 963 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); 964 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 965 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 966 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); 967 glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT); 968 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT); 969 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); 970 971 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT | 972 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT | 973 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT | 974 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT | 975 GL_SHADER_STORAGE_BARRIER_BIT); 976 977 glMemoryBarrier(GL_ALL_BARRIER_BITS); 978 979 return NO_ERROR; 980 } 981}; 982 983class BasicAPIBarrierByRegion : public ShaderImageLoadStoreBase 984{ 985 virtual long Run() 986 { 987 glMemoryBarrierByRegion(GL_UNIFORM_BARRIER_BIT); 988 glMemoryBarrierByRegion(GL_TEXTURE_FETCH_BARRIER_BIT); 989 glMemoryBarrierByRegion(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 990 glMemoryBarrierByRegion(GL_FRAMEBUFFER_BARRIER_BIT); 991 glMemoryBarrierByRegion(GL_ATOMIC_COUNTER_BARRIER_BIT); 992 glMemoryBarrierByRegion(GL_SHADER_STORAGE_BARRIER_BIT); 993 994 glMemoryBarrierByRegion(GL_UNIFORM_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT | 995 GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT | 996 GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT); 997 998 glMemoryBarrierByRegion(GL_ALL_BARRIER_BITS); 999 return NO_ERROR; 1000 } 1001}; 1002//----------------------------------------------------------------------------- 1003// 1.1.4 BasicAPITexParam 1004//----------------------------------------------------------------------------- 1005class BasicAPITexParam : public ShaderImageLoadStoreBase 1006{ 1007 GLuint m_texture; 1008 1009 virtual long Setup() 1010 { 1011 m_texture = 0; 1012 return NO_ERROR; 1013 } 1014 virtual long Run() 1015 { 1016 glGenTextures(1, &m_texture); 1017 glBindTexture(GL_TEXTURE_2D, m_texture); 1018 glTexStorage2D(GL_TEXTURE_2D, 5, GL_RG32F, 16, 16); 1019 1020 GLint i; 1021 GLfloat f; 1022 1023 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i); 1024 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE) 1025 { 1026 Output("GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to " 1027 "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."); 1028 return ERROR; 1029 } 1030 glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f); 1031 if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE) 1032 { 1033 Output("GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to " 1034 "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."); 1035 return ERROR; 1036 } 1037 1038 return NO_ERROR; 1039 } 1040 virtual long Cleanup() 1041 { 1042 glDeleteTextures(1, &m_texture); 1043 return NO_ERROR; 1044 } 1045}; 1046//----------------------------------------------------------------------------- 1047// 1.2.1 BasicAllFormatsStore 1048//----------------------------------------------------------------------------- 1049class BasicAllFormatsStoreFS : public ShaderImageLoadStoreBase 1050{ 1051 GLuint m_vao, m_vbo; 1052 1053 virtual long Setup() 1054 { 1055 m_vao = 0; 1056 m_vbo = 0; 1057 return NO_ERROR; 1058 } 1059 virtual long Run() 1060 { 1061 if (!IsVSFSAvailable(0, 1)) 1062 return NOT_SUPPORTED; 1063 1064 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 1065 1066 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1067 return ERROR; 1068 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1069 return ERROR; 1070 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1071 return ERROR; 1072 1073 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1074 return ERROR; 1075 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1076 return ERROR; 1077 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1078 return ERROR; 1079 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1080 return ERROR; 1081 1082 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1083 return ERROR; 1084 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1085 return ERROR; 1086 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1087 return ERROR; 1088 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1089 return ERROR; 1090 1091 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 1092 return ERROR; 1093 1094 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1095 return ERROR; 1096 1097 return NO_ERROR; 1098 } 1099 1100 template <typename T> 1101 bool Write(GLenum internalformat, const T& write_value, const T& expected_value) 1102 { 1103 const char* src_vs = 1104 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 1105 GLuint program = BuildProgram(src_vs, GenFS(internalformat, write_value).c_str()); 1106 const int kSize = 11; 1107 std::vector<T> data(kSize * kSize); 1108 GLuint texture; 1109 glGenTextures(1, &texture); 1110 glUseProgram(program); 1111 1112 GLuint unit = 2; 1113 glBindTexture(GL_TEXTURE_2D, texture); 1114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1116 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); 1117 glBindTexture(GL_TEXTURE_2D, 0); 1118 1119 glViewport(0, 0, kSize, kSize); 1120 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 1121 glBindVertexArray(m_vao); 1122 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1123 1124 glBindTexture(GL_TEXTURE_2D, texture); 1125 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 1126 1127 GLuint c_program = CreateComputeProgram(GenC(write_value)); 1128 std::vector<T> out_data(kSize * kSize); 1129 GLuint m_buffer; 1130 glGenBuffers(1, &m_buffer); 1131 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 1132 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW); 1133 1134 glUseProgram(c_program); 1135 glDispatchCompute(1, 1, 1); 1136 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 1137 T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 1138 for (int i = 0; i < kSize * kSize; ++i) 1139 { 1140 if (!Equal(map_data[i], expected_value, internalformat)) 1141 { 1142 Output("[%d] Value is: %s. Value should be: %s. Format is: %s. Unit is: %d.\n", i, 1143 ToString(map_data[i]).c_str(), ToString(expected_value).c_str(), 1144 FormatEnumToString(internalformat).c_str(), unit); 1145 glDeleteTextures(1, &texture); 1146 glUseProgram(0); 1147 glDeleteProgram(program); 1148 glDeleteProgram(c_program); 1149 glDeleteBuffers(1, &m_buffer); 1150 return false; 1151 } 1152 } 1153 glDeleteTextures(1, &texture); 1154 glUseProgram(0); 1155 glDeleteProgram(program); 1156 glDeleteProgram(c_program); 1157 glDeleteBuffers(1, &m_buffer); 1158 return true; 1159 } 1160 1161 virtual long Cleanup() 1162 { 1163 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 1164 glDeleteVertexArrays(1, &m_vao); 1165 glDeleteBuffers(1, &m_vbo); 1166 return NO_ERROR; 1167 } 1168 1169 template <typename T> 1170 std::string GenFS(GLenum internalformat, const T& value) 1171 { 1172 std::ostringstream os; 1173 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) writeonly uniform " 1174 << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 1175 " imageStore(g_image, coord, " 1176 << TypePrefix<T>() << "vec4" << value << ");" NL " discard;" NL "}"; 1177 return os.str(); 1178 } 1179 1180 template <typename T> 1181 std::string GenC(const T& value) 1182 { 1183 std::ostringstream os; 1184 os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform " 1185 << TypePrefix<T>() << "sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL " " 1186 << TypePrefix<T>() 1187 << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL 1188 " data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL 1189 " //data[gl_LocalInvocationIndex] = " 1190 << value << ";" NL "}"; 1191 return os.str(); 1192 } 1193}; 1194 1195class BasicAllFormatsStoreCS : public ShaderImageLoadStoreBase 1196{ 1197 virtual long Setup() 1198 { 1199 return NO_ERROR; 1200 } 1201 1202 template <typename T> 1203 std::string GenCS(GLenum internalformat, const T& value) 1204 { 1205 std::ostringstream os; 1206 os << NL "#define KSIZE 4" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " 1207 << TypePrefix<T>() 1208 << "image2D g_image;" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "void main() {" NL 1209 " ivec2 thread_xy = ivec2(gl_LocalInvocationID);" NL " imageStore(g_image, thread_xy, " 1210 << TypePrefix<T>() << "vec4" << value << ");" NL "}"; 1211 return os.str(); 1212 } 1213 1214 template <typename T> 1215 std::string GenC(const T& value) 1216 { 1217 std::ostringstream os; 1218 os << NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform " 1219 << TypePrefix<T>() << "sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL " " 1220 << TypePrefix<T>() 1221 << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL 1222 " data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL 1223 " //data[gl_LocalInvocationIndex] = " 1224 << TypePrefix<T>() << "vec4" << value << ";" NL "}"; 1225 return os.str(); 1226 } 1227 1228 template <typename T> 1229 bool WriteCS(GLenum internalformat, const T& write_value, const T& expected_value) 1230 { 1231 const int kSize = 4; 1232 GLuint program = CreateComputeProgram(GenCS(internalformat, write_value)); 1233 1234 std::vector<T> data(kSize * kSize); 1235 GLuint texture; 1236 glGenTextures(1, &texture); 1237 1238 GLuint unit = 0; 1239 glBindTexture(GL_TEXTURE_2D, texture); 1240 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1242 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); 1243 glBindTexture(GL_TEXTURE_2D, 0); 1244 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); 1245 glUseProgram(program); 1246 glDispatchCompute(1, 1, 1); 1247 1248 glBindTexture(GL_TEXTURE_2D, texture); 1249 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); 1250 1251 GLuint c_program = CreateComputeProgram(GenC(expected_value)); 1252 std::vector<T> out_data(kSize * kSize); 1253 GLuint m_buffer; 1254 glGenBuffers(1, &m_buffer); 1255 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 1256 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW); 1257 1258 glUseProgram(c_program); 1259 glDispatchCompute(1, 1, 1); 1260 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 1261 T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 1262 for (int i = 0; i < kSize * kSize; ++i) 1263 { 1264 if (!Equal(map_data[i], expected_value, internalformat)) 1265 { 1266 Output("[%d] Value is: %s. Value should be: %s. Format is: %s. Unit is: %d.\n", i, 1267 ToString(map_data[i]).c_str(), ToString(expected_value).c_str(), 1268 FormatEnumToString(internalformat).c_str(), unit); 1269 glDeleteTextures(1, &texture); 1270 glUseProgram(0); 1271 glDeleteProgram(program); 1272 glDeleteProgram(c_program); 1273 glDeleteBuffers(1, &m_buffer); 1274 return false; 1275 } 1276 } 1277 glDeleteTextures(1, &texture); 1278 glUseProgram(0); 1279 glDeleteProgram(program); 1280 glDeleteProgram(c_program); 1281 glDeleteBuffers(1, &m_buffer); 1282 1283 return true; 1284 } 1285 1286 virtual long Run() 1287 { 1288 1289 if (!WriteCS(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1290 return ERROR; 1291 if (!WriteCS(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 1292 return ERROR; 1293 if (!WriteCS(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 1294 return ERROR; 1295 1296 if (!WriteCS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1297 return ERROR; 1298 if (!WriteCS(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 1299 return ERROR; 1300 if (!WriteCS(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1301 return ERROR; 1302 if (!WriteCS(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1303 return ERROR; 1304 1305 if (!WriteCS(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1306 return ERROR; 1307 if (!WriteCS(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 1308 return ERROR; 1309 if (!WriteCS(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1310 return ERROR; 1311 if (!WriteCS(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 1312 return ERROR; 1313 1314 if (!WriteCS(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 1315 return ERROR; 1316 1317 if (!WriteCS(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 1318 return ERROR; 1319 1320 return NO_ERROR; 1321 } 1322 1323 virtual long Cleanup() 1324 { 1325 return NO_ERROR; 1326 } 1327}; 1328//----------------------------------------------------------------------------- 1329// 1.2.2 BasicAllFormatsLoad 1330//----------------------------------------------------------------------------- 1331class BasicAllFormatsLoadFS : public ShaderImageLoadStoreBase 1332{ 1333 GLuint m_vao, m_vbo; 1334 1335 virtual long Setup() 1336 { 1337 m_vao = 0; 1338 m_vbo = 0; 1339 return NO_ERROR; 1340 } 1341 virtual long Run() 1342 { 1343 if (!IsVSFSAvailable(0, 1) || !IsSSBInVSFSAvailable(1)) 1344 return NOT_SUPPORTED; 1345 1346 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 1347 1348 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT)) 1349 return ERROR; 1350 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f), GL_RED, GL_FLOAT)) 1351 return ERROR; 1352 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT)) 1353 return ERROR; 1354 1355 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_INT)) 1356 return ERROR; 1357 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1), GL_RED_INTEGER, GL_INT)) 1358 return ERROR; 1359 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_SHORT)) 1360 return ERROR; 1361 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_BYTE)) 1362 return ERROR; 1363 1364 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) 1365 return ERROR; 1366 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1), GL_RED_INTEGER, GL_UNSIGNED_INT)) 1367 return ERROR; 1368 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_SHORT)) 1369 return ERROR; 1370 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_BYTE)) 1371 return ERROR; 1372 1373 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f), GL_RGBA, GL_UNSIGNED_BYTE)) 1374 return ERROR; 1375 1376 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f), GL_RGBA, GL_BYTE)) 1377 return ERROR; 1378 1379 return NO_ERROR; 1380 } 1381 1382 template <typename T> 1383 bool Read(GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type) 1384 { 1385 const char* src_vs = 1386 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 1387 GLuint program = BuildProgram(src_vs, GenFS(internalformat, expected_value).c_str()); 1388 const int kSize = 11; 1389 ShortByteData<T> d(kSize, value, internalformat, format); 1390 GLuint texture; 1391 glGenTextures(1, &texture); 1392 GLuint unit = 1; 1393 glBindTexture(GL_TEXTURE_2D, texture); 1394 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1395 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1396 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); 1397 if (Shorts(internalformat)) 1398 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datas[0]); 1399 else if (Bytes(internalformat)) 1400 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datab[0]); 1401 else 1402 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.data[0]); 1403 glBindTexture(GL_TEXTURE_2D, 0); 1404 1405 glViewport(0, 0, kSize, kSize); 1406 glClear(GL_COLOR_BUFFER_BIT); 1407 glUseProgram(program); 1408 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 1409 glBindVertexArray(m_vao); 1410 1411 std::vector<T> out_data(kSize * kSize); 1412 GLuint m_buffer; 1413 glGenBuffers(1, &m_buffer); 1414 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 1415 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW); 1416 1417 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1418 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 1419 T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 1420 for (int i = 0; i < kSize * kSize; ++i) 1421 { 1422 if (!Equal(map_data[i], expected_value, internalformat)) 1423 { 1424 Output("[%d] Value is: %s. Value should be: %s. Format is: %s. Unit is: %d.\n", i, 1425 ToString(map_data[i]).c_str(), ToString(expected_value).c_str(), 1426 FormatEnumToString(internalformat).c_str(), unit); 1427 glUseProgram(0); 1428 glDeleteProgram(program); 1429 glDeleteTextures(1, &texture); 1430 glDeleteBuffers(1, &m_buffer); 1431 return false; 1432 } 1433 } 1434 glUseProgram(0); 1435 glDeleteProgram(program); 1436 glDeleteTextures(1, &texture); 1437 glDeleteBuffers(1, &m_buffer); 1438 return true; 1439 } 1440 1441 virtual long Cleanup() 1442 { 1443 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 1444 glDeleteVertexArrays(1, &m_vao); 1445 glDeleteBuffers(1, &m_vbo); 1446 return NO_ERROR; 1447 } 1448 1449 template <typename T> 1450 std::string GenFS(GLenum internalformat, const T& expected_value) 1451 { 1452 std::ostringstream os; 1453 os << NL "#define KSIZE 11" NL "layout(" << FormatEnumToString(internalformat) 1454 << ", binding = 1) readonly uniform " << TypePrefix<T>() 1455 << "image2D g_image;" NL "layout(std430) buffer OutputBuffer {" NL " " << TypePrefix<T>() 1456 << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " " 1457 << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL " data[coord.y * KSIZE + coord.x] = v;" NL 1458 " //data[coord.y * KSIZE + coord.x] = " 1459 << TypePrefix<T>() << "vec4" << expected_value << ";" NL " discard;" NL "}"; 1460 return os.str(); 1461 } 1462}; 1463 1464class BasicAllFormatsLoadCS : public ShaderImageLoadStoreBase 1465{ 1466 virtual long Setup() 1467 { 1468 return NO_ERROR; 1469 } 1470 1471 template <typename T> 1472 std::string GenCS(GLenum internalformat, const T& expected_value) 1473 { 1474 std::ostringstream os; 1475 os << NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "layout(" 1476 << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform " << TypePrefix<T>() 1477 << "image2D g_image;" NL "layout(std430) buffer OutputBuffer {" NL " " << TypePrefix<T>() 1478 << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL 1479 " " 1480 << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL " data[gl_LocalInvocationIndex] = v;" NL 1481 " //data[gl_LocalInvocationIndex] = " 1482 << TypePrefix<T>() << "vec4" << expected_value << ";" NL "}"; 1483 return os.str(); 1484 } 1485 1486 virtual long Run() 1487 { 1488 if (!ReadCS(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT)) 1489 return ERROR; 1490 if (!ReadCS(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f), GL_RED, GL_FLOAT)) 1491 return ERROR; 1492 if (!ReadCS(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT)) 1493 return ERROR; 1494 1495 if (!ReadCS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_INT)) 1496 return ERROR; 1497 if (!ReadCS(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1), GL_RED_INTEGER, GL_INT)) 1498 return ERROR; 1499 if (!ReadCS(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_SHORT)) 1500 return ERROR; 1501 if (!ReadCS(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_BYTE)) 1502 return ERROR; 1503 1504 if (!ReadCS(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) 1505 return ERROR; 1506 if (!ReadCS(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1), GL_RED_INTEGER, GL_UNSIGNED_INT)) 1507 return ERROR; 1508 if (!ReadCS(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_SHORT)) 1509 return ERROR; 1510 if (!ReadCS(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_BYTE)) 1511 return ERROR; 1512 1513 if (!ReadCS(GL_RGBA8, vec4(1.0f), vec4(1.0f), GL_RGBA, GL_UNSIGNED_BYTE)) 1514 return ERROR; 1515 1516 if (!ReadCS(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f), GL_RGBA, GL_BYTE)) 1517 return ERROR; 1518 1519 return NO_ERROR; 1520 } 1521 1522 template <typename T> 1523 bool ReadCS(GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type) 1524 { 1525 GLuint program = CreateComputeProgram(GenCS(internalformat, expected_value)); 1526 const int kSize = 4; 1527 ShortByteData<T> d(kSize, value, internalformat, format); 1528 GLuint texture; 1529 glGenTextures(1, &texture); 1530 1531 GLuint unit = 1; 1532 glBindTexture(GL_TEXTURE_2D, texture); 1533 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1534 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1535 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); 1536 if (Shorts(internalformat)) 1537 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datas[0]); 1538 else if (Bytes(internalformat)) 1539 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datab[0]); 1540 else 1541 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.data[0]); 1542 glBindTexture(GL_TEXTURE_2D, 0); 1543 1544 glUseProgram(program); 1545 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); 1546 1547 std::vector<T> out_data(kSize * kSize); 1548 GLuint m_buffer; 1549 glGenBuffers(1, &m_buffer); 1550 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 1551 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW); 1552 1553 glDispatchCompute(1, 1, 1); 1554 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 1555 T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 1556 for (int i = 0; i < kSize * kSize; ++i) 1557 { 1558 if (!Equal(map_data[i], expected_value, internalformat)) 1559 { 1560 Output("[%d] Value is: %s. Value should be: %s. Format is: %s. Unit is: %d.\n", i, 1561 ToString(map_data[i]).c_str(), ToString(expected_value).c_str(), 1562 FormatEnumToString(internalformat).c_str(), unit); 1563 glUseProgram(0); 1564 glDeleteProgram(program); 1565 glDeleteTextures(1, &texture); 1566 glDeleteBuffers(1, &m_buffer); 1567 return false; 1568 } 1569 } 1570 glUseProgram(0); 1571 glDeleteProgram(program); 1572 glDeleteTextures(1, &texture); 1573 glDeleteBuffers(1, &m_buffer); 1574 return true; 1575 } 1576 virtual long Cleanup() 1577 { 1578 return NO_ERROR; 1579 } 1580}; 1581 1582class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase 1583{ 1584 virtual long Run() 1585 { 1586 1587 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(2.0f, 4.0f, 6.0f, 8.0f), GL_RGBA, GL_FLOAT)) 1588 return ERROR; 1589 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(2.0f, 0.0f, 0.0f, 1.0f), GL_RED, GL_FLOAT)) 1590 return ERROR; 1591 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(2.0f, 4.0f, 6.0f, 8.0f), GL_RGBA, GL_FLOAT)) 1592 return ERROR; 1593 1594 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(2, -4, 6, -8), GL_RGBA_INTEGER, GL_INT)) 1595 return ERROR; 1596 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(2, 0, 0, 1), GL_RED_INTEGER, GL_INT)) 1597 return ERROR; 1598 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(2, -4, 6, -8), GL_RGBA_INTEGER, GL_SHORT)) 1599 return ERROR; 1600 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(2, -4, 6, -8), GL_RGBA_INTEGER, GL_BYTE)) 1601 return ERROR; 1602 1603 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 2, 4, 6), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) 1604 return ERROR; 1605 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(14, 0, 0, 1), GL_RED_INTEGER, GL_UNSIGNED_INT)) 1606 return ERROR; 1607 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 2, 4, 6), GL_RGBA_INTEGER, GL_UNSIGNED_SHORT)) 1608 return ERROR; 1609 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 2, 4, 6), GL_RGBA_INTEGER, GL_UNSIGNED_BYTE)) 1610 return ERROR; 1611 1612 if (!Read(GL_RGBA8, vec4(0.5f), vec4(1.0f), GL_RGBA, GL_UNSIGNED_BYTE)) 1613 return ERROR; 1614 if (!Read(GL_RGBA8_SNORM, vec4(0.5f, 0.0f, 0.5f, -0.5f), vec4(1.0f, 0.0f, 1.0f, -1.0f), GL_RGBA, GL_BYTE)) 1615 return ERROR; 1616 1617 return NO_ERROR; 1618 } 1619 1620 template <typename T> 1621 bool Read(GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type) 1622 { 1623 GLuint program = CreateComputeProgram(GenCS(internalformat, expected_value)); 1624 1625 const int kSize = 8; 1626 ShortByteData<T> d(kSize, value, internalformat, format); 1627 GLuint texture[2]; 1628 glGenTextures(2, texture); 1629 1630 /* read texture */ 1631 { 1632 glBindTexture(GL_TEXTURE_2D, texture[0]); 1633 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1634 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1635 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); 1636 if (Shorts(internalformat)) 1637 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datas[0]); 1638 else if (Bytes(internalformat)) 1639 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datab[0]); 1640 else 1641 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.data[0]); 1642 } 1643 /* write texture */ 1644 { 1645 glBindTexture(GL_TEXTURE_2D, texture[1]); 1646 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1647 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1648 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); 1649 } 1650 glBindTexture(GL_TEXTURE_2D, 0); 1651 1652 glUseProgram(program); 1653 1654 glBindImageTexture(2, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); 1655 glBindImageTexture(3, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); 1656 1657 glDispatchCompute(1, 1, 1); 1658 1659 glBindTexture(GL_TEXTURE_2D, texture[1]); 1660 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); 1661 1662 GLuint c_program = CreateComputeProgram(GenC(expected_value)); 1663 std::vector<T> out_data(kSize * kSize); 1664 GLuint m_buffer; 1665 glGenBuffers(1, &m_buffer); 1666 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 1667 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW); 1668 1669 glUseProgram(c_program); 1670 glDispatchCompute(1, 1, 1); 1671 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 1672 T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 1673 for (int i = 0; i < kSize * kSize; ++i) 1674 { 1675 if (!Equal(map_data[i], expected_value, internalformat)) 1676 { 1677 Output("[%d] Value is: %s. Value should be: %s. Format is: %s.\n", i, ToString(map_data[i]).c_str(), 1678 ToString(expected_value).c_str(), FormatEnumToString(internalformat).c_str()); 1679 glDeleteTextures(2, texture); 1680 glUseProgram(0); 1681 glDeleteProgram(program); 1682 glDeleteProgram(c_program); 1683 glDeleteBuffers(1, &m_buffer); 1684 return false; 1685 } 1686 } 1687 glDeleteTextures(2, texture); 1688 glUseProgram(0); 1689 glDeleteProgram(program); 1690 glDeleteProgram(c_program); 1691 glDeleteBuffers(1, &m_buffer); 1692 1693 return true; 1694 } 1695 1696 template <typename T> 1697 std::string GenCS(GLenum internalformat, const T& expected_value) 1698 { 1699 std::ostringstream os; 1700 os << NL "#define KSIZE 8" NL "layout(local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "layout(" 1701 << FormatEnumToString(internalformat) << ", binding = 2) readonly uniform " << TypePrefix<T>() 1702 << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) 1703 << ", binding = 3) writeonly uniform " << TypePrefix<T>() 1704 << "image2D g_image_write;" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL " " 1705 << TypePrefix<T>() << "vec4 v = imageLoad(g_image_read, coord);" NL 1706 " imageStore(g_image_write, coord, v+v);" NL " //imageStore(g_image_write, coord, " 1707 << TypePrefix<T>() << "vec4" << expected_value << ");" NL "}"; 1708 return os.str(); 1709 } 1710 1711 template <typename T> 1712 std::string GenC(const T& value) 1713 { 1714 std::ostringstream os; 1715 os << NL "#define KSIZE 8" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform " 1716 << TypePrefix<T>() << "sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL " " 1717 << TypePrefix<T>() 1718 << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL 1719 " data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL 1720 " //data[gl_LocalInvocationIndex] = " 1721 << TypePrefix<T>() << "vec4" << value << ";" NL "}"; 1722 return os.str(); 1723 } 1724}; 1725//----------------------------------------------------------------------------- 1726// 1.3.1 BasicAllTargetsStore 1727//----------------------------------------------------------------------------- 1728class BasicAllTargetsStoreFS : public ShaderImageLoadStoreBase 1729{ 1730 GLuint m_vao; 1731 GLuint m_vbo; 1732 1733 virtual long Setup() 1734 { 1735 m_vao = 0; 1736 m_vbo = 0; 1737 return NO_ERROR; 1738 } 1739 1740 virtual long Run() 1741 { 1742 if (!IsVSFSAvailable(0, 4)) 1743 return NOT_SUPPORTED; 1744 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 1745 1746 if (!Write(T2D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 1747 return ERROR; 1748 if (!Write(T2D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1749 return ERROR; 1750 if (!Write(T2D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 1751 return ERROR; 1752 if (!Write(T3D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 1753 return ERROR; 1754 if (!Write(T3D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1755 return ERROR; 1756 if (!Write(T3D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 1757 return ERROR; 1758 if (!Write(TCM, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 1759 return ERROR; 1760 if (!Write(TCM, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1761 return ERROR; 1762 if (!Write(TCM, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 1763 return ERROR; 1764 if (!Write(T2DA, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 1765 return ERROR; 1766 if (!Write(T2DA, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1767 return ERROR; 1768 if (!Write(T2DA, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 1769 return ERROR; 1770 1771 return NO_ERROR; 1772 } 1773 1774 virtual long Cleanup() 1775 { 1776 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 1777 glDeleteVertexArrays(1, &m_vao); 1778 glDeleteBuffers(1, &m_vbo); 1779 glActiveTexture(GL_TEXTURE0); 1780 return NO_ERROR; 1781 } 1782 1783 template <typename T> 1784 bool Write(int target, GLenum internalformat, const T& write_value, const T& expected_value) 1785 { 1786 const char* src_vs = 1787 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 1788 const GLuint program = BuildProgram(src_vs, GenFS(target, internalformat, write_value).c_str()); 1789 GLuint textures[8]; 1790 glGenTextures(8, textures); 1791 1792 const int kSize = 11; 1793 std::vector<T> data(kSize * kSize * 2); 1794 1795 glBindTexture(GL_TEXTURE_2D, textures[1]); 1796 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1797 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1798 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); 1799 glBindTexture(GL_TEXTURE_2D, 0); 1800 1801 glBindTexture(GL_TEXTURE_3D, textures[2]); 1802 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1803 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1804 glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2); 1805 glBindTexture(GL_TEXTURE_3D, 0); 1806 1807 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); 1808 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1809 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1810 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize); 1811 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 1812 1813 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); 1814 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1815 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1816 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2); 1817 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 1818 1819 glBindImageTexture(0, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); // 2D 1820 glBindImageTexture(1, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 3D 1821 glBindImageTexture(2, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // Cube 1822 glBindImageTexture(3, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 2DArray 1823 1824 glUseProgram(program); 1825 glBindVertexArray(m_vao); 1826 glViewport(0, 0, kSize, kSize); 1827 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1828 1829 glActiveTexture(GL_TEXTURE1); 1830 glBindTexture(GL_TEXTURE_2D, textures[1]); 1831 glActiveTexture(GL_TEXTURE2); 1832 glBindTexture(GL_TEXTURE_3D, textures[2]); 1833 glActiveTexture(GL_TEXTURE3); 1834 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); 1835 glActiveTexture(GL_TEXTURE4); 1836 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); 1837 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); 1838 1839 GLuint c_program = CreateComputeProgram(GenC(write_value)); 1840 std::vector<T> out_data2D(kSize * kSize * 6); 1841 std::vector<T> out_data3D(kSize * kSize * 6); 1842 std::vector<T> out_dataCube(kSize * kSize * 6); 1843 std::vector<T> out_data2DArray(kSize * kSize * 6); 1844 GLuint m_buffer[4]; 1845 glGenBuffers(4, m_buffer); 1846 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[0]); 1847 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 1848 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]); 1849 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 1850 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[2]); 1851 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 1852 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]); 1853 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 1854 1855 glUseProgram(c_program); 1856 glUniform1i(glGetUniformLocation(c_program, "g_sampler_2d"), 1); 1857 glUniform1i(glGetUniformLocation(c_program, "g_sampler_3d"), 2); 1858 glUniform1i(glGetUniformLocation(c_program, "g_sampler_cube"), 3); 1859 glUniform1i(glGetUniformLocation(c_program, "g_sampler_2darray"), 4); 1860 glDispatchCompute(1, 1, 1); 1861 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 1862 1863 bool status = true; 1864 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]); 1865 T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 1866 int layers = 2; 1867 if (target == T2D) 1868 layers = 1; 1869 if (target == TCM) 1870 layers = 6; 1871 status = CompareValues(map_data, kSize, expected_value, internalformat, layers); 1872 if (!status) 1873 Output("%d target, %s format failed. \n", target, FormatEnumToString(internalformat).c_str()); 1874 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); 1875 1876 glDeleteTextures(8, textures); 1877 glUseProgram(0); 1878 glDeleteProgram(program); 1879 glDeleteProgram(c_program); 1880 glDeleteBuffers(4, m_buffer); 1881 1882 return status; 1883 } 1884 1885 template <typename T> 1886 std::string GenFS(int target, GLenum internalformat, const T& write_value) 1887 { 1888 std::ostringstream os; 1889 switch (target) 1890 { 1891 case T2D: 1892 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) writeonly uniform " 1893 << TypePrefix<T>() << "image2D g_image_2d;"; 1894 break; 1895 case T3D: 1896 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) writeonly uniform " 1897 << TypePrefix<T>() << "image3D g_image_3d;"; 1898 break; 1899 case TCM: 1900 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) writeonly uniform " 1901 << TypePrefix<T>() << "imageCube g_image_cube;"; 1902 break; 1903 case T2DA: 1904 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) writeonly uniform " 1905 << TypePrefix<T>() << "image2DArray g_image_2darray;"; 1906 break; 1907 } 1908 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);"; 1909 switch (target) 1910 { 1911 case T2D: 1912 os << NL " imageStore(g_image_2d, coord, " << TypePrefix<T>() << "vec4" << write_value << ");"; 1913 break; 1914 case T3D: 1915 os << NL " imageStore(g_image_3d, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value 1916 << ");" NL " imageStore(g_image_3d, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value 1917 << ");"; 1918 break; 1919 case TCM: 1920 os << NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value 1921 << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value 1922 << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4" << write_value 1923 << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4" << write_value 1924 << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4" << write_value 1925 << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4" << write_value 1926 << ");"; 1927 break; 1928 case T2DA: 1929 os << NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value 1930 << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value 1931 << ");"; 1932 break; 1933 } 1934 os << NL " discard;" NL "}"; 1935 return os.str(); 1936 } 1937 1938 template <typename T> 1939 std::string GenC(const T& write_value) 1940 { 1941 std::ostringstream os; 1942 os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform " 1943 << TypePrefix<T>() << "sampler2D g_sampler_2d;" NL "uniform " << TypePrefix<T>() 1944 << "sampler3D g_sampler_3d;" NL "uniform " << TypePrefix<T>() << "samplerCube g_sampler_cube;" NL "uniform " 1945 << TypePrefix<T>() 1946 << "sampler2DArray g_sampler_2darray;" NL "layout(std430, binding = 1) buffer OutputBuffer2D {" NL " " 1947 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;" NL 1948 "layout(std430, binding = 0) buffer OutputBuffer3D {" NL " " 1949 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;" NL 1950 "layout(std430, binding = 3) buffer OutputBufferCube {" NL " " 1951 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;" NL 1952 "layout(std430, binding = 2) buffer OutputBuffer2DArray {" NL " " 1953 << TypePrefix<T>() 1954 << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;" NL "void main() {" NL 1955 " int cubemap_i = 2 * int(gl_LocalInvocationID.x) - KSIZE + 1;" NL 1956 " int cubemap_j = 2 * int(gl_LocalInvocationID.y) - KSIZE + 1;" NL 1957 " uint layer = uint(KSIZE * KSIZE);" NL 1958 " g_buff_2d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_2d, ivec2(gl_LocalInvocationID), 0);" NL 1959 " g_buff_3d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_3d, ivec3(gl_LocalInvocationID.xy, 0), " 1960 "0);" NL " g_buff_3d.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_3d, " 1961 "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL " g_buff_2darray.data[gl_LocalInvocationIndex] = " 1962 "texelFetch(g_sampler_2darray, " 1963 "ivec3(gl_LocalInvocationID.xy, 0), 0);" NL 1964 " g_buff_2darray.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_2darray, " 1965 "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL " g_buff_cube.data[gl_LocalInvocationIndex] = " 1966 "texture(g_sampler_cube, vec3(KSIZE,cubemap_i,cubemap_j));" NL 1967 " g_buff_cube.data[gl_LocalInvocationIndex + layer] = texture(g_sampler_cube, " 1968 "vec3(KSIZE,cubemap_i,cubemap_j));" NL " g_buff_cube.data[gl_LocalInvocationIndex + 2u * layer] = " 1969 "texture(g_sampler_cube, vec3(cubemap_i,KSIZE,cubemap_j));" NL 1970 " g_buff_cube.data[gl_LocalInvocationIndex + 3u * layer] = texture(g_sampler_cube, " 1971 "vec3(cubemap_i,KSIZE,cubemap_j));" NL " g_buff_cube.data[gl_LocalInvocationIndex + 4u * layer] = " 1972 "texture(g_sampler_cube, vec3(cubemap_i,cubemap_j,KSIZE));" NL 1973 " g_buff_cube.data[gl_LocalInvocationIndex + 5u * layer] = texture(g_sampler_cube, " 1974 "vec3(cubemap_i,cubemap_j,KSIZE));" NL " //g_buff_2d.data[gl_LocalInvocationIndex] = " 1975 << write_value << ";" NL "}"; 1976 return os.str(); 1977 } 1978}; 1979 1980class BasicAllTargetsStoreCS : public ShaderImageLoadStoreBase 1981{ 1982 virtual long Setup() 1983 { 1984 return NO_ERROR; 1985 } 1986 virtual long Run() 1987 { 1988 1989 if (!Write(T2D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 1990 return ERROR; 1991 if (!Write(T2D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1992 return ERROR; 1993 if (!Write(T2D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 1994 return ERROR; 1995 if (!Write(T3D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 1996 return ERROR; 1997 if (!Write(T3D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 1998 return ERROR; 1999 if (!Write(T3D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 2000 return ERROR; 2001 if (!Write(TCM, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 2002 return ERROR; 2003 if (!Write(TCM, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 2004 return ERROR; 2005 if (!Write(TCM, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2006 return ERROR; 2007 if (!Write(T2DA, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f))) 2008 return ERROR; 2009 if (!Write(T2DA, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 2010 return ERROR; 2011 if (!Write(T2DA, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4))) 2012 return ERROR; 2013 2014 return NO_ERROR; 2015 } 2016 virtual long Cleanup() 2017 { 2018 glActiveTexture(GL_TEXTURE0); 2019 return NO_ERROR; 2020 } 2021 2022 template <typename T> 2023 bool Write(int target, GLenum internalformat, const T& write_value, const T& expected_value) 2024 { 2025 const GLuint program = CreateComputeProgram(GenCS(target, internalformat, write_value)); 2026 GLuint textures[8]; 2027 glGenTextures(8, textures); 2028 2029 const int kSize = 11; 2030 std::vector<T> data(kSize * kSize * 2); 2031 2032 glBindTexture(GL_TEXTURE_2D, textures[1]); 2033 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2034 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2035 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); 2036 glBindTexture(GL_TEXTURE_2D, 0); 2037 2038 glBindTexture(GL_TEXTURE_3D, textures[2]); 2039 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2040 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2041 glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2); 2042 glBindTexture(GL_TEXTURE_3D, 0); 2043 2044 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); 2045 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2046 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2047 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize); 2048 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 2049 2050 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); 2051 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2052 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2053 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2); 2054 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 2055 2056 glBindImageTexture(0, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); // 2D 2057 glBindImageTexture(1, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 3D 2058 glBindImageTexture(2, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // Cube 2059 glBindImageTexture(3, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 2DArray 2060 2061 glUseProgram(program); 2062 glDispatchCompute(1, 1, 1); 2063 2064 glActiveTexture(GL_TEXTURE1); 2065 glBindTexture(GL_TEXTURE_2D, textures[1]); 2066 glActiveTexture(GL_TEXTURE2); 2067 glBindTexture(GL_TEXTURE_3D, textures[2]); 2068 glActiveTexture(GL_TEXTURE3); 2069 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); 2070 glActiveTexture(GL_TEXTURE4); 2071 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); 2072 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); 2073 2074 GLuint c_program = CreateComputeProgram(GenC(write_value)); 2075 std::vector<T> out_data2D(kSize * kSize * 6); 2076 std::vector<T> out_data3D(kSize * kSize * 6); 2077 std::vector<T> out_dataCube(kSize * kSize * 6); 2078 std::vector<T> out_data2DArray(kSize * kSize * 6); 2079 GLuint m_buffer[4]; 2080 glGenBuffers(4, m_buffer); 2081 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]); 2082 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 2083 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]); 2084 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 2085 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[2]); 2086 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 2087 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[3]); 2088 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 2089 2090 glUseProgram(c_program); 2091 glUniform1i(glGetUniformLocation(c_program, "g_sampler_2d"), 1); 2092 glUniform1i(glGetUniformLocation(c_program, "g_sampler_3d"), 2); 2093 glUniform1i(glGetUniformLocation(c_program, "g_sampler_cube"), 3); 2094 glUniform1i(glGetUniformLocation(c_program, "g_sampler_2darray"), 4); 2095 2096 glDispatchCompute(1, 1, 1); 2097 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 2098 2099 bool status = true; 2100 2101 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]); 2102 T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 2103 int layers = 2; 2104 if (target == T2D) 2105 layers = 1; 2106 if (target == TCM) 2107 layers = 6; 2108 status = CompareValues(map_data, kSize, expected_value, internalformat, layers); 2109 if (!status) 2110 Output("%d target, %s format failed. \n", target, FormatEnumToString(internalformat).c_str()); 2111 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); 2112 2113 glDeleteTextures(8, textures); 2114 glUseProgram(0); 2115 glDeleteProgram(program); 2116 glDeleteProgram(c_program); 2117 glDeleteBuffers(4, m_buffer); 2118 2119 return status; 2120 } 2121 2122 template <typename T> 2123 std::string GenCS(int target, GLenum internalformat, const T& write_value) 2124 { 2125 std::ostringstream os; 2126 os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;"; 2127 switch (target) 2128 { 2129 case T2D: 2130 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) writeonly uniform " 2131 << TypePrefix<T>() << "image2D g_image_2d;"; 2132 break; 2133 case T3D: 2134 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) writeonly uniform " 2135 << TypePrefix<T>() << "image3D g_image_3d;"; 2136 break; 2137 case TCM: 2138 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) writeonly uniform " 2139 << TypePrefix<T>() << "imageCube g_image_cube;"; 2140 break; 2141 case T2DA: 2142 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) writeonly uniform " 2143 << TypePrefix<T>() << "image2DArray g_image_2darray;"; 2144 break; 2145 } 2146 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);"; 2147 2148 switch (target) 2149 { 2150 case T2D: 2151 os << NL " imageStore(g_image_2d, coord, " << TypePrefix<T>() << "vec4" << write_value << ");"; 2152 break; 2153 case T3D: 2154 os << NL " imageStore(g_image_3d, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value 2155 << ");" NL " imageStore(g_image_3d, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value 2156 << ");"; 2157 break; 2158 case TCM: 2159 os << NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value 2160 << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value 2161 << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4" << write_value 2162 << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4" << write_value 2163 << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4" << write_value 2164 << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4" << write_value 2165 << ");"; 2166 break; 2167 case T2DA: 2168 os << NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value 2169 << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value 2170 << ");"; 2171 break; 2172 } 2173 os << NL "}"; 2174 return os.str(); 2175 } 2176 2177 template <typename T> 2178 std::string GenC(const T& write_value) 2179 { 2180 std::ostringstream os; 2181 os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform " 2182 << TypePrefix<T>() << "sampler2D g_sampler_2d;" NL "uniform " << TypePrefix<T>() 2183 << "sampler3D g_sampler_3d;" NL "uniform " << TypePrefix<T>() << "samplerCube g_sampler_cube;" NL "uniform " 2184 << TypePrefix<T>() 2185 << "sampler2DArray g_sampler_2darray;" NL "layout(std430, binding = 0) buffer OutputBuffer2D {" NL " " 2186 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;" NL 2187 "layout(std430, binding = 1) buffer OutputBuffer3D {" NL " " 2188 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;" NL 2189 "layout(std430, binding = 2) buffer OutputBufferCube {" NL " " 2190 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;" NL 2191 "layout(std430, binding = 3) buffer OutputBuffer2DArray {" NL " " 2192 << TypePrefix<T>() 2193 << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;" NL "void main() {" NL 2194 " int cubemap_i = 2 * int(gl_LocalInvocationID.x) - KSIZE + 1;" NL 2195 " int cubemap_j = 2 * int(gl_LocalInvocationID.y) - KSIZE + 1;" NL 2196 " uint layer = uint(KSIZE * KSIZE);" NL 2197 " g_buff_2d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_2d, ivec2(gl_LocalInvocationID), 0);" NL 2198 " g_buff_3d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_3d, ivec3(gl_LocalInvocationID.xy, 0), " 2199 "0);" NL " g_buff_3d.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_3d, " 2200 "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL " g_buff_2darray.data[gl_LocalInvocationIndex] = " 2201 "texelFetch(g_sampler_2darray, " 2202 "ivec3(gl_LocalInvocationID.xy, 0), 0);" NL 2203 " g_buff_2darray.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_2darray, " 2204 "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL " g_buff_cube.data[gl_LocalInvocationIndex] = " 2205 "texture(g_sampler_cube, vec3(KSIZE,cubemap_i,cubemap_j));" NL 2206 " g_buff_cube.data[gl_LocalInvocationIndex + layer] = texture(g_sampler_cube, " 2207 "vec3(KSIZE,cubemap_i,cubemap_j));" NL " g_buff_cube.data[gl_LocalInvocationIndex + 2u * layer] = " 2208 "texture(g_sampler_cube, vec3(cubemap_i,KSIZE,cubemap_j));" NL 2209 " g_buff_cube.data[gl_LocalInvocationIndex + 3u * layer] = texture(g_sampler_cube, " 2210 "vec3(cubemap_i,KSIZE,cubemap_j));" NL " g_buff_cube.data[gl_LocalInvocationIndex + 4u * layer] = " 2211 "texture(g_sampler_cube, vec3(cubemap_i,cubemap_j,KSIZE));" NL 2212 " g_buff_cube.data[gl_LocalInvocationIndex + 5u * layer] = texture(g_sampler_cube, " 2213 "vec3(cubemap_i,cubemap_j,KSIZE));" NL " //g_buff_2d.data[gl_LocalInvocationIndex] = " 2214 << write_value << ";" NL "}"; 2215 return os.str(); 2216 } 2217}; 2218//----------------------------------------------------------------------------- 2219// 1.3.2.1 BasicAllTargetsLoad 2220//----------------------------------------------------------------------------- 2221class BasicAllTargetsLoadFS : public ShaderImageLoadStoreBase 2222{ 2223 GLuint m_vao; 2224 GLuint m_vbo; 2225 2226 virtual long Setup() 2227 { 2228 m_vao = 0; 2229 m_vbo = 0; 2230 return NO_ERROR; 2231 } 2232 2233 virtual long Run() 2234 { 2235 if (!IsVSFSAvailable(0, 4) || !IsSSBInVSFSAvailable(4)) 2236 return NOT_SUPPORTED; 2237 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 2238 2239 if (!Read(T2D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA, 2240 GL_FLOAT)) 2241 return ERROR; 2242 if (!Read(T2D, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT)) 2243 return ERROR; 2244 if (!Read(T2D, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) 2245 return ERROR; 2246 if (!Read(T3D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA, 2247 GL_FLOAT)) 2248 return ERROR; 2249 if (!Read(T3D, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT)) 2250 return ERROR; 2251 if (!Read(T3D, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) 2252 return ERROR; 2253 if (!Read(TCM, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA, 2254 GL_FLOAT)) 2255 return ERROR; 2256 if (!Read(TCM, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT)) 2257 return ERROR; 2258 if (!Read(TCM, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) 2259 return ERROR; 2260 if (!Read(T2DA, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA, 2261 GL_FLOAT)) 2262 return ERROR; 2263 if (!Read(T2DA, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT)) 2264 return ERROR; 2265 if (!Read(T2DA, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, 2266 GL_UNSIGNED_INT)) 2267 return ERROR; 2268 2269 return NO_ERROR; 2270 } 2271 2272 virtual long Cleanup() 2273 { 2274 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 2275 glDeleteVertexArrays(1, &m_vao); 2276 glDeleteBuffers(1, &m_vbo); 2277 return NO_ERROR; 2278 } 2279 2280 template <typename T> 2281 bool Read(int target, GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type) 2282 { 2283 const char* src_vs = 2284 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 2285 const GLuint program = BuildProgram(src_vs, GenFS(target, internalformat, expected_value).c_str()); 2286 GLuint textures[8]; 2287 glGenTextures(8, textures); 2288 2289 const int kSize = 11; 2290 std::vector<T> data(kSize * kSize * 2, value); 2291 2292 glBindTexture(GL_TEXTURE_2D, textures[1]); 2293 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2294 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2295 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); 2296 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2297 glBindTexture(GL_TEXTURE_2D, 0); 2298 2299 glBindTexture(GL_TEXTURE_3D, textures[2]); 2300 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2301 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2302 glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2); 2303 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]); 2304 glBindTexture(GL_TEXTURE_3D, 0); 2305 2306 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); 2307 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2308 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2309 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize); 2310 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2311 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2312 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2313 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2314 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2315 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2316 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 2317 2318 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); 2319 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2320 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2321 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2); 2322 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]); 2323 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 2324 2325 glBindImageTexture(2, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); // 2D 2326 glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 3D 2327 glBindImageTexture(3, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // Cube 2328 glBindImageTexture(1, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 2DArray 2329 2330 std::vector<T> out_data2D(kSize * kSize * 6); 2331 std::vector<T> out_data3D(kSize * kSize * 6); 2332 std::vector<T> out_dataCube(kSize * kSize * 6); 2333 std::vector<T> out_data2DArray(kSize * kSize * 6); 2334 GLuint m_buffer[4]; 2335 glGenBuffers(4, m_buffer); 2336 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[0]); 2337 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 2338 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]); 2339 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 2340 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[2]); 2341 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 2342 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]); 2343 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 2344 2345 glUseProgram(program); 2346 glClear(GL_COLOR_BUFFER_BIT); 2347 glBindVertexArray(m_vao); 2348 glViewport(0, 0, kSize, kSize); 2349 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 2350 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 2351 2352 bool status = true; 2353 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]); 2354 T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 2355 int layers = 2; 2356 if (target == T2D) 2357 layers = 1; 2358 if (target == TCM) 2359 layers = 6; 2360 status = CompareValues(map_data, kSize, expected_value, internalformat, layers); 2361 if (!status) 2362 Output("%d target, %s format failed. \n", target, FormatEnumToString(internalformat).c_str()); 2363 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); 2364 2365 glUseProgram(0); 2366 glDeleteProgram(program); 2367 glDeleteTextures(8, textures); 2368 glDeleteBuffers(4, m_buffer); 2369 2370 return status; 2371 } 2372 2373 template <typename T> 2374 std::string GenFS(int target, GLenum internalformat, const T& expected_value) 2375 { 2376 std::ostringstream os; 2377 os << NL "#define KSIZE 11"; 2378 switch (target) 2379 { 2380 case T2D: 2381 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) readonly uniform " 2382 << TypePrefix<T>() 2383 << "image2D g_image_2d;" NL "layout(std430, binding = 1) buffer OutputBuffer2D {" NL " " 2384 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;"; 2385 break; 2386 case T3D: 2387 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) readonly uniform " 2388 << TypePrefix<T>() 2389 << "image3D g_image_3d;" NL "layout(std430, binding = 0) buffer OutputBuffer3D {" NL " " 2390 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;"; 2391 break; 2392 case TCM: 2393 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) readonly uniform " 2394 << TypePrefix<T>() 2395 << "imageCube g_image_cube;" NL "layout(std430, binding = 3) buffer OutputBufferCube {" NL " " 2396 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;"; 2397 break; 2398 case T2DA: 2399 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform " 2400 << TypePrefix<T>() 2401 << "image2DArray g_image_2darray;" NL "layout(std430, binding = 2) buffer OutputBuffer2DArray {" NL " " 2402 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;"; 2403 break; 2404 } 2405 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 2406 " int coordIndex = coord.x + KSIZE * coord.y;" NL " int layer = int(KSIZE * KSIZE);" NL " " 2407 << TypePrefix<T>() << "vec4 v;"; 2408 2409 switch (target) 2410 { 2411 case T2D: 2412 os << NL " v = imageLoad(g_image_2d, coord);" NL " g_buff_2d.data[coordIndex] = v;"; 2413 break; 2414 case T3D: 2415 os << NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL " g_buff_3d.data[coordIndex] = v;" NL 2416 " v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL " g_buff_3d.data[coordIndex + layer] = v;"; 2417 break; 2418 case TCM: 2419 os << NL 2420 " v = imageLoad(g_image_cube, ivec3(coord, 0));" NL " g_buff_cube.data[coordIndex] = v;" NL 2421 " v = imageLoad(g_image_cube, ivec3(coord, 1));" NL " g_buff_cube.data[coordIndex + layer] = v;" NL 2422 " v = imageLoad(g_image_cube, ivec3(coord, 2));" NL 2423 " g_buff_cube.data[coordIndex + 2 * layer] = v;" NL 2424 " v = imageLoad(g_image_cube, ivec3(coord, 3));" NL 2425 " g_buff_cube.data[coordIndex + 3 * layer] = v;" NL 2426 " v = imageLoad(g_image_cube, ivec3(coord, 4));" NL 2427 " g_buff_cube.data[coordIndex + 4 * layer] = v;" NL 2428 " v = imageLoad(g_image_cube, ivec3(coord, 5));" NL " g_buff_cube.data[coordIndex + 5 * layer] = v;"; 2429 break; 2430 case T2DA: 2431 os << NL " v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL " g_buff_2darray.data[coordIndex] = v;" NL 2432 " v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL 2433 " g_buff_2darray.data[coordIndex + layer] = v;"; 2434 break; 2435 } 2436 os << NL " //g_buff_2d.data[coordIndex] = " << expected_value << ";" NL "}"; 2437 return os.str(); 2438 } 2439}; 2440 2441class BasicAllTargetsLoadCS : public ShaderImageLoadStoreBase 2442{ 2443 virtual long Setup() 2444 { 2445 return NO_ERROR; 2446 } 2447 2448 virtual long Run() 2449 { 2450 if (!Read(T2D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA, 2451 GL_FLOAT)) 2452 return ERROR; 2453 if (!Read(T2D, GL_RGBA32I, ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), 2454 ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), GL_RGBA_INTEGER, GL_INT)) 2455 return ERROR; 2456 if (!Read(T2D, GL_RGBA32UI, uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), 2457 uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) 2458 return ERROR; 2459 if (!Read(T3D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA, 2460 GL_FLOAT)) 2461 return ERROR; 2462 if (!Read(T3D, GL_RGBA32I, ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), 2463 ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), GL_RGBA_INTEGER, GL_INT)) 2464 return ERROR; 2465 if (!Read(T3D, GL_RGBA32UI, uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), 2466 uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) 2467 return ERROR; 2468 if (!Read(TCM, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA, 2469 GL_FLOAT)) 2470 return ERROR; 2471 if (!Read(TCM, GL_RGBA32I, ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), 2472 ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), GL_RGBA_INTEGER, GL_INT)) 2473 return ERROR; 2474 if (!Read(TCM, GL_RGBA32UI, uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), 2475 uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) 2476 return ERROR; 2477 if (!Read(T2DA, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA, 2478 GL_FLOAT)) 2479 return ERROR; 2480 if (!Read(T2DA, GL_RGBA32I, ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), 2481 ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), GL_RGBA_INTEGER, GL_INT)) 2482 return ERROR; 2483 if (!Read(T2DA, GL_RGBA32UI, uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), 2484 uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT)) 2485 return ERROR; 2486 2487 return NO_ERROR; 2488 } 2489 2490 virtual long Cleanup() 2491 { 2492 return NO_ERROR; 2493 } 2494 2495 template <typename T> 2496 bool Read(int target, GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type) 2497 { 2498 const GLuint program = CreateComputeProgram(GenCS(target, internalformat, expected_value)); 2499 GLuint textures[8]; 2500 glGenTextures(8, textures); 2501 2502 const int kSize = 11; 2503 std::vector<T> data(kSize * kSize * 2, value); 2504 2505 glBindTexture(GL_TEXTURE_2D, textures[1]); 2506 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2507 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2508 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); 2509 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2510 glBindTexture(GL_TEXTURE_2D, 0); 2511 2512 glBindTexture(GL_TEXTURE_3D, textures[2]); 2513 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2514 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2515 glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2); 2516 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]); 2517 glBindTexture(GL_TEXTURE_3D, 0); 2518 2519 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); 2520 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2521 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2522 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize); 2523 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2524 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2525 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2526 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2527 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2528 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]); 2529 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 2530 2531 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); 2532 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2533 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2534 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2); 2535 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]); 2536 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 2537 2538 glBindImageTexture(2, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); // 2D 2539 glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 3D 2540 glBindImageTexture(3, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // Cube 2541 glBindImageTexture(1, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 2DArray 2542 2543 std::vector<T> out_data2D(kSize * kSize * 6); 2544 std::vector<T> out_data3D(kSize * kSize * 6); 2545 std::vector<T> out_dataCube(kSize * kSize * 6); 2546 std::vector<T> out_data2DArray(kSize * kSize * 6); 2547 GLuint m_buffer[4]; 2548 glGenBuffers(4, m_buffer); 2549 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]); 2550 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 2551 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]); 2552 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 2553 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[2]); 2554 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 2555 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[3]); 2556 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW); 2557 2558 glUseProgram(program); 2559 glDispatchCompute(1, 1, 1); 2560 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 2561 2562 bool status = true; 2563 2564 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]); 2565 T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 2566 int layers = 2; 2567 if (target == T2D) 2568 layers = 1; 2569 if (target == TCM) 2570 layers = 6; 2571 status = CompareValues(map_data, kSize, expected_value, internalformat, layers); 2572 if (!status) 2573 Output("%d target, %s format failed. \n", target, FormatEnumToString(internalformat).c_str()); 2574 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); 2575 2576 glUseProgram(0); 2577 glDeleteProgram(program); 2578 glDeleteTextures(8, textures); 2579 glDeleteBuffers(4, m_buffer); 2580 2581 return status; 2582 } 2583 2584 template <typename T> 2585 std::string GenCS(int target, GLenum internalformat, const T& expected_value) 2586 { 2587 std::ostringstream os; 2588 os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;"; 2589 switch (target) 2590 { 2591 case T2D: 2592 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) readonly uniform " 2593 << TypePrefix<T>() 2594 << "image2D g_image_2d;" NL "layout(std430, binding = 0) buffer OutputBuffer2D {" NL " " 2595 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;"; 2596 break; 2597 case T3D: 2598 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) readonly uniform " 2599 << TypePrefix<T>() 2600 << "image3D g_image_3d;" NL "layout(std430, binding = 1) buffer OutputBuffer3D {" NL " " 2601 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;"; 2602 break; 2603 case TCM: 2604 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) readonly uniform " 2605 << TypePrefix<T>() 2606 << "imageCube g_image_cube;" NL "layout(std430, binding = 2) buffer OutputBufferCube {" NL " " 2607 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;"; 2608 break; 2609 case T2DA: 2610 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform " 2611 << TypePrefix<T>() 2612 << "image2DArray g_image_2darray;" NL "layout(std430, binding = 3) buffer OutputBuffer2DArray {" NL " " 2613 << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;"; 2614 break; 2615 } 2616 os << NL "void main() {" NL " ivec3 coord = ivec3(gl_LocalInvocationID.xy, 0);" NL 2617 " uint layer = uint(KSIZE * KSIZE);" NL " " 2618 << TypePrefix<T>() << "vec4 v;"; 2619 2620 switch (target) 2621 { 2622 case T2D: 2623 os << NL " v = imageLoad(g_image_2d, coord.xy);" NL " g_buff_2d.data[gl_LocalInvocationIndex] = v;"; 2624 break; 2625 case T3D: 2626 os << NL " v = imageLoad(g_image_3d, coord);" NL " g_buff_3d.data[gl_LocalInvocationIndex] = v;" NL 2627 " v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL 2628 " g_buff_3d.data[gl_LocalInvocationIndex + layer] = v;"; 2629 break; 2630 case TCM: 2631 os << NL " v = imageLoad(g_image_cube, coord);" NL " g_buff_cube.data[gl_LocalInvocationIndex] = v;" NL 2632 " v = imageLoad(g_image_cube, ivec3(coord.xy, 1));" NL 2633 " g_buff_cube.data[gl_LocalInvocationIndex + layer] = v;" NL 2634 " v = imageLoad(g_image_cube, ivec3(coord.xy, 2));" NL 2635 " g_buff_cube.data[gl_LocalInvocationIndex + 2u * layer] = v;" NL 2636 " v = imageLoad(g_image_cube, ivec3(coord.xy, 3));" NL 2637 " g_buff_cube.data[gl_LocalInvocationIndex + 3u * layer] = v;" NL 2638 " v = imageLoad(g_image_cube, ivec3(coord.xy, 4));" NL 2639 " g_buff_cube.data[gl_LocalInvocationIndex + 4u * layer] = v;" NL 2640 " v = imageLoad(g_image_cube, ivec3(coord.xy, 5));" NL 2641 " g_buff_cube.data[gl_LocalInvocationIndex + 5u * layer] = v;"; 2642 break; 2643 case T2DA: 2644 os << NL " v = imageLoad(g_image_2darray, coord);" NL 2645 " g_buff_2darray.data[gl_LocalInvocationIndex] = v;" NL 2646 " v = imageLoad(g_image_2darray, ivec3(coord.xy, 1));" NL 2647 " g_buff_2darray.data[gl_LocalInvocationIndex + layer] = v;"; 2648 break; 2649 } 2650 os << NL " //g_buff_2d.data[gl_LocalInvocationIndex] = " << expected_value << ";" NL "}"; 2651 return os.str(); 2652 } 2653}; 2654 2655//----------------------------------------------------------------------------- 2656// 1.3.3 BasicAllTargetsAtomic 2657//----------------------------------------------------------------------------- 2658class BasicAllTargetsAtomicFS : public ShaderImageLoadStoreBase 2659{ 2660 GLuint m_vao; 2661 GLuint m_vbo; 2662 2663 virtual long Setup() 2664 { 2665 m_vao = 0; 2666 m_vbo = 0; 2667 return NO_ERROR; 2668 } 2669 2670 virtual long Run() 2671 { 2672 if (!IsImageAtomicSupported()) 2673 return NOT_SUPPORTED; 2674 if (!IsVSFSAvailable(0, 4)) 2675 return NOT_SUPPORTED; 2676 if (!AreOutputsAvailable(5)) 2677 return NOT_SUPPORTED; 2678 if (!IsSSBInVSFSAvailable(1)) 2679 return NOT_SUPPORTED; 2680 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 2681 2682 if (!Atomic<GLint>(GL_R32I)) 2683 return ERROR; 2684 if (!Atomic<GLuint>(GL_R32UI)) 2685 return ERROR; 2686 2687 return NO_ERROR; 2688 } 2689 2690 virtual long Cleanup() 2691 { 2692 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 2693 glDeleteVertexArrays(1, &m_vao); 2694 glDeleteBuffers(1, &m_vbo); 2695 return NO_ERROR; 2696 } 2697 2698 template <typename T> 2699 bool Atomic(GLenum internalformat) 2700 { 2701 const char* src_vs = 2702 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 2703 2704 const GLuint program = BuildProgram(src_vs, GenFS<T>(internalformat).c_str(), false, true); 2705 GLuint textures[8]; 2706 GLuint buffer; 2707 glGenTextures(8, textures); 2708 glGenBuffers(1, &buffer); 2709 2710 const int kSize = 11; 2711 std::vector<T> data(kSize * kSize * 3); 2712 2713 glBindTexture(GL_TEXTURE_2D, textures[1]); 2714 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2715 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2716 glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize); 2717 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]); 2718 glBindTexture(GL_TEXTURE_2D, 0); 2719 2720 glBindTexture(GL_TEXTURE_3D, textures[2]); 2721 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2722 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2723 glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 3); 2724 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kSize, kSize, 3, Format<T>(), Type<T>(), &data[0]); 2725 glBindTexture(GL_TEXTURE_3D, 0); 2726 2727 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]); 2728 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2729 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2730 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize); 2731 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]); 2732 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]); 2733 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]); 2734 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]); 2735 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]); 2736 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]); 2737 glBindTexture(GL_TEXTURE_CUBE_MAP, 0); 2738 2739 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]); 2740 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2741 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2742 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 3); 2743 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 3, Format<T>(), Type<T>(), &data[0]); 2744 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 2745 2746 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); // 2D 2747 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); // 3D 2748 glBindImageTexture(0, textures[4], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); // Cube 2749 glBindImageTexture(3, textures[7], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); // 2DArray 2750 2751 std::vector<ivec4> o_data(kSize * kSize); 2752 GLuint m_buffer; 2753 glGenBuffers(1, &m_buffer); 2754 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 2755 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &o_data[0], GL_STATIC_DRAW); 2756 2757 glUseProgram(program); 2758 glClear(GL_COLOR_BUFFER_BIT); 2759 glBindVertexArray(m_vao); 2760 glViewport(0, 0, kSize, kSize); 2761 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 2762 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 2763 2764 bool status = true; 2765 2766 ivec4* out_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 2767 for (int i = 0; i < kSize * kSize; ++i) 2768 { 2769 if (!Equal(out_data[i], ivec4(10, 10, 10, 10), 0)) 2770 { 2771 status = false; 2772 Output("[%d] Atomic operation check failed. (operation/target coded: %s) \n", i, 2773 ToString(out_data[i]).c_str()); 2774 } 2775 } 2776 2777 glUseProgram(0); 2778 glDeleteProgram(program); 2779 glDeleteTextures(8, textures); 2780 glDeleteBuffers(1, &buffer); 2781 glDeleteBuffers(1, &m_buffer); 2782 2783 return status; 2784 } 2785 2786 template <typename T> 2787 std::string GenFS(GLenum internalformat) 2788 { 2789 std::ostringstream os; 2790 os << NL "#define KSIZE 11" NL "layout(" << FormatEnumToString(internalformat) 2791 << ", binding = 1) coherent uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" 2792 << FormatEnumToString(internalformat) << ", binding = 2) coherent uniform " << TypePrefix<T>() 2793 << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) 2794 << ", binding = 0) coherent uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" 2795 << FormatEnumToString(internalformat) << ", binding = 3) coherent uniform " << TypePrefix<T>() 2796 << "image2DArray g_image_2darray;" NL "layout(std430) buffer out_data {" NL 2797 " ivec4 o_color[KSIZE*KSIZE];" NL "};" NL 2798 << TypePrefix<T>() << "vec2 t(int i) {" NL " return " << TypePrefix<T>() 2799 << "vec2(i);" NL "}" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 2800 " int coordIndex = coord.x + KSIZE * coord.y;" NL " o_color[coordIndex] = ivec4(coordIndex);" NL 2801 " if (imageAtomicAdd(g_image_2d, coord, t(2).x) != t(0).x) o_color[coordIndex].x = 1;" NL 2802 " else if (imageAtomicMin(g_image_2d, coord, t(3).x) != t(2).x) o_color[coordIndex].x = 2;" NL 2803 " else if (imageAtomicMax(g_image_2d, coord, t(4).x) != t(2).x) o_color[coordIndex].x = 3;" NL 2804 " else if (imageAtomicAnd(g_image_2d, coord, t(0).x) != t(4).x) o_color[coordIndex].x = 4;" NL 2805 " else if (imageAtomicOr(g_image_2d, coord, t(7).x) != t(0).x) o_color[coordIndex].x = 5;" NL 2806 " else if (imageAtomicXor(g_image_2d, coord, t(4).x) != t(7).x) o_color[coordIndex].x = 6;" NL 2807 " else if (imageAtomicExchange(g_image_2d, coord, t(1).x) != t(3).x) o_color[coordIndex].x = 7;" NL 2808 " else if (imageAtomicCompSwap(g_image_2d, coord, t(1).x, t(6).x) != t(1).x) o_color[coordIndex].x = " 2809 "8;" NL " else o_color[coordIndex].x = 10;" NL 2810 " if (imageAtomicAdd(g_image_3d, ivec3(coord, 2), t(2).x) != t(0).x) o_color[coordIndex].y = 1;" NL 2811 " else if (imageAtomicMin(g_image_3d, ivec3(coord, 2), t(3).x) != t(2).x) o_color[coordIndex].y = 2;" NL 2812 " else if (imageAtomicMax(g_image_3d, ivec3(coord, 2), t(4).x) != t(2).x) o_color[coordIndex].y = 3;" NL 2813 " else if (imageAtomicAnd(g_image_3d, ivec3(coord, 2), t(0).x) != t(4).x) o_color[coordIndex].y = 4;" NL 2814 " else if (imageAtomicOr(g_image_3d, ivec3(coord, 2), t(7).x) != t(0).x) o_color[coordIndex].y = 5;" NL 2815 " else if (imageAtomicXor(g_image_3d, ivec3(coord, 2), t(4).x) != t(7).x) o_color[coordIndex].y = 6;" NL 2816 " else if (imageAtomicExchange(g_image_3d, ivec3(coord, 2), t(1).x) != t(3).x) o_color[coordIndex].y = " 2817 "7;" NL " else if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 2), t(1).x, t(6).x) != t(1).x) " 2818 "o_color[coordIndex].y = 8;" NL " else o_color[coordIndex].y = 10;" NL 2819 " if (imageAtomicAdd(g_image_cube, ivec3(coord, 3), t(2).x) != t(0).x) o_color[coordIndex].z = 1;" NL 2820 " else if (imageAtomicMin(g_image_cube, ivec3(coord, 3), t(3).x) != t(2).x) o_color[coordIndex].z = " 2821 "2;" NL " else if (imageAtomicMax(g_image_cube, ivec3(coord, 3), t(4).x) != t(2).x) " 2822 "o_color[coordIndex].z = 3;" NL " else if (imageAtomicAnd(g_image_cube, ivec3(coord, 3), " 2823 "t(0).x) != t(4).x) o_color[coordIndex].z = 4;" NL 2824 " else if (imageAtomicOr(g_image_cube, ivec3(coord, 3), t(7).x) != t(0).x) o_color[coordIndex].z = 5;" NL 2825 " else if (imageAtomicXor(g_image_cube, ivec3(coord, 3), t(4).x) != t(7).x) o_color[coordIndex].z = " 2826 "6;" NL " else if (imageAtomicExchange(g_image_cube, ivec3(coord, 3), t(1).x) != t(3).x) " 2827 "o_color[coordIndex].z = 7;" NL " else if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 3), " 2828 "t(1).x, t(6).x) != t(1).x) o_color[coordIndex].z = 8;" NL " else o_color[coordIndex].z = 10;" NL 2829 " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 2), t(2).x) != t(0).x) o_color[coordIndex].w = 1;" NL 2830 " else if (imageAtomicMin(g_image_2darray, ivec3(coord, 2), t(3).x) != t(2).x) o_color[coordIndex].w = " 2831 "2;" NL " else if (imageAtomicMax(g_image_2darray, ivec3(coord, 2), t(4).x) != t(2).x) " 2832 "o_color[coordIndex].w = 3;" NL " else if (imageAtomicAnd(g_image_2darray, ivec3(coord, 2), " 2833 "t(0).x) != t(4).x) o_color[coordIndex].w = 4;" NL 2834 " else if (imageAtomicOr(g_image_2darray, ivec3(coord, 2), t(7).x) != t(0).x) o_color[coordIndex].w = " 2835 "5;" NL " else if (imageAtomicXor(g_image_2darray, ivec3(coord, 2), t(4).x) != t(7).x) " 2836 "o_color[coordIndex].w = 6;" NL " else if (imageAtomicExchange(g_image_2darray, ivec3(coord, " 2837 "2), t(1).x) != t(3).x) o_color[coordIndex].w = 7;" NL 2838 " else if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 2), t(1).x, t(6).x) != t(1).x) " 2839 "o_color[coordIndex].w = 8;" NL " else o_color[coordIndex].w = 10;" NL " discard;" NL "}"; 2840 return os.str(); 2841 } 2842}; 2843//----------------------------------------------------------------------------- 2844// LoadStoreMachine 2845//----------------------------------------------------------------------------- 2846class LoadStoreMachine : public ShaderImageLoadStoreBase 2847{ 2848 GLuint m_vao; 2849 GLuint m_buffer; 2850 int m_stage; 2851 2852 virtual long Setup() 2853 { 2854 glEnable(GL_RASTERIZER_DISCARD); 2855 glGenVertexArrays(1, &m_vao); 2856 glGenBuffers(1, &m_buffer); 2857 return NO_ERROR; 2858 } 2859 2860 virtual long Cleanup() 2861 { 2862 glDisable(GL_RASTERIZER_DISCARD); 2863 glDeleteVertexArrays(1, &m_vao); 2864 glDeleteBuffers(1, &m_buffer); 2865 return NO_ERROR; 2866 } 2867 2868 template <typename T> 2869 bool Write(GLenum internalformat, const T& write_value, const T& expected_value) 2870 { 2871 const GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY }; 2872 const int kTargets = sizeof(targets) / sizeof(targets[0]); 2873 const int kSize = 100; 2874 GLuint program_store = 0; 2875 GLuint program_load = 0; 2876 if (m_stage == 0) 2877 { // VS 2878 const char* src_fs = NL "void main() {" NL " discard;" NL "}"; 2879 program_store = BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), src_fs); 2880 program_load = BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), src_fs); 2881 } 2882 else if (m_stage == 4) 2883 { // CS 2884 program_store = CreateComputeProgram(GenStoreShader(m_stage, internalformat, write_value)); 2885 program_load = CreateComputeProgram(GenLoadShader(m_stage, internalformat, expected_value)); 2886 } 2887 GLuint textures[kTargets]; 2888 glGenTextures(kTargets, textures); 2889 2890 for (int i = 0; i < kTargets; ++i) 2891 { 2892 glBindTexture(targets[i], textures[i]); 2893 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2894 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2895 2896 if (targets[i] == GL_TEXTURE_2D) 2897 { 2898 glTexStorage2D(targets[i], 1, internalformat, kSize, 1); 2899 } 2900 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY) 2901 { 2902 glTexStorage3D(targets[i], 1, internalformat, kSize, 1, 2); 2903 } 2904 else if (targets[i] == GL_TEXTURE_CUBE_MAP) 2905 { 2906 glTexStorage2D(targets[i], 1, internalformat, kSize, kSize); 2907 } 2908 } 2909 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); // 2D 2910 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 3D 2911 glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // Cube 2912 glBindImageTexture(3, textures[3], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat); // 2DArray 2913 2914 std::vector<ivec4> b_data(kSize); 2915 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 2916 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * 4 * 4, &b_data[0], GL_STATIC_DRAW); 2917 2918 glUseProgram(program_store); 2919 glBindVertexArray(m_vao); 2920 if (m_stage == 4) 2921 { // CS 2922 glDispatchCompute(1, 1, 1); 2923 } 2924 else if (m_stage == 0) 2925 { // VS 2926 glDrawArrays(GL_POINTS, 0, kSize); 2927 } 2928 bool status = true; 2929 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); 2930 2931 glBindImageTexture(3, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); // 2D 2932 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 3D 2933 glBindImageTexture(1, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // Cube 2934 glBindImageTexture(0, textures[3], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat); // 2DArray 2935 2936 glUseProgram(program_load); 2937 if (m_stage == 0) 2938 { // VS 2939 glDrawArrays(GL_POINTS, 0, kSize); 2940 } 2941 else if (m_stage == 4) 2942 { // CS 2943 glDispatchCompute(1, 1, 1); 2944 } 2945 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 2946 2947 ivec4* out_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * 4 * 4, GL_MAP_READ_BIT); 2948 for (int i = 0; i < kSize; ++i) 2949 { 2950 if (!Equal(out_data[i], ivec4(0, 1, 0, 1), 0)) 2951 { 2952 status = false; 2953 Output("[%d] load/store operation check failed. (%s) \n", i, ToString(out_data[i]).c_str()); 2954 } 2955 } 2956 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); 2957 glUseProgram(0); 2958 glDeleteProgram(program_store); 2959 glDeleteProgram(program_load); 2960 glDeleteTextures(kTargets, textures); 2961 return status; 2962 } 2963 2964 template <typename T> 2965 std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value) 2966 { 2967 std::ostringstream os; 2968 if (stage == 4) 2969 { // CS 2970 os << NL "#define KSIZE 100" NL "layout(local_size_x = KSIZE) in;"; 2971 } 2972 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) writeonly uniform " 2973 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) 2974 << ", binding = 2) writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" 2975 << FormatEnumToString(internalformat) << ", binding = 0) writeonly uniform " << TypePrefix<T>() 2976 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) 2977 << ", binding = 3) writeonly uniform " << TypePrefix<T>() 2978 << "image2DArray g_image_2darray;" NL "layout(std430) buffer out_data {" NL " ivec4 o_color;" NL "};" NL 2979 "void main() {" NL " " 2980 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4(o_color) + " << TypePrefix<T>() << "vec4" 2981 << write_value 2982 << ";" NL " int g_index[6] = int[](o_color.x, o_color.y, o_color.z, o_color.w, o_color.r, o_color.g);"; 2983 if (stage == 0) 2984 { // VS 2985 os << NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);"; 2986 } 2987 else if (stage == 4) 2988 { // CS 2989 os << NL " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);"; 2990 } 2991 os << NL " imageStore(g_image_2d, coord, g_value);" NL 2992 " imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL 2993 " imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL 2994 " for (int i = 0; i < 6; ++i) {" NL 2995 " imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL " }" NL 2996 " imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL 2997 " imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL "}"; 2998 return os.str(); 2999 } 3000 3001 template <typename T> 3002 std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value) 3003 { 3004 std::ostringstream os; 3005 os << NL "#define KSIZE 100"; 3006 if (stage == 4) 3007 { // CS 3008 os << NL "layout(local_size_x = KSIZE) in;"; 3009 } 3010 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) readonly uniform " 3011 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) 3012 << ", binding = 2) readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" 3013 << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform " << TypePrefix<T>() 3014 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) 3015 << ", binding = 0) readonly uniform " << TypePrefix<T>() 3016 << "image2DArray g_image_2darray;" NL "layout(std430) buffer out_data {" NL " ivec4 o_color[KSIZE];" NL 3017 "};" NL "void main() {"; 3018 3019 if (stage == 0) 3020 { // VS 3021 os << NL " " << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4(o_color[gl_VertexID]) + " 3022 << TypePrefix<T>() << "vec4" << expected_value << ";"; 3023 } 3024 else if (stage == 4) 3025 { // CS 3026 os << NL " " << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() 3027 << "vec4(o_color[gl_GlobalInvocationID.x]) + " << TypePrefix<T>() << "vec4" << expected_value << ";"; 3028 } 3029 3030 os << NL " int g_index[6] = int[](o_color[0].x, o_color[0].y, o_color[0].z, o_color[0].w, o_color[1].r, " 3031 "o_color[1].g);"; 3032 if (stage == 0) 3033 { // VS 3034 os << NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);"; 3035 } 3036 else if (stage == 4) 3037 { // CS 3038 os << NL " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);"; 3039 } 3040 os << NL " vec4 r = vec4(0.0, 1.0, 0.0, 1.0);" NL " " << TypePrefix<T>() 3041 << "vec4 v;" NL " v = imageLoad(g_image_2d, coord);" NL 3042 " if (v != g_value) r = vec4(1.0, 0.0, float(coord.x), 2.0);" NL 3043 " v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL 3044 " if (v != g_value) r = vec4(1.0, 0.0, float(coord.x), 3.0);" NL 3045 " v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL 3046 " if (v != g_value) r = vec4(1.0, 0.0, float(coord.x), 6.0);" NL 3047 " v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL 3048 " if (v != g_value) r = vec4(1.0, 0.0, float(coord.x), 23.0);" NL " o_color[coord.x] = ivec4(r);" NL 3049 "}"; 3050 return os.str(); 3051 } 3052 3053protected: 3054 long RunStage(int stage) 3055 { 3056 m_stage = stage; 3057 if (!AreOutputsAvailable(5)) 3058 return NOT_SUPPORTED; 3059 3060 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 3061 return ERROR; 3062 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f))) 3063 return ERROR; 3064 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f))) 3065 return ERROR; 3066 3067 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 3068 return ERROR; 3069 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1))) 3070 return ERROR; 3071 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 3072 return ERROR; 3073 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4))) 3074 return ERROR; 3075 3076 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 3077 return ERROR; 3078 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1))) 3079 return ERROR; 3080 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 3081 return ERROR; 3082 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3))) 3083 return ERROR; 3084 3085 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f))) 3086 return ERROR; 3087 3088 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f))) 3089 return ERROR; 3090 3091 return NO_ERROR; 3092 } 3093}; 3094//----------------------------------------------------------------------------- 3095// AtomicMachine 3096//----------------------------------------------------------------------------- 3097class AtomicMachine : public ShaderImageLoadStoreBase 3098{ 3099 GLuint m_vao; 3100 GLuint m_buffer; 3101 3102 virtual long Setup() 3103 { 3104 glEnable(GL_RASTERIZER_DISCARD); 3105 glGenVertexArrays(1, &m_vao); 3106 glGenBuffers(1, &m_buffer); 3107 return NO_ERROR; 3108 } 3109 3110 virtual long Cleanup() 3111 { 3112 glDisable(GL_RASTERIZER_DISCARD); 3113 glDeleteVertexArrays(1, &m_vao); 3114 glDeleteBuffers(1, &m_buffer); 3115 return NO_ERROR; 3116 } 3117 3118 template <typename T> 3119 bool Atomic(int target, int stage, GLenum internalformat) 3120 { 3121 GLuint program = 0; 3122 if (stage == 0) 3123 { // VS 3124 const char* src_fs = NL "void main() {" NL " discard;" NL "}"; 3125 program = BuildProgram(GenShader<T>(target, stage, internalformat).c_str(), src_fs, true, false); 3126 } 3127 else if (stage == 4) 3128 { // CS 3129 program = CreateComputeProgram(GenShader<T>(target, stage, internalformat), true); 3130 } 3131 3132 const GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY }; 3133 const int kTargets = sizeof(targets) / sizeof(targets[0]); 3134 const int kSize = 100; 3135 3136 GLuint textures[kTargets]; 3137 glGenTextures(kTargets, textures); 3138 3139 for (int i = 0; i < kTargets; ++i) 3140 { 3141 glBindTexture(targets[i], textures[i]); 3142 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3143 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3144 if (targets[i] == GL_TEXTURE_2D) 3145 { 3146 glTexStorage2D(targets[i], 1, internalformat, kSize, 1); 3147 } 3148 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY) 3149 { 3150 glTexStorage3D(targets[i], 1, internalformat, kSize, 1, 2); 3151 } 3152 else if (targets[i] == GL_TEXTURE_CUBE_MAP) 3153 { 3154 glTexStorage2D(targets[i], 1, internalformat, kSize, kSize); 3155 } 3156 } 3157 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); // 2D 3158 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); // 3D 3159 glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); // Cube 3160 glBindImageTexture(3, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat); // 2DArray 3161 3162 std::vector<ivec4> b_data(kSize); 3163 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 3164 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * 4 * 4, &b_data[0], GL_STATIC_DRAW); 3165 3166 glUseProgram(program); 3167 glBindVertexArray(m_vao); 3168 if (stage == 0) 3169 { // VS 3170 glDrawArrays(GL_POINTS, 0, kSize); 3171 } 3172 else if (stage == 4) 3173 { // CS 3174 glDispatchCompute(1, 1, 1); 3175 } 3176 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 3177 3178 bool status = true; 3179 ivec4* out_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * 4 * 4, GL_MAP_READ_BIT); 3180 for (int i = 0; i < kSize; ++i) 3181 { 3182 if (!Equal(out_data[i], ivec4(0, 1, 0, 1), 0)) 3183 { 3184 status = false; 3185 Output("[%d] Atomic operation check failed. (%s) \n", i, ToString(out_data[i]).c_str()); 3186 } 3187 } 3188 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); 3189 glUseProgram(0); 3190 glDeleteProgram(program); 3191 glDeleteTextures(kTargets, textures); 3192 return status; 3193 } 3194 3195 template <typename T> 3196 std::string GenShader(int target, int stage, GLenum internalformat) 3197 { 3198 std::ostringstream os; 3199 os << NL "#define KSIZE 100"; 3200 if (stage == 4) 3201 { // CS 3202 os << NL "layout(local_size_x = KSIZE) in;"; 3203 } 3204 switch (target) 3205 { 3206 case T2D: 3207 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) coherent uniform " 3208 << TypePrefix<T>() << "image2D g_image_2d;"; 3209 break; 3210 case T3D: 3211 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) coherent uniform " 3212 << TypePrefix<T>() << "image3D g_image_3d;"; 3213 break; 3214 case TCM: 3215 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) coherent uniform " 3216 << TypePrefix<T>() << "imageCube g_image_cube;"; 3217 break; 3218 case T2DA: 3219 os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) coherent uniform " 3220 << TypePrefix<T>() << "image2DArray g_image_2darray;"; 3221 break; 3222 } 3223 os << NL "layout(std430) buffer out_data {" NL " ivec4 o_color[KSIZE];" NL "} r;" NL << TypePrefix<T>() 3224 << "vec2 t(int i) {" NL " return " << TypePrefix<T>() 3225 << "vec2(i);" NL "}" NL "void main() {" NL " int g_value[6] = int[](r.o_color[0].x, r.o_color[0].y+1, " 3226 "r.o_color[0].z+2, r.o_color[0].w+3, r.o_color[1].r+4, " 3227 "r.o_color[1].g+5);"; 3228 if (stage == 0) 3229 { // VS 3230 os << NL " ivec2 coord = ivec2(gl_VertexID, g_value[0]);"; 3231 } 3232 else if (stage == 4) 3233 { // CS 3234 os << NL " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);"; 3235 } 3236 os << NL " ivec4 o_color = ivec4(0, 1, 0, 1);"; 3237 switch (target) 3238 { 3239 case T2D: 3240 os << NL " ivec4 i = ivec4(1, 0, 0, 2);" NL " imageAtomicExchange(g_image_2d, coord, t(0).x);" NL 3241 " if (imageAtomicAdd(g_image_2d, coord, t(2).x) != t(0).x) o_color = i;" NL 3242 " if (imageAtomicMin(g_image_2d, coord, t(3).x) != t(2).x) o_color = i;" NL 3243 " if (imageAtomicMax(g_image_2d, coord, t(4).x) != t(2).x) o_color = i;" NL 3244 " if (imageAtomicAnd(g_image_2d, coord, t(0).x) != t(4).x) o_color = i;" NL 3245 " if (imageAtomicOr(g_image_2d, coord, t(7).x) != t(0).x) o_color = i;" NL 3246 " if (imageAtomicXor(g_image_2d, coord, t(4).x) != t(7).x) o_color = i;" NL 3247 " if (imageAtomicExchange(g_image_2d, coord, t(1).x) != t(3).x) o_color = i;" NL 3248 " if (imageAtomicCompSwap(g_image_2d, coord, t(1).x, t(6).x) != t(1).x) o_color = i;" NL 3249 " if (imageAtomicExchange(g_image_2d, coord, t(0).x) != t(6).x) o_color = i;"; 3250 break; 3251 case T3D: 3252 os << NL " ivec4 i = ivec4(1, 0, 0, 3);" NL 3253 " imageAtomicExchange(g_image_3d, ivec3(coord, 0), t(0).x);" NL 3254 " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), t(2).x) != t(0).x) o_color = i;" NL 3255 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), t(3).x) != t(2).x) o_color = i;" NL 3256 " if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), t(4).x) != t(2).x) o_color = i;" NL 3257 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), t(0).x) != t(4).x) o_color = i;" NL 3258 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), t(7).x) != t(0).x) o_color = i;" NL 3259 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), t(4).x) != t(7).x) o_color = i;" NL 3260 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), t(1).x) != t(3).x) o_color = i;" NL 3261 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), t(1).x, t(6).x) != t(1).x) o_color = i;" NL 3262 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), t(0).x) != t(6).x) o_color = i;"; 3263 break; 3264 case TCM: 3265 os << NL 3266 " ivec4 i = ivec4(1, 0, 0, 6);" NL " imageAtomicExchange(g_image_cube, ivec3(coord, 0), t(0).x);" NL 3267 " if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), t(g_value[2]).x) != t(0).x) o_color = i;" NL 3268 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), t(3).x) != t(2).x) o_color = i;" NL 3269 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), t(4).x) != t(2).x) o_color = i;" NL 3270 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), t(0).x) != t(4).x) o_color = i;" NL 3271 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), t(7).x) != t(0).x) o_color = i;" NL 3272 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), t(4).x) != t(7).x) o_color = i;" NL 3273 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), t(1).x) != t(3).x) o_color = i;" NL 3274 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), t(1).x, t(6).x) != t(1).x) o_color " 3275 "= i;" NL " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), t(0).x) != t(6).x) o_color = i;"; 3276 break; 3277 case T2DA: 3278 os << NL 3279 " ivec4 i = ivec4(1, 0, 0, 23);" NL 3280 " imageAtomicExchange(g_image_2darray, ivec3(coord, 0), t(0).x);" NL 3281 " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), t(2).x) != t(0).x) o_color = i;" NL 3282 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), t(3).x) != t(2).x) o_color = i;" NL 3283 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), t(4).x) != t(2).x) o_color = i;" NL 3284 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), t(0).x) != t(4).x) o_color = i;" NL 3285 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), t(7).x) != t(0).x) o_color = i;" NL 3286 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), t(g_value[4]).x) != t(7).x) o_color = i;" NL 3287 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), t(1).x) != t(3).x) o_color = i;" NL 3288 " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), t(1).x, t(6).x) != t(1).x) o_color = i;" NL 3289 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), t(0).x) != t(6).x) o_color = i;"; 3290 break; 3291 } 3292 os << NL " r.o_color[coord.x] = o_color;" NL "}"; 3293 return os.str(); 3294 } 3295 3296protected: 3297 long RunStage(int stage) 3298 { 3299 if (!IsImageAtomicSupported()) 3300 return NOT_SUPPORTED; 3301 if (!Atomic<GLint>(T2D, stage, GL_R32I)) 3302 return ERROR; 3303 if (!Atomic<GLuint>(T2D, stage, GL_R32UI)) 3304 return ERROR; 3305 if (!Atomic<GLint>(T3D, stage, GL_R32I)) 3306 return ERROR; 3307 if (!Atomic<GLuint>(T3D, stage, GL_R32UI)) 3308 return ERROR; 3309 if (!Atomic<GLint>(TCM, stage, GL_R32I)) 3310 return ERROR; 3311 if (!Atomic<GLuint>(TCM, stage, GL_R32UI)) 3312 return ERROR; 3313 if (!Atomic<GLint>(T2DA, stage, GL_R32I)) 3314 return ERROR; 3315 if (!Atomic<GLuint>(T2DA, stage, GL_R32UI)) 3316 return ERROR; 3317 return NO_ERROR; 3318 } 3319}; 3320//----------------------------------------------------------------------------- 3321// 1.3.4 BasicAllTargetsLoadStoreVS 3322//----------------------------------------------------------------------------- 3323class BasicAllTargetsLoadStoreVS : public LoadStoreMachine 3324{ 3325 virtual long Run() 3326 { 3327 if (!IsVSFSAvailable(4, 0) || !IsSSBInVSFSAvailable(1)) 3328 return NOT_SUPPORTED; 3329 return RunStage(0); 3330 } 3331}; 3332//----------------------------------------------------------------------------- 3333// 1.3.8 BasicAllTargetsLoadStoreCS 3334//----------------------------------------------------------------------------- 3335class BasicAllTargetsLoadStoreCS : public LoadStoreMachine 3336{ 3337 virtual long Run() 3338 { 3339 return RunStage(4); 3340 } 3341}; 3342//----------------------------------------------------------------------------- 3343// 1.3.9 BasicAllTargetsAtomicVS 3344//----------------------------------------------------------------------------- 3345class BasicAllTargetsAtomicVS : public AtomicMachine 3346{ 3347 virtual long Run() 3348 { 3349 if (!IsVSFSAvailable(4, 0) || !IsSSBInVSFSAvailable(1)) 3350 return NOT_SUPPORTED; 3351 return RunStage(0); 3352 } 3353}; 3354//----------------------------------------------------------------------------- 3355// 1.3.13 BasicAllTargetsAtomicCS 3356//----------------------------------------------------------------------------- 3357class BasicAllTargetsAtomicCS : public AtomicMachine 3358{ 3359 virtual long Run() 3360 { 3361 return RunStage(4); 3362 } 3363}; 3364//----------------------------------------------------------------------------- 3365// 1.4.1 BasicGLSLMisc 3366//----------------------------------------------------------------------------- 3367class BasicGLSLMiscFS : public ShaderImageLoadStoreBase 3368{ 3369 GLuint m_texture; 3370 GLuint m_program; 3371 GLuint m_vao, m_vbo; 3372 GLuint m_buffer; 3373 3374 virtual long Setup() 3375 { 3376 m_texture = 0; 3377 m_program = 0; 3378 m_vao = m_vbo = 0; 3379 m_buffer = 0; 3380 return NO_ERROR; 3381 } 3382 virtual long Run() 3383 { 3384 if (!IsVSFSAvailable(0, 2) || !IsSSBInVSFSAvailable(1)) 3385 return NOT_SUPPORTED; 3386 3387 const int kSize = 32; 3388 std::vector<float> data(kSize * kSize * 4); 3389 3390 glGenTextures(1, &m_texture); 3391 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 3392 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3393 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3394 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, kSize, kSize, 4); 3395 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 4, GL_RED, GL_FLOAT, &data[0]); 3396 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 3397 3398 const char* src_vs = 3399 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 3400 const char* src_fs = 3401 NL "#define KSIZE 32" NL "layout(std430) buffer out_data {" NL " ivec4 o_color[KSIZE*KSIZE];" NL "};" NL 3402 "layout(r32f, binding = 0) coherent restrict uniform image2D g_image_layer0;" NL 3403 "layout(r32f, binding = 1) volatile uniform image2D g_image_layer1;" NL "void main() {" NL 3404 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image_layer0, coord, vec4(1.0));" NL 3405 " memoryBarrier();" NL " imageStore(g_image_layer1, coord, vec4(2.0));" NL " memoryBarrier();" NL 3406 " imageStore(g_image_layer0, coord, vec4(3.0));" NL " memoryBarrier();" NL 3407 " int coordIndex = coord.x + KSIZE * coord.y;" NL 3408 " o_color[coordIndex] = ivec4(imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord));" NL 3409 "}"; 3410 m_program = BuildProgram(src_vs, src_fs); 3411 3412 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 3413 3414 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); 3415 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_R32F); 3416 3417 glClear(GL_COLOR_BUFFER_BIT); 3418 glViewport(0, 0, kSize, kSize); 3419 3420 std::vector<ivec4> o_data(kSize * kSize); 3421 glGenBuffers(1, &m_buffer); 3422 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 3423 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &o_data[0], GL_STATIC_DRAW); 3424 3425 glUseProgram(m_program); 3426 glBindVertexArray(m_vao); 3427 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3428 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 3429 3430 bool status = true; 3431 3432 ivec4* out_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 3433 for (int i = 0; i < kSize * kSize; ++i) 3434 { 3435 if (!Equal(out_data[i], ivec4(5, 0, 0, 2), 0)) 3436 { 3437 status = false; 3438 Output("[%d] Check failed. Received: %s instead of: %s \n", i, ToString(out_data[i]).c_str(), 3439 ToString(ivec4(5, 0, 0, 2)).c_str()); 3440 } 3441 } 3442 3443 if (status) 3444 return NO_ERROR; 3445 else 3446 return ERROR; 3447 } 3448 virtual long Cleanup() 3449 { 3450 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 3451 glDeleteTextures(1, &m_texture); 3452 glDeleteVertexArrays(1, &m_vao); 3453 glDeleteBuffers(1, &m_vbo); 3454 glDeleteBuffers(1, &m_buffer); 3455 glUseProgram(0); 3456 glDeleteProgram(m_program); 3457 return NO_ERROR; 3458 } 3459}; 3460 3461class BasicGLSLMiscCS : public ShaderImageLoadStoreBase 3462{ 3463 GLuint m_texture; 3464 GLuint m_program; 3465 GLuint m_buffer; 3466 3467 virtual long Setup() 3468 { 3469 m_texture = 0; 3470 m_program = 0; 3471 m_buffer = 0; 3472 return NO_ERROR; 3473 } 3474 virtual long Run() 3475 { 3476 const int kSize = 10; 3477 std::vector<float> data(kSize * kSize * 4); 3478 3479 glGenTextures(1, &m_texture); 3480 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 3481 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3482 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3483 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, kSize, kSize, 4); 3484 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 4, GL_RED, GL_FLOAT, &data[0]); 3485 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 3486 3487 const char* src_cs = 3488 NL "#define KSIZE 10" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL 3489 "layout(std430) buffer out_data {" NL " ivec4 o_color[KSIZE*KSIZE];" NL "};" NL 3490 "layout(r32f, binding = 0) coherent restrict uniform image2D g_image_layer0;" NL 3491 "layout(r32f, binding = 1) volatile uniform image2D g_image_layer1;" NL "void main() {" NL 3492 " ivec2 coord = ivec2(gl_LocalInvocationID.xy);" NL " imageStore(g_image_layer0, coord, vec4(1.0));" NL 3493 " memoryBarrier();" NL " imageStore(g_image_layer1, coord, vec4(2.0));" NL " memoryBarrier();" NL 3494 " imageStore(g_image_layer0, coord, vec4(3.0));" NL " memoryBarrier();" NL 3495 " o_color[gl_LocalInvocationIndex] = ivec4(imageLoad(g_image_layer0, coord) + " 3496 "imageLoad(g_image_layer1, coord));" NL "}"; 3497 m_program = CreateComputeProgram(src_cs); 3498 3499 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); 3500 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_R32F); 3501 3502 std::vector<ivec4> o_data(kSize * kSize); 3503 glGenBuffers(1, &m_buffer); 3504 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 3505 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &o_data[0], GL_STATIC_DRAW); 3506 3507 glUseProgram(m_program); 3508 glDispatchCompute(1, 1, 1); 3509 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 3510 3511 bool status = true; 3512 3513 ivec4* out_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 3514 for (int i = 0; i < kSize * kSize; ++i) 3515 { 3516 if (!Equal(out_data[i], ivec4(5, 0, 0, 2), 0)) 3517 { 3518 status = false; 3519 Output("[%d] Check failed. Received: %s instead of: %s \n", i, ToString(out_data[i]).c_str(), 3520 ToString(ivec4(5, 0, 0, 2)).c_str()); 3521 } 3522 } 3523 3524 if (status) 3525 return NO_ERROR; 3526 else 3527 return ERROR; 3528 } 3529 virtual long Cleanup() 3530 { 3531 glDeleteTextures(1, &m_texture); 3532 glUseProgram(0); 3533 glDeleteProgram(m_program); 3534 glDeleteBuffers(1, &m_buffer); 3535 return NO_ERROR; 3536 } 3537}; 3538 3539//----------------------------------------------------------------------------- 3540// 1.4.2 BasicGLSLEarlyFragTests 3541//----------------------------------------------------------------------------- 3542class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase 3543{ 3544 GLuint m_texture[2]; 3545 GLuint m_program[2]; 3546 GLuint m_vao, m_vbo; 3547 GLuint c_program; 3548 GLuint m_buffer; 3549 3550 virtual long Setup() 3551 { 3552 m_texture[0] = m_texture[1] = 0; 3553 m_program[0] = m_program[1] = 0; 3554 m_vao = m_vbo = 0; 3555 m_buffer = 0; 3556 c_program = 0; 3557 return NO_ERROR; 3558 } 3559 3560 virtual long Run() 3561 { 3562 if (!IsVSFSAvailable(0, 1)) 3563 return NOT_SUPPORTED; 3564 3565 const int kSize = 8; 3566 std::vector<vec4> data(kSize * kSize); 3567 3568 glGenTextures(2, m_texture); 3569 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 3570 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3571 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3572 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize); 3573 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_FLOAT, &data[0]); 3574 glBindTexture(GL_TEXTURE_2D, 0); 3575 3576 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 3577 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3578 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3579 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize); 3580 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_FLOAT, &data[0]); 3581 glBindTexture(GL_TEXTURE_2D, 0); 3582 3583 const char* glsl_vs = 3584 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 3585 const char* glsl_early_frag_tests_fs = 3586 NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL 3587 "layout(rgba32f, binding = 0) writeonly coherent uniform image2D g_image;" NL "void main() {" NL 3588 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(17.0));" NL 3589 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}"; 3590 const char* glsl_fs = 3591 NL "layout(location = 0) out vec4 o_color;" NL 3592 "layout(rgba32f, binding = 1) writeonly coherent uniform image2D g_image;" NL "void main() {" NL 3593 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(13.0));" NL 3594 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}"; 3595 m_program[0] = BuildProgram(glsl_vs, glsl_early_frag_tests_fs); 3596 m_program[1] = BuildProgram(glsl_vs, glsl_fs); 3597 3598 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 3599 3600 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 3601 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 3602 3603 glViewport(0, 0, kSize, kSize); 3604 glBindVertexArray(m_vao); 3605 3606 glEnable(GL_DEPTH_TEST); 3607 glClearColor(0.0, 1.0f, 0.0, 1.0f); 3608 glClearDepthf(0.0f); 3609 3610 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 3611 glUseProgram(m_program[0]); 3612 3613 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3614 3615 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 3616 glUseProgram(m_program[1]); 3617 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3618 3619 const char* check_cs = 3620 NL "#define KSIZE 8" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL 3621 "uniform sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL 3622 " vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL 3623 " data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL "}"; 3624 3625 c_program = CreateComputeProgram(check_cs); 3626 std::vector<vec4> out_data(kSize * kSize); 3627 glGenBuffers(1, &m_buffer); 3628 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 3629 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW); 3630 3631 glActiveTexture(GL_TEXTURE5); 3632 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 3633 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); 3634 3635 glUseProgram(c_program); 3636 glUniform1i(glGetUniformLocation(c_program, "g_sampler"), 5); 3637 glDispatchCompute(1, 1, 1); 3638 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 3639 vec4* map_data = (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 3640 3641 float expectedVal = 0.0f; 3642 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 3643 if (renderTarget.getDepthBits() == 0) 3644 { 3645 expectedVal = 17.0f; 3646 } 3647 3648 if (!CompareValues(map_data, kSize, vec4(expectedVal))) 3649 return ERROR; 3650 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); 3651 3652 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 3653 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); 3654 3655 glDispatchCompute(1, 1, 1); 3656 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 3657 map_data = (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 3658 3659 if (!CompareValues(map_data, kSize, vec4(13.0f))) 3660 return ERROR; 3661 3662 return NO_ERROR; 3663 } 3664 3665 virtual long Cleanup() 3666 { 3667 glDisable(GL_DEPTH_TEST); 3668 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 3669 glClearDepthf(1.0f); 3670 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 3671 glDeleteTextures(2, m_texture); 3672 glDeleteVertexArrays(1, &m_vao); 3673 glDeleteBuffers(1, &m_vbo); 3674 glUseProgram(0); 3675 glDeleteProgram(m_program[0]); 3676 glDeleteProgram(m_program[1]); 3677 glDeleteProgram(c_program); 3678 glDeleteBuffers(1, &m_buffer); 3679 glActiveTexture(GL_TEXTURE0); 3680 return NO_ERROR; 3681 } 3682}; 3683 3684//----------------------------------------------------------------------------- 3685// 1.4.3 BasicGLSLConst 3686//----------------------------------------------------------------------------- 3687class BasicGLSLConst : public ShaderImageLoadStoreBase 3688{ 3689 GLuint m_program; 3690 GLuint m_buffer; 3691 3692 virtual long Setup() 3693 { 3694 m_program = 0; 3695 m_buffer = 0; 3696 return NO_ERROR; 3697 } 3698 3699 virtual long Run() 3700 { 3701 const char* src_cs = 3702 NL "layout (local_size_x = 1) in;" NL "layout(std430) buffer out_data {" NL " ivec4 o_color;" NL "};" NL 3703 "uniform int MaxImageUnits;" NL "uniform int MaxCombinedShaderOutputResources;" NL 3704 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxFragmentImageUniforms;" NL 3705 "uniform int MaxComputeImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL "void main() {" NL 3706 " o_color = ivec4(0, 1, 0, 1);" NL 3707 " if (gl_MaxImageUnits != MaxImageUnits) o_color = ivec4(1, 0, 0, 1);" NL 3708 " if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = ivec4(1, 0, " 3709 "0, 2);" NL " if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = ivec4(1, 0, 0, 4);" NL 3710 " if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = ivec4(1, 0, 0, 5);" NL 3711 " if (gl_MaxComputeImageUniforms != MaxComputeImageUniforms) o_color = ivec4(1, 0, 0, 6);" NL 3712 " if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = ivec4(1, 0, 0, 9);" NL "}"; 3713 m_program = CreateComputeProgram(src_cs); 3714 glUseProgram(m_program); 3715 3716 GLint i; 3717 glGetIntegerv(GL_MAX_IMAGE_UNITS, &i); 3718 glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i); 3719 3720 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i); 3721 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i); 3722 3723 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i); 3724 glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i); 3725 3726 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i); 3727 glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i); 3728 3729 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &i); 3730 glUniform1i(glGetUniformLocation(m_program, "MaxComputeImageUniforms"), i); 3731 3732 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i); 3733 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i); 3734 3735 std::vector<ivec4> out_data(1); 3736 glGenBuffers(1, &m_buffer); 3737 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 3738 glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4, &out_data[0], GL_STATIC_DRAW); 3739 3740 glDispatchCompute(1, 1, 1); 3741 3742 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 3743 ivec4* map_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4, GL_MAP_READ_BIT); 3744 3745 if (!Equal(map_data[0], ivec4(0, 1, 0, 1), 0)) 3746 { 3747 Output("[%d] Value is: %s. Value should be: %s.\n", i, ToString(map_data[0]).c_str(), 3748 ToString(ivec4(0, 1, 0, 1)).c_str()); 3749 return ERROR; 3750 } 3751 return NO_ERROR; 3752 } 3753 3754 virtual long Cleanup() 3755 { 3756 glUseProgram(0); 3757 glDeleteProgram(m_program); 3758 glDeleteBuffers(1, &m_buffer); 3759 return NO_ERROR; 3760 } 3761}; 3762 3763//----------------------------------------------------------------------------- 3764// 2.1.1 AdvancedSyncImageAccess 3765//----------------------------------------------------------------------------- 3766class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase 3767{ 3768 GLuint m_buffer; 3769 GLuint m_texture; 3770 GLuint m_store_program; 3771 GLuint m_draw_program; 3772 GLuint m_attribless_vao; 3773 3774 virtual long Setup() 3775 { 3776 m_buffer = 0; 3777 m_texture = 0; 3778 m_store_program = 0; 3779 m_draw_program = 0; 3780 m_attribless_vao = 0; 3781 return NO_ERROR; 3782 } 3783 3784 virtual long Run() 3785 { 3786 if (!IsVSFSAvailable(1, 0) || !IsSSBInVSFSAvailable(1)) 3787 return NOT_SUPPORTED; 3788 3789 const int kSize = 44; 3790 const char* const glsl_store_vs = 3791 NL "layout(rgba32f) writeonly uniform image2D g_output_data;" NL "void main() {" NL 3792 " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL 3793 " imageStore(g_output_data, ivec2(gl_VertexID,0), vec4(data[gl_VertexID], 0.0, 1.0));" NL 3794 " gl_PointSize = 1.0;" NL "}"; 3795 const char* const glsl_store_fs = NL "void main() {" NL " discard;" NL "}"; 3796 const char* const glsl_draw_vs = 3797 NL "out vec4 vs_color;" NL "layout(rgba32f) readonly uniform image2D g_image;" NL 3798 "uniform sampler2D g_sampler;" NL "void main() {" NL 3799 " vec4 pi = imageLoad(g_image, ivec2(gl_VertexID, 0));" NL 3800 " vec4 ps = texelFetch(g_sampler, ivec2(gl_VertexID, 0), 0);" NL 3801 " if (pi != ps) vs_color = vec4(1.0, 0.0, 0.0, 1.0);" NL 3802 " else vs_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " gl_Position = pi;" NL "}"; 3803 const char* const glsl_draw_fs = 3804 NL "#define KSIZE 44" NL "in vec4 vs_color;" NL "layout(std430) buffer OutputBuffer {" NL 3805 " vec4 o_color[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 3806 " int coordIndex = coord.x + KSIZE * coord.y;" NL " o_color[coordIndex] = vs_color;" NL "}"; 3807 m_store_program = BuildProgram(glsl_store_vs, glsl_store_fs); 3808 m_draw_program = BuildProgram(glsl_draw_vs, glsl_draw_fs); 3809 3810 glGenVertexArrays(1, &m_attribless_vao); 3811 glBindVertexArray(m_attribless_vao); 3812 3813 glGenTextures(1, &m_texture); 3814 glBindTexture(GL_TEXTURE_2D, m_texture); 3815 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3816 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3817 std::vector<ivec4> data(4); 3818 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 4, 1); 3819 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 1, GL_RGBA, GL_FLOAT, &data[0]); 3820 3821 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 3822 3823 glUseProgram(m_store_program); 3824 glDrawArrays(GL_POINTS, 0, 4); 3825 3826 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT); 3827 3828 glViewport(0, 0, kSize, kSize); 3829 glClear(GL_COLOR_BUFFER_BIT); 3830 glUseProgram(m_draw_program); 3831 3832 std::vector<vec4> out_data(kSize * kSize); 3833 glGenBuffers(1, &m_buffer); 3834 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 3835 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW); 3836 3837 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 3838 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 3839 vec4* map_data = (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 3840 3841 if (!CompareValues(map_data, kSize, vec4(0, 1, 0, 1))) 3842 return ERROR; 3843 3844 return NO_ERROR; 3845 } 3846 3847 virtual long Cleanup() 3848 { 3849 glUseProgram(0); 3850 glDeleteBuffers(1, &m_buffer); 3851 glDeleteTextures(1, &m_texture); 3852 glDeleteProgram(m_store_program); 3853 glDeleteProgram(m_draw_program); 3854 glDeleteVertexArrays(1, &m_attribless_vao); 3855 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 3856 return NO_ERROR; 3857 } 3858}; 3859 3860//----------------------------------------------------------------------------- 3861// 2.1.2 AdvancedSyncVertexArray 3862//----------------------------------------------------------------------------- 3863class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase 3864{ 3865 GLuint m_position_buffer; 3866 GLuint m_color_buffer; 3867 GLuint m_element_buffer; 3868 GLuint m_texture[3]; 3869 GLuint m_store_program; 3870 GLuint m_copy_program; 3871 GLuint m_draw_program; 3872 GLuint m_attribless_vao; 3873 GLuint m_draw_vao; 3874 3875 virtual long Setup() 3876 { 3877 m_position_buffer = 0; 3878 m_color_buffer = 0; 3879 m_element_buffer = 0; 3880 m_store_program = 0; 3881 m_draw_program = 0; 3882 m_copy_program = 0; 3883 m_attribless_vao = 0; 3884 m_draw_vao = 0; 3885 return NO_ERROR; 3886 } 3887 3888 virtual long Run() 3889 { 3890 if (!IsVSFSAvailable(3, 0)) 3891 return NOT_SUPPORTED; 3892 const char* const glsl_store_vs = 3893 NL "layout(rgba32f, binding = 0) writeonly uniform image2D g_position_buffer;" NL 3894 "layout(rgba32f, binding = 1) writeonly uniform image2D g_color_buffer;" NL 3895 "layout(r32ui, binding = 2) writeonly uniform uimage2D g_element_buffer;" NL "uniform vec4 g_color;" NL 3896 "void main() {" NL " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL 3897 " imageStore(g_position_buffer, ivec2(gl_VertexID,0), vec4(data[gl_VertexID], 0.0, 1.0));" NL 3898 " imageStore(g_color_buffer, ivec2(gl_VertexID,0), g_color);" NL 3899 " imageStore(g_element_buffer, ivec2(gl_VertexID,0), uvec4(gl_VertexID));" NL "}"; 3900 const char* const glsl_store_fs = NL "void main() {" NL " discard;" NL "}"; 3901 const char* glsl_copy_cs = 3902 NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE) in;" NL 3903 "layout(rgba32f, binding = 0) readonly uniform image2D g_position_img;" NL 3904 "layout(rgba32f, binding = 1) readonly uniform image2D g_color_img;" NL 3905 "layout(r32ui, binding = 2) readonly uniform uimage2D g_element_img;" NL 3906 "layout(std430, binding = 1) buffer g_position_buf {" NL " vec2 g_pos[KSIZE];" NL "};" NL 3907 "layout(std430, binding = 2) buffer g_color_buf {" NL " vec4 g_col[KSIZE];" NL "};" NL 3908 "layout(std430, binding = 3) buffer g_element_buf {" NL " uint g_elem[KSIZE];" NL "};" NL 3909 "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID.x, 0);" NL 3910 " g_pos[coord.x] = (imageLoad(g_position_img, coord)).xy;" NL 3911 " g_col[coord.x] = imageLoad(g_color_img, coord);" NL 3912 " g_elem[coord.x] = uint((imageLoad(g_element_img, coord)).x);" NL "}"; 3913 const char* const glsl_draw_vs = NL 3914 "layout(location = 0) in vec4 i_position;" NL "layout(location = 1) in vec4 i_color;" NL 3915 "out vec4 vs_color;" NL "void main() {" NL " gl_Position = i_position;" NL " vs_color = i_color;" NL "}"; 3916 const char* const glsl_draw_fs = NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL 3917 "void main() {" NL " o_color = vs_color;" NL "}"; 3918 m_store_program = BuildProgram(glsl_store_vs, glsl_store_fs); 3919 m_copy_program = CreateComputeProgram(glsl_copy_cs); 3920 m_draw_program = BuildProgram(glsl_draw_vs, glsl_draw_fs); 3921 3922 glGenTextures(3, m_texture); 3923 std::vector<ivec4> data(4); 3924 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 3925 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 4, 1); 3926 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3927 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3928 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 3929 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 4, 1); 3930 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3931 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3932 glBindTexture(GL_TEXTURE_2D, m_texture[2]); 3933 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 4, 1); 3934 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3935 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3936 3937 glGenVertexArrays(1, &m_attribless_vao); 3938 glGenVertexArrays(1, &m_draw_vao); 3939 glBindVertexArray(m_draw_vao); 3940 glGenBuffers(1, &m_position_buffer); 3941 glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer); 3942 glBufferData(GL_ARRAY_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW); 3943 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); 3944 glGenBuffers(1, &m_color_buffer); 3945 glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer); 3946 glBufferData(GL_ARRAY_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW); 3947 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); 3948 glBindBuffer(GL_ARRAY_BUFFER, 0); 3949 glEnableVertexAttribArray(0); 3950 glEnableVertexAttribArray(1); 3951 glGenBuffers(1, &m_element_buffer); 3952 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer); 3953 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW); 3954 glBindVertexArray(0); 3955 3956 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 3957 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 3958 glBindImageTexture(2, m_texture[2], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); 3959 glUseProgram(m_store_program); 3960 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f); 3961 glBindVertexArray(m_attribless_vao); 3962 glDrawArrays(GL_POINTS, 0, 4); 3963 3964 glUseProgram(m_copy_program); 3965 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_position_buffer); 3966 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_color_buffer); 3967 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_element_buffer); 3968 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 3969 glDispatchCompute(1, 1, 1); 3970 3971 glClear(GL_COLOR_BUFFER_BIT); 3972 glUseProgram(m_draw_program); 3973 glBindVertexArray(m_draw_vao); 3974 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT); 3975 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0); 3976 3977 if (!CheckFB(vec4(0, 1, 0, 1))) 3978 { 3979 return ERROR; 3980 } 3981 3982 glUseProgram(m_store_program); 3983 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f); 3984 glBindVertexArray(m_attribless_vao); 3985 glDrawArrays(GL_POINTS, 0, 4); 3986 glUseProgram(m_copy_program); 3987 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 3988 glDispatchCompute(1, 1, 1); 3989 glClear(GL_COLOR_BUFFER_BIT); 3990 glUseProgram(m_draw_program); 3991 glBindVertexArray(m_draw_vao); 3992 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT); 3993 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0); 3994 3995 if (!CheckFB(vec4(0, 0, 1, 1))) 3996 { 3997 return ERROR; 3998 } 3999 return NO_ERROR; 4000 } 4001 4002 virtual long Cleanup() 4003 { 4004 glDisable(GL_RASTERIZER_DISCARD); 4005 glUseProgram(0); 4006 glDeleteTextures(3, m_texture); 4007 glDeleteBuffers(1, &m_position_buffer); 4008 glDeleteBuffers(1, &m_color_buffer); 4009 glDeleteBuffers(1, &m_element_buffer); 4010 glDeleteProgram(m_store_program); 4011 glDeleteProgram(m_copy_program); 4012 glDeleteProgram(m_draw_program); 4013 glDeleteVertexArrays(1, &m_attribless_vao); 4014 glDeleteVertexArrays(1, &m_draw_vao); 4015 return NO_ERROR; 4016 } 4017}; 4018//----------------------------------------------------------------------------- 4019// 2.1.6 AdvancedSyncImageAccess2 4020//----------------------------------------------------------------------------- 4021class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase 4022{ 4023 GLuint m_texture; 4024 GLuint m_store_program; 4025 GLuint m_draw_program; 4026 GLuint m_vao; 4027 GLuint m_vbo; 4028 GLuint m_buffer; 4029 4030 virtual long Setup() 4031 { 4032 m_texture = 0; 4033 m_store_program = 0; 4034 m_draw_program = 0; 4035 m_vao = 0; 4036 m_vbo = 0; 4037 m_buffer = 0; 4038 return NO_ERROR; 4039 } 4040 4041 virtual long Run() 4042 { 4043 const int kSize = 32; 4044 if (!IsVSFSAvailable(0, 1) || !IsSSBInVSFSAvailable(1)) 4045 return NOT_SUPPORTED; 4046 const char* const glsl_vs = 4047 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 4048 const char* const glsl_store_fs = 4049 NL "layout(rgba32f) writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL 4050 " imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL " discard;" NL "}"; 4051 const char* const glsl_draw_fs = 4052 NL "layout(location = 0) out vec4 o_color;" NL "uniform sampler2D g_sampler;" NL 4053 "layout(std430) buffer OutputBuffer {" NL " uvec4 counter;" NL " vec4 data[];" NL "};" NL 4054 "void main() {" NL " uint idx = atomicAdd(counter[0], 1u);" NL 4055 " data[idx] = texelFetch(g_sampler, ivec2(gl_FragCoord.xy), 0);" NL "}"; 4056 m_store_program = BuildProgram(glsl_vs, glsl_store_fs); 4057 m_draw_program = BuildProgram(glsl_vs, glsl_draw_fs); 4058 4059 glGenTextures(1, &m_texture); 4060 glBindTexture(GL_TEXTURE_2D, m_texture); 4061 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4062 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4063 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, getWindowWidth(), getWindowHeight()); 4064 glBindTexture(GL_TEXTURE_2D, 0); 4065 4066 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 4067 4068 glViewport(0, 0, kSize, kSize); 4069 std::vector<vec4> data_b(kSize * kSize + 1); 4070 glGenBuffers(1, &m_buffer); 4071 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 4072 glBufferData(GL_SHADER_STORAGE_BUFFER, (kSize * kSize + 1) * 4 * 4, &data_b[0], GL_STATIC_DRAW); 4073 4074 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 4075 glUseProgram(m_store_program); 4076 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f); 4077 glBindVertexArray(m_vao); 4078 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 4079 4080 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 4081 4082 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f); 4083 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 4084 4085 glBindTexture(GL_TEXTURE_2D, m_texture); 4086 glUseProgram(m_draw_program); 4087 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); 4088 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 4089 4090 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 4091 vec4* map_data = 4092 (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 4 * 4, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 4093 4094 if (!CompareValues(map_data, kSize, vec4(0, 1, 0, 1))) 4095 return ERROR; 4096 return NO_ERROR; 4097 } 4098 4099 virtual long Cleanup() 4100 { 4101 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 4102 glUseProgram(0); 4103 glDeleteBuffers(1, &m_vbo); 4104 glDeleteTextures(1, &m_texture); 4105 glDeleteProgram(m_store_program); 4106 glDeleteProgram(m_draw_program); 4107 glDeleteVertexArrays(1, &m_vao); 4108 glDeleteBuffers(1, &m_buffer); 4109 return NO_ERROR; 4110 } 4111}; 4112 4113//----------------------------------------------------------------------------- 4114// 2.2.1 AdvancedAllStagesOneImage 4115//----------------------------------------------------------------------------- 4116class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase 4117{ 4118 GLuint m_program; 4119 GLuint c_program; 4120 GLuint m_vao; 4121 GLuint m_vbo; 4122 GLuint m_buffer; 4123 GLuint m_texture; 4124 4125 virtual long Setup() 4126 { 4127 m_program = 0; 4128 c_program = 0; 4129 m_vao = 0; 4130 m_vbo = 0; 4131 m_buffer = 0; 4132 m_texture = 0; 4133 return NO_ERROR; 4134 } 4135 4136 virtual long Run() 4137 { 4138 const int kSize = 64; 4139 if (!IsVSFSAvailable(1, 1) || !IsImageAtomicSupported()) 4140 return NOT_SUPPORTED; 4141 const char* const glsl_vs = 4142 NL "layout(location = 0) in vec4 i_position;" NL 4143 "layout(r32ui, binding = 3) coherent uniform uimage2D g_image;" NL "void main() {" NL 4144 " gl_Position = i_position;" NL " imageAtomicAdd(g_image, ivec2(0, gl_VertexID), 100u);" NL "}"; 4145 const char* const glsl_fs = 4146 NL "#define KSIZE 64" NL "layout(r32ui, binding = 3) coherent uniform uimage2D g_image;" NL 4147 "void main() {" NL " imageAtomicAdd(g_image, ivec2(0, int(gl_FragCoord.x) & 0x03), 0x1u);" NL "}"; 4148 m_program = BuildProgram(glsl_vs, glsl_fs, true, true); 4149 const char* const glsl_cs = 4150 NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE) in;" NL 4151 "layout(r32ui, binding = 3) uniform uimage2D g_image;" NL "layout(std430) buffer out_data {" NL 4152 " uvec4 data[KSIZE];" NL "};" NL "void main() {" NL 4153 " uvec4 v = imageLoad(g_image, ivec2(0, gl_LocalInvocationID.x));" NL 4154 " data[gl_LocalInvocationIndex] = v;" NL "}"; 4155 c_program = CreateComputeProgram(glsl_cs, true); 4156 glUseProgram(m_program); 4157 4158 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 4159 4160 std::vector<uvec4> ui32(16); 4161 glGenTextures(1, &m_texture); 4162 glBindTexture(GL_TEXTURE_2D, m_texture); 4163 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 4, 4); 4164 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4165 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4166 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32[0]); 4167 glBindTexture(GL_TEXTURE_2D, 0); 4168 4169 glBindImageTexture(3, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); 4170 4171 glViewport(0, 0, kSize, kSize); 4172 glBindVertexArray(m_vao); 4173 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1); 4174 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 4175 4176 std::vector<vec4> data_b(4); 4177 glGenBuffers(1, &m_buffer); 4178 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 4179 glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4 * 4, &data_b[0], GL_STATIC_DRAW); 4180 glUseProgram(c_program); 4181 glDispatchCompute(1, 1, 1); 4182 4183 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 4184 uvec4* map_data = (uvec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT); 4185 4186 if (!CompareValues(map_data, 2, uvec4(1024 + 100, 0, 0, 1))) 4187 return ERROR; 4188 return NO_ERROR; 4189 } 4190 4191 virtual long Cleanup() 4192 { 4193 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 4194 glUseProgram(0); 4195 glDeleteBuffers(1, &m_buffer); 4196 glDeleteBuffers(1, &m_vbo); 4197 glDeleteTextures(1, &m_texture); 4198 glDeleteProgram(m_program); 4199 glDeleteProgram(c_program); 4200 glDeleteVertexArrays(1, &m_vao); 4201 return NO_ERROR; 4202 } 4203}; 4204 4205//----------------------------------------------------------------------------- 4206// 2.3.2 AdvancedMemoryOrder 4207//----------------------------------------------------------------------------- 4208class AdvancedMemoryOrderVSFS : public ShaderImageLoadStoreBase 4209{ 4210 GLuint m_buffer; 4211 GLuint m_texture[2]; 4212 GLuint m_program; 4213 GLuint m_vao; 4214 GLuint m_vbo; 4215 4216 virtual long Setup() 4217 { 4218 m_buffer = 0; 4219 m_program = 0; 4220 m_vao = 0; 4221 m_vbo = 0; 4222 return NO_ERROR; 4223 } 4224 4225 virtual long Run() 4226 { 4227 const int kSize = 11; 4228 if (!IsVSFSAvailable(1, 1) || !IsSSBInVSFSAvailable(1)) 4229 return NOT_SUPPORTED; 4230 const char* const glsl_vs = NL 4231 "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL 4232 "layout(r32f, binding = 0) uniform image2D g_image_vs;" NL "void main() {" NL 4233 " gl_Position = i_position;" NL " vs_color = vec4(41, 42, 43, 44);" NL 4234 " imageStore(g_image_vs, ivec2(gl_VertexID), vec4(1.0));" NL 4235 " imageStore(g_image_vs, ivec2(gl_VertexID), vec4(2.0));" NL 4236 " imageStore(g_image_vs, ivec2(gl_VertexID), vec4(3.0));" NL 4237 " if (imageLoad(g_image_vs, ivec2(gl_VertexID)) != vec4(3,0,0,1)) vs_color = vec4(21, 22, 23, 24);" NL "}"; 4238 const char* const glsl_fs = 4239 NL "#define KSIZE 11" NL "in vec4 vs_color;" NL "layout(r32f, binding = 1) uniform image2D g_image;" NL 4240 "layout(std430) buffer out_data {" NL " vec4 data[KSIZE*KSIZE*4];" NL "};" NL "void main() {" NL 4241 " ivec2 coord = ivec2(gl_FragCoord);" NL " int coordIndex = coord.x + KSIZE * coord.y;" NL 4242 " for (int i = 0; i < 4; ++i) {" NL " data[coordIndex + i * KSIZE*KSIZE] = vs_color;" NL " }" NL 4243 " for (int i = 0; i < 4; ++i) {" NL " imageStore(g_image, coord, vec4(i+50));" NL 4244 " vec4 v = imageLoad(g_image, coord);" NL " if (v.x != float(i+50)) {" NL 4245 " data[coordIndex + i * KSIZE*KSIZE] = vec4(v.xyz, i+10);" NL " break;" NL " }" NL " }" NL 4246 "}"; 4247 m_program = BuildProgram(glsl_vs, glsl_fs); 4248 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 4249 4250 std::vector<float> data(kSize * kSize); 4251 glGenTextures(2, m_texture); 4252 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 4253 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, kSize, kSize); 4254 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4255 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4256 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RED, GL_FLOAT, &data[0]); 4257 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 4258 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, kSize, kSize); 4259 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4261 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RED, GL_FLOAT, &data[0]); 4262 glBindTexture(GL_TEXTURE_2D, 0); 4263 4264 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); 4265 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); 4266 4267 std::vector<vec4> data_b(kSize * kSize * 4); 4268 glGenBuffers(1, &m_buffer); 4269 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 4270 glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * kSize * kSize * 4 * 4, &data_b[0], GL_STATIC_DRAW); 4271 4272 glUseProgram(m_program); 4273 glViewport(0, 0, kSize, kSize); 4274 glBindVertexArray(m_vao); 4275 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1); 4276 4277 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 4278 vec4* map_data = 4279 (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 4280 4281 if (!CompareValues(map_data, kSize * 2, vec4(41, 42, 43, 44))) 4282 return ERROR; 4283 return NO_ERROR; 4284 } 4285 4286 virtual long Cleanup() 4287 { 4288 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 4289 glUseProgram(0); 4290 glDeleteBuffers(1, &m_vbo); 4291 glDeleteBuffers(1, &m_buffer); 4292 glDeleteTextures(2, m_texture); 4293 glDeleteProgram(m_program); 4294 glDeleteVertexArrays(1, &m_vao); 4295 return NO_ERROR; 4296 } 4297}; 4298 4299//----------------------------------------------------------------------------- 4300// 2.4.1 AdvancedSSOSimple 4301//----------------------------------------------------------------------------- 4302class AdvancedSSOSimple : public ShaderImageLoadStoreBase 4303{ 4304 bool pipeline; 4305 GLuint m_texture; 4306 GLuint m_pipeline[2]; 4307 GLuint m_vsp, m_fsp0, m_fsp1; 4308 GLuint m_vao, m_vbo; 4309 GLuint m_program[2]; 4310 GLuint c_program; 4311 GLuint m_buffer; 4312 4313 virtual long Setup() 4314 { 4315 c_program = 0; 4316 m_buffer = 0; 4317 CreateFullViewportQuad(&m_vao, &m_vbo, NULL); 4318 glGenTextures(1, &m_texture); 4319 const char* const glsl_vs = 4320 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 4321 const char* const glsl_fs0 = 4322 NL "layout(rgba32f, binding = 2) writeonly uniform image2D g_image[2];" NL "void main() {" NL 4323 " int i = g_image.length();" NL " imageStore(g_image[0], ivec2(gl_FragCoord), vec4(i+98));" NL 4324 " imageStore(g_image[1], ivec2(gl_FragCoord), vec4(i+99));" NL " discard;" NL "}"; 4325 const char* const glsl_fs1 = 4326 NL "layout(rgba32f, binding = 0) writeonly uniform image2D g_image[2];" NL "void main() {" NL 4327 " int i = g_image.length();" NL " imageStore(g_image[0], ivec2(gl_FragCoord), vec4(i+8));" NL 4328 " imageStore(g_image[1], ivec2(gl_FragCoord), vec4(i+9));" NL " discard;" NL "}"; 4329 if (pipeline) 4330 { 4331 glGenProgramPipelines(2, m_pipeline); 4332 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs); 4333 m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0); 4334 m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1); 4335 } 4336 else 4337 { 4338 m_program[0] = BuildProgram(glsl_vs, glsl_fs0); 4339 m_program[1] = BuildProgram(glsl_vs, glsl_fs1); 4340 } 4341 return NO_ERROR; 4342 } 4343 4344 virtual long Run() 4345 { 4346 if (!IsVSFSAvailable(0, 2)) 4347 return NOT_SUPPORTED; 4348 const int kSize = 4; 4349 4350 if (pipeline) 4351 { 4352 glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp); 4353 glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0); 4354 glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp); 4355 glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1); 4356 } 4357 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 4358 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4359 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4360 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 8); 4361 4362 glBindImageTexture(0, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F); 4363 glBindImageTexture(1, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F); 4364 glBindImageTexture(2, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F); 4365 glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F); 4366 4367 glBindVertexArray(m_vao); 4368 if (pipeline) 4369 glBindProgramPipeline(m_pipeline[0]); 4370 else 4371 glUseProgram(m_program[0]); 4372 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1); 4373 4374 if (pipeline) 4375 glBindProgramPipeline(m_pipeline[1]); 4376 else 4377 glUseProgram(m_program[1]); 4378 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 4379 4380 const char* const glsl_cs = 4381 NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL 4382 "layout(rgba32f, binding = 0) readonly uniform image2D g_image[4];" NL 4383 "layout(std430) buffer OutputBuffer {" NL " uvec4 counter;" NL " vec4 data[];" NL "};" NL 4384 "void main() {" NL " uint idx = atomicAdd(counter[0], 1u);" NL 4385 " data[idx][0] = (imageLoad(g_image[0], ivec2(gl_GlobalInvocationID))).z;" NL 4386 " data[idx][1] = (imageLoad(g_image[1], ivec2(gl_GlobalInvocationID))).z;" NL 4387 " data[idx][2] = (imageLoad(g_image[2], ivec2(gl_GlobalInvocationID))).z;" NL 4388 " data[idx][3] = (imageLoad(g_image[3], ivec2(gl_GlobalInvocationID))).z;" NL "}"; 4389 c_program = CreateComputeProgram(glsl_cs); 4390 glUseProgram(c_program); 4391 int wsx = (getWindowWidth() / kSize) * kSize; 4392 int wsy = (getWindowHeight() / kSize) * kSize; 4393 int minor = wsx > wsy ? wsy : wsx; 4394 4395 std::vector<vec4> data_b(wsx * wsy + 1); 4396 glGenBuffers(1, &m_buffer); 4397 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 4398 glBufferData(GL_SHADER_STORAGE_BUFFER, (wsx * wsy + 1) * 4 * 4, &data_b[0], GL_STATIC_DRAW); 4399 4400 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 4401 glDispatchCompute(wsx / kSize, wsy / kSize, 1); 4402 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 4403 vec4* map_data = (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 4 * 4, wsx * wsy * 4 * 4, GL_MAP_READ_BIT); 4404 4405 if (!CompareValues(map_data, minor, vec4(10, 11, 100, 101))) 4406 return ERROR; 4407 return NO_ERROR; 4408 } 4409 4410 virtual long Cleanup() 4411 { 4412 glUseProgram(0); 4413 glDeleteBuffers(1, &m_vbo); 4414 glDeleteTextures(1, &m_texture); 4415 if (pipeline) 4416 { 4417 glDeleteProgram(m_vsp); 4418 glDeleteProgram(m_fsp0); 4419 glDeleteProgram(m_fsp1); 4420 glDeleteProgramPipelines(2, m_pipeline); 4421 } 4422 else 4423 { 4424 glDeleteProgram(m_program[0]); 4425 glDeleteProgram(m_program[1]); 4426 } 4427 glDeleteProgram(c_program); 4428 glDeleteVertexArrays(1, &m_vao); 4429 glDeleteBuffers(1, &m_buffer); 4430 return NO_ERROR; 4431 } 4432 4433public: 4434 AdvancedSSOSimple() : pipeline(true) 4435 { 4436 } 4437}; 4438 4439//----------------------------------------------------------------------------- 4440// 2.5 AdvancedCopyImage 4441//----------------------------------------------------------------------------- 4442class AdvancedCopyImageFS : public ShaderImageLoadStoreBase 4443{ 4444 GLuint m_texture[2]; 4445 GLuint m_program; 4446 GLuint c_program; 4447 GLuint m_vao, m_vbo, m_ebo; 4448 GLuint m_buffer; 4449 4450 virtual long Setup() 4451 { 4452 glGenTextures(2, m_texture); 4453 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 4454 glGenBuffers(1, &m_buffer); 4455 4456 const char* const glsl_vs = 4457 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 4458 const char* const glsl_fs = 4459 NL "layout(rgba32f, binding = 3) readonly uniform image2D g_input_image;" NL 4460 "layout(rgba32f, binding = 1) writeonly uniform image2D g_output_image;" NL "void main() {" NL 4461 " ivec2 coord = ivec2(gl_FragCoord);" NL 4462 " imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL " discard;" NL "}"; 4463 m_program = BuildProgram(glsl_vs, glsl_fs); 4464 const char* const glsl_cs = NL 4465 "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL 4466 "layout(rgba32f, binding = 2) readonly uniform image2D g_image;" NL "layout(std430) buffer out_data {" NL 4467 " vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL 4468 " data[gl_LocalInvocationIndex] = imageLoad(g_image, coord);" NL "}"; 4469 c_program = CreateComputeProgram(glsl_cs); 4470 4471 return NO_ERROR; 4472 } 4473 4474 virtual long Run() 4475 { 4476 const int kSize = 11; 4477 if (!IsVSFSAvailable(0, 2)) 4478 return NOT_SUPPORTED; 4479 4480 std::vector<vec4> data(kSize * kSize, vec4(7.0f)); 4481 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 4482 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize); 4483 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4484 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4485 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_FLOAT, &data[0]); 4486 4487 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 4488 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize); 4489 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4490 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4491 4492 glBindTexture(GL_TEXTURE_2D, 0); 4493 4494 glBindImageTexture(3, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); 4495 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 4496 glBindImageTexture(2, m_texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); 4497 4498 std::vector<vec4> data_b(kSize * kSize); 4499 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 4500 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data_b[0], GL_STATIC_DRAW); 4501 4502 glUseProgram(m_program); 4503 glBindVertexArray(m_vao); 4504 glViewport(0, 0, kSize, kSize); 4505 glDrawElementsInstanced(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1); 4506 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 4507 4508 glUseProgram(c_program); 4509 glDispatchCompute(1, 1, 1); 4510 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 4511 vec4* map_data = (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 4512 4513 if (!CompareValues(map_data, kSize, vec4(7.f))) 4514 return ERROR; 4515 return NO_ERROR; 4516 } 4517 4518 virtual long Cleanup() 4519 { 4520 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 4521 glUseProgram(0); 4522 glDeleteBuffers(1, &m_vbo); 4523 glDeleteBuffers(1, &m_ebo); 4524 glDeleteBuffers(1, &m_buffer); 4525 glDeleteTextures(2, m_texture); 4526 glDeleteProgram(m_program); 4527 glDeleteProgram(c_program); 4528 glDeleteVertexArrays(1, &m_vao); 4529 return NO_ERROR; 4530 } 4531}; 4532class AdvancedCopyImageCS : public ShaderImageLoadStoreBase 4533{ 4534 GLuint m_texture[2]; 4535 GLuint m_program; 4536 GLuint c_program; 4537 GLuint m_buffer; 4538 4539 virtual long Setup() 4540 { 4541 glGenTextures(2, m_texture); 4542 glGenBuffers(1, &m_buffer); 4543 4544 const char* const glsl_cs = 4545 NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL 4546 "layout(rgba32f, binding = 3) readonly uniform image2D g_input_image;" NL 4547 "layout(rgba32f, binding = 1) writeonly uniform image2D g_output_image;" NL "void main() {" NL 4548 " ivec2 coord = ivec2(gl_LocalInvocationID);" NL 4549 " imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL "}"; 4550 m_program = CreateComputeProgram(glsl_cs); 4551 const char* const glsl_cs_c = NL 4552 "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL 4553 "layout(rgba32f, binding = 2) readonly uniform image2D g_image;" NL "layout(std430) buffer out_data {" NL 4554 " vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL 4555 " data[gl_LocalInvocationIndex] = imageLoad(g_image, coord);" NL "}"; 4556 c_program = CreateComputeProgram(glsl_cs_c); 4557 4558 return NO_ERROR; 4559 } 4560 4561 virtual long Run() 4562 { 4563 const int kSize = 11; 4564 4565 std::vector<vec4> data(kSize * kSize, vec4(7.0f)); 4566 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 4567 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize); 4568 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4569 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4570 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_FLOAT, &data[0]); 4571 4572 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 4573 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize); 4574 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4575 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4576 4577 glBindTexture(GL_TEXTURE_2D, 0); 4578 4579 glBindImageTexture(3, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); 4580 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); 4581 glBindImageTexture(2, m_texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); 4582 4583 std::vector<vec4> data_b(kSize * kSize); 4584 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 4585 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data_b[0], GL_STATIC_DRAW); 4586 4587 glUseProgram(m_program); 4588 glDispatchCompute(1, 1, 1); 4589 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 4590 4591 glUseProgram(c_program); 4592 glDispatchCompute(1, 1, 1); 4593 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 4594 vec4* map_data = (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 4595 4596 if (!CompareValues(map_data, kSize, vec4(7.f))) 4597 return ERROR; 4598 return NO_ERROR; 4599 } 4600 4601 virtual long Cleanup() 4602 { 4603 glUseProgram(0); 4604 glDeleteBuffers(1, &m_buffer); 4605 glDeleteTextures(2, m_texture); 4606 glDeleteProgram(m_program); 4607 glDeleteProgram(c_program); 4608 return NO_ERROR; 4609 } 4610}; 4611//----------------------------------------------------------------------------- 4612// 2.6 AdvancedAllMips 4613//----------------------------------------------------------------------------- 4614class AdvancedAllMipsFS : public ShaderImageLoadStoreBase 4615{ 4616 GLuint m_texture; 4617 GLuint m_store_program, m_load_program; 4618 GLuint m_vao, m_vbo, m_ebo; 4619 GLuint m_buffer; 4620 4621 virtual long Setup() 4622 { 4623 glGenTextures(1, &m_texture); 4624 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 4625 glGenBuffers(1, &m_buffer); 4626 4627 const char* const glsl_vs = 4628 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 4629 const char* const glsl_store_fs = 4630 NL "layout(rgba32f, binding = 0) writeonly uniform image2D g_image[4];" NL "void main() {" NL 4631 " imageStore(g_image[0], ivec2(gl_FragCoord), vec4(23));" NL 4632 " imageStore(g_image[1], ivec2(gl_FragCoord), vec4(24));" NL 4633 " imageStore(g_image[2], ivec2(gl_FragCoord), vec4(25));" NL 4634 " imageStore(g_image[3], ivec2(gl_FragCoord), vec4(26));" NL " discard;" NL "}"; 4635 const char* const glsl_load_cs = NL 4636 "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL 4637 "layout(rgba32f, binding = 0) readonly uniform image2D g_image[4];" NL "layout(std430) buffer out_data {" NL 4638 " ivec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL 4639 " data[gl_LocalInvocationIndex] = ivec4(2, 3, 4, 5);" NL " vec4 c0 = imageLoad(g_image[0], coord);" NL 4640 " vec4 c1 = imageLoad(g_image[1], coord);" NL " vec4 c2 = imageLoad(g_image[2], coord);" NL 4641 " vec4 c3 = imageLoad(g_image[3], coord);" NL 4642 " if ((all(lessThan(coord, ivec2(2))) && c0 != vec4(23)) || (any(greaterThanEqual(coord, ivec2(2))) && " 4643 "c0.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][0] = int(c0.x);" NL 4644 " if ((all(lessThan(coord, ivec2(4))) && c1 != vec4(24)) || (any(greaterThanEqual(coord, ivec2(4))) && " 4645 "c1.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][1] = int(c1.x);" NL 4646 " if ((all(lessThan(coord, ivec2(8))) && c2 != vec4(25)) || (any(greaterThanEqual(coord, ivec2(8))) && " 4647 "c2.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][2] = int(c2.x);" NL 4648 " if ((all(lessThan(coord, ivec2(16))) && c3 != vec4(26)) || (any(greaterThanEqual(coord, ivec2(16))) && " 4649 "c3.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][3] = int(c3.x);" NL "}"; 4650 m_store_program = BuildProgram(glsl_vs, glsl_store_fs); 4651 m_load_program = CreateComputeProgram(glsl_load_cs); 4652 4653 return NO_ERROR; 4654 } 4655 4656 virtual long Run() 4657 { 4658 const int kSize = 11; 4659 if (!IsVSFSAvailable(0, 4)) 4660 return NOT_SUPPORTED; 4661 glBindTexture(GL_TEXTURE_2D, m_texture); 4662 glTexStorage2D(GL_TEXTURE_2D, 8, GL_RGBA32F, 128, 128); 4663 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4664 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4665 glBindTexture(GL_TEXTURE_2D, 0); 4666 4667 glBindImageTexture(0, m_texture, 6, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4668 glBindImageTexture(1, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4669 glBindImageTexture(2, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4670 glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4671 4672 std::vector<GLubyte> data(kSize * kSize * 4 * 4); 4673 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 4674 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data[0], GL_STATIC_DRAW); 4675 4676 glViewport(0, 0, kSize, kSize); 4677 glBindVertexArray(m_vao); 4678 4679 glUseProgram(m_store_program); 4680 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0); 4681 4682 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 4683 4684 glUseProgram(m_load_program); 4685 glDispatchCompute(1, 1, 1); 4686 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 4687 ivec4* map_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 4688 4689 if (!CompareValues(map_data, kSize, ivec4(2, 3, 4, 5))) 4690 return ERROR; 4691 return NO_ERROR; 4692 } 4693 4694 virtual long Cleanup() 4695 { 4696 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 4697 glUseProgram(0); 4698 glDeleteBuffers(1, &m_vbo); 4699 glDeleteBuffers(1, &m_ebo); 4700 glDeleteTextures(1, &m_texture); 4701 glDeleteProgram(m_store_program); 4702 glDeleteProgram(m_load_program); 4703 glDeleteVertexArrays(1, &m_vao); 4704 glDeleteBuffers(1, &m_buffer); 4705 return NO_ERROR; 4706 } 4707}; 4708 4709class AdvancedAllMipsCS : public ShaderImageLoadStoreBase 4710{ 4711 GLuint m_texture; 4712 GLuint m_store_program, m_load_program; 4713 GLuint m_buffer; 4714 4715 virtual long Setup() 4716 { 4717 glGenTextures(1, &m_texture); 4718 glGenBuffers(1, &m_buffer); 4719 4720 const char* const glsl_store_cs = 4721 NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL 4722 "layout(rgba32f, binding = 0) writeonly uniform image2D g_image[4];" NL "void main() {" NL 4723 " ivec2 coord = ivec2(gl_LocalInvocationID);" NL " imageStore(g_image[0], coord, vec4(23));" NL 4724 " imageStore(g_image[1], coord, vec4(24));" NL " imageStore(g_image[2], coord, vec4(25));" NL 4725 " imageStore(g_image[3], coord, vec4(26));" NL "}"; 4726 const char* const glsl_load_cs = NL 4727 "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL 4728 "layout(rgba32f, binding = 0) readonly uniform image2D g_image[4];" NL "layout(std430) buffer out_data {" NL 4729 " ivec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL 4730 " data[gl_LocalInvocationIndex] = ivec4(2, 3, 4, 5);" NL " vec4 c0 = imageLoad(g_image[0], coord);" NL 4731 " vec4 c1 = imageLoad(g_image[1], coord);" NL " vec4 c2 = imageLoad(g_image[2], coord);" NL 4732 " vec4 c3 = imageLoad(g_image[3], coord);" NL 4733 " if ((all(lessThan(coord, ivec2(2))) && c0 != vec4(23)) || (any(greaterThanEqual(coord, ivec2(2))) && " 4734 "c0.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][0] = int(c0.x);" NL 4735 " if ((all(lessThan(coord, ivec2(4))) && c1 != vec4(24)) || (any(greaterThanEqual(coord, ivec2(4))) && " 4736 "c1.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][1] = int(c1.x);" NL 4737 " if ((all(lessThan(coord, ivec2(8))) && c2 != vec4(25)) || (any(greaterThanEqual(coord, ivec2(8))) && " 4738 "c2.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][2] = int(c2.x);" NL 4739 " if ((all(lessThan(coord, ivec2(16))) && c3 != vec4(26)) || (any(greaterThanEqual(coord, ivec2(16))) && " 4740 "c3.xyz != vec3(0.0)))" NL " data[gl_LocalInvocationIndex][3] = int(c3.x);" NL "}"; 4741 m_store_program = CreateComputeProgram(glsl_store_cs); 4742 m_load_program = CreateComputeProgram(glsl_load_cs); 4743 4744 return NO_ERROR; 4745 } 4746 4747 virtual long Run() 4748 { 4749 const int kSize = 11; 4750 glBindTexture(GL_TEXTURE_2D, m_texture); 4751 glTexStorage2D(GL_TEXTURE_2D, 8, GL_RGBA32F, 128, 128); 4752 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4753 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4754 glBindTexture(GL_TEXTURE_2D, 0); 4755 4756 glBindImageTexture(0, m_texture, 6, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4757 glBindImageTexture(1, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4758 glBindImageTexture(2, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4759 glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 4760 4761 std::vector<GLubyte> data(kSize * kSize * 4 * 4); 4762 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 4763 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data[0], GL_STATIC_DRAW); 4764 4765 glUseProgram(m_store_program); 4766 glDispatchCompute(1, 1, 1); 4767 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 4768 4769 glUseProgram(m_load_program); 4770 glDispatchCompute(1, 1, 1); 4771 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 4772 ivec4* map_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 4773 4774 if (!CompareValues(map_data, kSize, ivec4(2, 3, 4, 5))) 4775 return ERROR; 4776 return NO_ERROR; 4777 } 4778 4779 virtual long Cleanup() 4780 { 4781 glUseProgram(0); 4782 glDeleteTextures(1, &m_texture); 4783 glDeleteProgram(m_store_program); 4784 glDeleteProgram(m_load_program); 4785 glDeleteBuffers(1, &m_buffer); 4786 return NO_ERROR; 4787 } 4788}; 4789//----------------------------------------------------------------------------- 4790// 2.7 AdvancedCast 4791//----------------------------------------------------------------------------- 4792class AdvancedCastFS : public ShaderImageLoadStoreBase 4793{ 4794 GLuint m_texture[2]; 4795 GLuint m_program; 4796 GLuint c_program; 4797 GLuint m_vao, m_vbo, m_ebo; 4798 GLuint m_buffer; 4799 4800 virtual long Setup() 4801 { 4802 glGenTextures(2, m_texture); 4803 glGenBuffers(1, &m_buffer); 4804 m_program = 0; 4805 c_program = 0; 4806 return NO_ERROR; 4807 } 4808 4809 virtual long Run() 4810 { 4811 if (!IsVSFSAvailable(0, 2) || !IsImageAtomicSupported()) 4812 return NOT_SUPPORTED; 4813 const int kSize = 11; 4814 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo); 4815 4816 const char* const glsl_vs = 4817 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 4818 const char* const glsl_fs = 4819 NL "#define KSIZE 11" NL "layout(r32i, binding = 0) coherent uniform iimage2D g_image0;" NL 4820 "layout(r32ui, binding = 1) coherent uniform uimage2D g_image1;" NL "void main() {" NL 4821 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageAtomicAdd(g_image0, coord, 2);" NL 4822 " imageAtomicAdd(g_image0, coord, -1);" NL " imageAtomicAdd(g_image1, coord, 1u);" NL 4823 " imageAtomicAdd(g_image1, coord, 2u);" NL "}"; 4824 m_program = BuildProgram(glsl_vs, glsl_fs, false, true); 4825 4826 const char* const glsl_cs = NL 4827 "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL 4828 "layout(r32i, binding = 0) uniform iimage2D gi_image;" NL 4829 "layout(r32ui, binding = 1) uniform uimage2D gu_image;" NL "layout(std430) buffer out_data {" NL 4830 " ivec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL 4831 " data[gl_LocalInvocationIndex].yx = imageLoad(gi_image, coord).xy;" NL 4832 " data[gl_LocalInvocationIndex].wz = ivec2(imageLoad(gu_image, coord).xz);" NL "}"; 4833 c_program = CreateComputeProgram(glsl_cs); 4834 4835 std::vector<GLubyte> data(kSize * kSize * 4 * 4); 4836 glActiveTexture(GL_TEXTURE11); 4837 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 4838 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize); 4839 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); 4840 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4841 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4842 glActiveTexture(GL_TEXTURE15); 4843 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 4844 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize); 4845 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); 4846 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4847 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4848 4849 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I); 4850 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); 4851 4852 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 4853 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data[0], GL_STATIC_DRAW); 4854 4855 glUseProgram(m_program); 4856 glBindVertexArray(m_vao); 4857 glViewport(0, 0, kSize, kSize); 4858 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0); 4859 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 4860 4861 glUseProgram(c_program); 4862 glDispatchCompute(1, 1, 1); 4863 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 4864 ivec4* map_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 4865 4866 if (!CompareValues(map_data, kSize, ivec4(0, 1, 0, 3))) 4867 return ERROR; 4868 return NO_ERROR; 4869 } 4870 4871 virtual long Cleanup() 4872 { 4873 glViewport(0, 0, getWindowWidth(), getWindowHeight()); 4874 glUseProgram(0); 4875 glDeleteBuffers(1, &m_vbo); 4876 glDeleteBuffers(1, &m_ebo); 4877 glDeleteBuffers(1, &m_buffer); 4878 glDeleteTextures(2, m_texture); 4879 glDeleteProgram(m_program); 4880 glDeleteProgram(c_program); 4881 glDeleteVertexArrays(1, &m_vao); 4882 glActiveTexture(GL_TEXTURE0); 4883 return NO_ERROR; 4884 } 4885}; 4886 4887class AdvancedCastCS : public ShaderImageLoadStoreBase 4888{ 4889 GLuint m_texture[2]; 4890 GLuint m_program; 4891 GLuint c_program; 4892 GLuint m_buffer; 4893 4894 virtual long Setup() 4895 { 4896 glGenTextures(2, m_texture); 4897 glGenBuffers(1, &m_buffer); 4898 m_program = 0; 4899 c_program = 0; 4900 return NO_ERROR; 4901 } 4902 virtual long Run() 4903 { 4904 const int kSize = 11; 4905 if (!IsImageAtomicSupported()) 4906 return NO_ERROR; 4907 4908 const char* const glsl_cs = 4909 NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL 4910 "layout(r32i, binding = 0) coherent uniform iimage2D g_image0;" NL 4911 "layout(r32ui, binding = 1) coherent uniform uimage2D g_image1;" NL "void main() {" NL 4912 " ivec2 coord = ivec2(gl_LocalInvocationID);" NL " imageAtomicAdd(g_image0, coord, 222);" NL 4913 " imageAtomicAdd(g_image0, coord, -11);" NL " imageAtomicAdd(g_image1, coord, 1u);" NL 4914 " imageAtomicAdd(g_image1, coord, 2u);" NL "}"; 4915 m_program = CreateComputeProgram(glsl_cs, true); 4916 4917 const char* const glsl_cs_c = NL 4918 "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL 4919 "layout(r32i, binding = 0) uniform iimage2D gi_image;" NL 4920 "layout(r32ui, binding = 1) uniform uimage2D gu_image;" NL "layout(std430) buffer out_data {" NL 4921 " ivec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL " ivec2 coord = ivec2(gl_LocalInvocationID);" NL 4922 " data[gl_LocalInvocationIndex].yz = imageLoad(gi_image, coord).xw;" NL 4923 " data[gl_LocalInvocationIndex].wx = ivec2(imageLoad(gu_image, coord).xy);" NL "}"; 4924 c_program = CreateComputeProgram(glsl_cs_c); 4925 4926 std::vector<GLubyte> data(kSize * kSize * 4 * 4); 4927 glActiveTexture(GL_TEXTURE11); 4928 glBindTexture(GL_TEXTURE_2D, m_texture[0]); 4929 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize); 4930 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); 4931 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4932 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4933 glActiveTexture(GL_TEXTURE15); 4934 glBindTexture(GL_TEXTURE_2D, m_texture[1]); 4935 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize); 4936 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); 4937 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4938 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4939 4940 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I); 4941 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); 4942 4943 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer); 4944 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data[0], GL_STATIC_DRAW); 4945 4946 glUseProgram(m_program); 4947 glDispatchCompute(1, 1, 1); 4948 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); 4949 4950 glUseProgram(c_program); 4951 glDispatchCompute(1, 1, 1); 4952 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 4953 ivec4* map_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT); 4954 4955 if (!CompareValues(map_data, kSize, ivec4(0, 211, 1, 3))) 4956 return ERROR; 4957 return NO_ERROR; 4958 } 4959 4960 virtual long Cleanup() 4961 { 4962 glUseProgram(0); 4963 glDeleteBuffers(1, &m_buffer); 4964 glDeleteTextures(2, m_texture); 4965 glDeleteProgram(m_program); 4966 glDeleteProgram(c_program); 4967 glActiveTexture(GL_TEXTURE0); 4968 return NO_ERROR; 4969 } 4970}; 4971 4972//----------------------------------------------------------------------------- 4973// 4.1 NegativeUniform 4974//----------------------------------------------------------------------------- 4975class NegativeUniform : public ShaderImageLoadStoreBase 4976{ 4977 GLuint m_program; 4978 4979 virtual long Setup() 4980 { 4981 m_program = 0; 4982 return NO_ERROR; 4983 } 4984 virtual long Run() 4985 { 4986 const char* glsl_vs = 4987 NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL " gl_Position = i_position;" NL "}"; 4988 const char* glsl_fs = NL "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL 4989 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL 4990 " imageStore(g_image, coord, vec4(0.0));" NL " discard;" NL "}"; 4991 m_program = BuildProgram(glsl_vs, glsl_fs); 4992 4993 GLint max_image_units; 4994 glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units); 4995 glUseProgram(m_program); 4996 bool status = true; 4997 GLint i = 1; 4998 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1); 4999 if (glGetError() != GL_INVALID_OPERATION) 5000 status = false; 5001 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i); 5002 if (glGetError() != GL_INVALID_OPERATION) 5003 status = false; 5004 glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0); 5005 if (glGetError() != GL_INVALID_OPERATION) 5006 status = false; 5007 glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0); 5008 if (glGetError() != GL_INVALID_OPERATION) 5009 status = false; 5010 5011 if (!status) 5012 { 5013 Output("glUniform* should generate INVALID_OPERATION if the location refers to an image variable.\n"); 5014 return ERROR; 5015 } 5016 5017 glUseProgram(0); 5018 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), 1); 5019 if (glGetError() != GL_INVALID_OPERATION) 5020 status = false; 5021 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &i); 5022 if (glGetError() != GL_INVALID_OPERATION) 5023 status = false; 5024 glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0); 5025 if (glGetError() != GL_INVALID_OPERATION) 5026 status = false; 5027 glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0); 5028 if (glGetError() != GL_INVALID_OPERATION) 5029 status = false; 5030 5031 if (!status) 5032 { 5033 Output( 5034 "glProgramUniform* should generate INVALID_OPERATION if the location refers to an image variable.\n"); 5035 return ERROR; 5036 } 5037 5038 return NO_ERROR; 5039 } 5040 5041 virtual long Cleanup() 5042 { 5043 glUseProgram(0); 5044 glDeleteProgram(m_program); 5045 return NO_ERROR; 5046 } 5047}; 5048//----------------------------------------------------------------------------- 5049// 4.2 NegativeBind 5050//----------------------------------------------------------------------------- 5051class NegativeBind : public ShaderImageLoadStoreBase 5052{ 5053 GLuint m_texture, m_texture2; 5054 5055 virtual long Setup() 5056 { 5057 m_texture = 0; 5058 m_texture2 = 0; 5059 return NO_ERROR; 5060 } 5061 5062 virtual long Run() 5063 { 5064 GLint max_image_units; 5065 glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units); 5066 glGenTextures(1, &m_texture); 5067 glBindTexture(GL_TEXTURE_2D, m_texture); 5068 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 64, 64); 5069 5070 glBindImageTexture(max_image_units, m_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); 5071 if (glGetError() != GL_INVALID_VALUE) 5072 { 5073 Output("BindImageTexture should generate INVALID_VALUE if <unit> is greater than or equal to the value of " 5074 "MAX_IMAGE_UNITS.\n"); 5075 return ERROR; 5076 } 5077 5078 glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); 5079 if (glGetError() != GL_INVALID_VALUE) 5080 { 5081 Output("BindImageTexture should generate INVALID_VALUE if <texture> is not the name of an existing texture " 5082 "object.\n"); 5083 return ERROR; 5084 } 5085 5086 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA); 5087 if (glGetError() != GL_INVALID_VALUE) 5088 { 5089 Output("BindImageTexture should generate INVALID_VALUE if <format> is not a legal format.\n"); 5090 return ERROR; 5091 } 5092 5093 glBindImageTexture(1, m_texture, -1, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); 5094 if (glGetError() != GL_INVALID_VALUE) 5095 { 5096 Output("BindImageTexture should generate INVALID_VALUE if <level> is less than zero.\n"); 5097 return ERROR; 5098 } 5099 5100 glBindImageTexture(1, m_texture, 0, GL_FALSE, -1, GL_READ_ONLY, GL_RGBA32F); 5101 if (glGetError() != GL_INVALID_VALUE) 5102 { 5103 Output("BindImageTexture should generate INVALID_VALUE if <layer> is less than zero.\n"); 5104 return ERROR; 5105 } 5106 5107 glGenTextures(1, &m_texture2); 5108 glBindTexture(GL_TEXTURE_2D, m_texture2); 5109 glBindImageTexture(1, m_texture2, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); 5110 if (glGetError() != GL_INVALID_OPERATION) 5111 { 5112 Output("BindImageTexture should generate INVALID_OPERATION if <texture> is a mutable texture object.\n"); 5113 return ERROR; 5114 } 5115 5116 return NO_ERROR; 5117 } 5118 5119 virtual long Cleanup() 5120 { 5121 glDeleteTextures(1, &m_texture); 5122 glDeleteTextures(1, &m_texture2); 5123 return NO_ERROR; 5124 } 5125}; 5126//----------------------------------------------------------------------------- 5127// 4.3 NegativeCompileErrors 5128//----------------------------------------------------------------------------- 5129class NegativeCompileErrors : public ShaderImageLoadStoreBase 5130{ 5131 virtual long Run() 5132 { 5133 if (!Compile( // writeonly & readonly qualifiers 5134 NL "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL 5135 " vec4 o_color;" NL " o_color = imageLoad(g_image, ivec2(0));" NL "}")) 5136 return ERROR; 5137 5138 if (!Compile( // writeonly && reading 5139 NL "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL " vec4 o_color;" NL 5140 " o_color = imageLoad(g_image, ivec2(0));" NL "}")) 5141 return ERROR; 5142 5143 if (!Compile( //readonly && writing 5144 NL "uniform vec4 i_color;" NL "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL 5145 " vec4 o_color;" NL " imageStore(g_image, ivec2(0), i_color);" NL " o_color = i_color;" NL "}")) 5146 return ERROR; 5147 5148 if (!Compile( // no format layout && load 5149 NL "uniform image2D g_image;" NL "void main() {" NL " vec4 o_color;" NL 5150 " o_color = imageLoad(g_image, ivec2(0));" NL "}")) 5151 return ERROR; 5152 5153 if (!Compile( // no fromat layout && readonly && load 5154 NL "readonly uniform image2D g_image;" NL "void main() {" NL " vec4 o_color;" NL 5155 " o_color = imageLoad(g_image, ivec2(0));" NL "}")) 5156 return ERROR; 5157 5158 if (!Compile( // target type image1D not supported 5159 NL "layout(r32i) uniform image1D g_image;" NL "void main() {" NL " vec4 o_color;" NL 5160 " o_color = vec4(1.0);" NL "}")) 5161 return ERROR; 5162 5163 if (!Compile( // format layout not compatible with type 5164 NL "layout(rgba16) writeonly uniform iimage2D g_image;" NL "void main() {" NL " vec4 o_color;" NL 5165 " o_color = vec4(1.0);" NL "}")) 5166 return ERROR; 5167 5168 if (!Compile( // imageAtomicAdd doesn't support r32f 5169 NL "#extension GL_OES_shader_image_atomic : require" NL 5170 "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL " vec4 o_color;" NL 5171 " imageAtomicAdd(g_image, ivec2(1), 10);" NL " o_color = vec4(1.0);" NL "}")) 5172 return ERROR; 5173 5174 if (!Compile( // imageAtomicAdd doesn't support rgba8i 5175 NL "#extension GL_OES_shader_image_atomic : require" NL 5176 "layout(rgba8i) coherent uniform iimage2D g_image;" NL "void main() {" NL " vec4 o_color;" NL 5177 " imageAtomicAdd(g_image, ivec2(1), 1);" NL " o_color = vec4(1.0);" NL "}")) 5178 return ERROR; 5179 5180 if (!Compile( // format layout not compatible with type 5181 NL "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL " vec4 o_color;" NL 5182 " imageStore(g_image, ivec3(1), ivec4(1));" NL " o_color = vec4(1.0);" NL "}")) 5183 return ERROR; 5184 5185 if (!Compile( // format layout not compatible with type 5186 NL "layout(r32f) uniform uimage2DArray g_image;" NL "void main() {" NL " vec4 o_color;" NL 5187 " imageStore(g_image, ivec3(0), uvec4(1));" NL " o_color = vec4(1.0);" NL "}")) 5188 return ERROR; 5189 5190 if (!Compile( // wrong function argument type 5191 NL "layout(r32f) coherent uniform image2D g_image;" NL "vec4 Load(iimage2D image) {" NL 5192 " return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL " vec4 o_color;" NL 5193 " o_color = Load(g_image);" NL "}")) 5194 return ERROR; 5195 5196 return NO_ERROR; 5197 } 5198 5199 bool Compile(const std::string& source) 5200 { 5201 const char* const csVer = "#version 310 es" NL "layout(local_size_x = 1) in;"; 5202 const char* const src[3] = { csVer, kGLSLPrec, source.c_str() }; 5203 const GLuint sh = glCreateShader(GL_COMPUTE_SHADER); 5204 glShaderSource(sh, 3, src, NULL); 5205 glCompileShader(sh); 5206 5207 GLchar log[1024]; 5208 glGetShaderInfoLog(sh, sizeof(log), NULL, log); 5209 Output("Shader Info Log:\n%s\n", log); 5210 5211 GLint status; 5212 glGetShaderiv(sh, GL_COMPILE_STATUS, &status); 5213 glDeleteShader(sh); 5214 5215 if (status == GL_TRUE) 5216 { 5217 Output("Compilation should fail [compute shader].\n"); 5218 return false; 5219 } 5220 const char* const fsVer = "#version 310 es" NL "precision highp float;"; 5221 const char* const fsrc[3] = { fsVer, kGLSLPrec, source.c_str() }; 5222 const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER); 5223 glShaderSource(fsh, 3, fsrc, NULL); 5224 glCompileShader(fsh); 5225 5226 glGetShaderInfoLog(fsh, sizeof(log), NULL, log); 5227 Output("Shader Info Log:\n%s\n", log); 5228 5229 glGetShaderiv(fsh, GL_COMPILE_STATUS, &status); 5230 glDeleteShader(fsh); 5231 5232 if (status == GL_TRUE) 5233 { 5234 Output("Compilation should fail [fragment shader].\n"); 5235 return false; 5236 } 5237 5238 return true; 5239 } 5240}; 5241 5242//----------------------------------------------------------------------------- 5243// 4.4 NegativeLinkErrors 5244//----------------------------------------------------------------------------- 5245class NegativeLinkErrors : public ShaderImageLoadStoreBase 5246{ 5247 virtual long Run() 5248 { 5249 if (!IsVSFSAvailable(1, 1)) 5250 return NOT_SUPPORTED; 5251 if (!Link(NL "layout(location = 0) in vec4 i_position;" NL 5252 "layout(rgba32f) writeonly uniform highp image3D g_image;" NL "void main() {" NL 5253 " imageStore(g_image, ivec3(gl_VertexID), vec4(0));" NL " gl_Position = i_position;" NL "}", 5254 5255 NL "precision highp float;" NL "layout(location = 0) out vec4 o_color;" NL 5256 "layout(rgba32f) writeonly uniform highp image2D g_image;" NL "void main() {" NL 5257 " imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}")) 5258 return ERROR; 5259 5260 if (!Link(NL "layout(location = 0) in vec4 i_position;" NL 5261 "layout(rgba32f) writeonly uniform highp image2D g_image;" NL "void main() {" NL 5262 " imageStore(g_image, ivec2(gl_VertexID), vec4(0));" NL " gl_Position = i_position;" NL "}", 5263 5264 NL "precision highp float;" NL "layout(location = 0) out vec4 o_color;" NL 5265 "layout(r32f) writeonly uniform highp image2D g_image;" NL "void main() {" NL 5266 " imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}")) 5267 return ERROR; 5268 5269 return NO_ERROR; 5270 } 5271 5272 bool Link(const std::string& vs, const std::string& fs) 5273 { 5274 const char* const sVer = "#version 310 es"; 5275 const GLuint p = glCreateProgram(); 5276 5277 const GLuint vsh = glCreateShader(GL_VERTEX_SHADER); 5278 glAttachShader(p, vsh); 5279 glDeleteShader(vsh); 5280 const char* const vssrc[2] = { sVer, vs.c_str() }; 5281 glShaderSource(vsh, 2, vssrc, NULL); 5282 glCompileShader(vsh); 5283 5284 const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER); 5285 glAttachShader(p, fsh); 5286 glDeleteShader(fsh); 5287 const char* const fssrc[2] = { sVer, fs.c_str() }; 5288 glShaderSource(fsh, 2, fssrc, NULL); 5289 glCompileShader(fsh); 5290 5291 GLint status; 5292 glGetShaderiv(vsh, GL_COMPILE_STATUS, &status); 5293 if (status == GL_FALSE) 5294 { 5295 glDeleteProgram(p); 5296 Output("VS compilation should be ok.\n"); 5297 return false; 5298 } 5299 glGetShaderiv(fsh, GL_COMPILE_STATUS, &status); 5300 if (status == GL_FALSE) 5301 { 5302 glDeleteProgram(p); 5303 Output("FS compilation should be ok.\n"); 5304 return false; 5305 } 5306 5307 glLinkProgram(p); 5308 5309 GLchar log[1024]; 5310 glGetProgramInfoLog(p, sizeof(log), NULL, log); 5311 Output("Program Info Log:\n%s\n", log); 5312 5313 glGetProgramiv(p, GL_LINK_STATUS, &status); 5314 glDeleteProgram(p); 5315 5316 if (status == GL_TRUE) 5317 { 5318 Output("Link operation should fail.\n"); 5319 return false; 5320 } 5321 return true; 5322 } 5323}; 5324 5325} // anonymous namespace 5326 5327ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(glcts::Context& context) 5328 : TestCaseGroup(context, "shader_image_load_store", "") 5329{ 5330} 5331 5332ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void) 5333{ 5334} 5335 5336void ShaderImageLoadStoreTests::init() 5337{ 5338 using namespace glcts; 5339 setOutput(m_context.getTestContext().getLog()); 5340 addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>)); 5341 addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>)); 5342 addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>)); 5343 addChild(new TestSubcase(m_context, "basic-api-barrier-byRegion", TestSubcase::Create<BasicAPIBarrierByRegion>)); 5344 addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>)); 5345 addChild(new TestSubcase(m_context, "basic-allFormats-store-fs", TestSubcase::Create<BasicAllFormatsStoreFS>)); 5346 addChild(new TestSubcase(m_context, "basic-allFormats-store-cs", TestSubcase::Create<BasicAllFormatsStoreCS>)); 5347 addChild(new TestSubcase(m_context, "basic-allFormats-load-fs", TestSubcase::Create<BasicAllFormatsLoadFS>)); 5348 addChild(new TestSubcase(m_context, "basic-allFormats-load-cs", TestSubcase::Create<BasicAllFormatsLoadCS>)); 5349 addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage", 5350 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>)); 5351 addChild(new TestSubcase(m_context, "basic-allTargets-store-fs", TestSubcase::Create<BasicAllTargetsStoreFS>)); 5352 addChild(new TestSubcase(m_context, "basic-allTargets-store-cs", TestSubcase::Create<BasicAllTargetsStoreCS>)); 5353 addChild(new TestSubcase(m_context, "basic-allTargets-load-fs", TestSubcase::Create<BasicAllTargetsLoadFS>)); 5354 addChild(new TestSubcase(m_context, "basic-allTargets-load-cs", TestSubcase::Create<BasicAllTargetsLoadCS>)); 5355 addChild(new TestSubcase(m_context, "basic-allTargets-atomicFS", TestSubcase::Create<BasicAllTargetsAtomicFS>)); 5356 addChild( 5357 new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>)); 5358 addChild( 5359 new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>)); 5360 addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>)); 5361 addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>)); 5362 addChild(new TestSubcase(m_context, "basic-glsl-misc-fs", TestSubcase::Create<BasicGLSLMiscFS>)); 5363 addChild(new TestSubcase(m_context, "basic-glsl-misc-cs", TestSubcase::Create<BasicGLSLMiscCS>)); 5364 addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>)); 5365 addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>)); 5366 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>)); 5367 addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>)); 5368 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>)); 5369 addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>)); 5370 addChild(new TestSubcase(m_context, "advanced-memory-order-vsfs", TestSubcase::Create<AdvancedMemoryOrderVSFS>)); 5371 addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>)); 5372 addChild(new TestSubcase(m_context, "advanced-copyImage-fs", TestSubcase::Create<AdvancedCopyImageFS>)); 5373 addChild(new TestSubcase(m_context, "advanced-copyImage-cs", TestSubcase::Create<AdvancedCopyImageCS>)); 5374 addChild(new TestSubcase(m_context, "advanced-allMips-fs", TestSubcase::Create<AdvancedAllMipsFS>)); 5375 addChild(new TestSubcase(m_context, "advanced-allMips-cs", TestSubcase::Create<AdvancedAllMipsCS>)); 5376 addChild(new TestSubcase(m_context, "advanced-cast-fs", TestSubcase::Create<AdvancedCastFS>)); 5377 addChild(new TestSubcase(m_context, "advanced-cast-cs", TestSubcase::Create<AdvancedCastCS>)); 5378 addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>)); 5379 addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>)); 5380 addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>)); 5381 addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>)); 5382} 5383} 5384