1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 */ /*-------------------------------------------------------------------*/
24 #include "gl4cShaderImageLoadStoreTests.hpp"
25 #include "gluContextInfo.hpp"
26 #include "glwEnums.hpp"
27 #include "tcuMatrix.hpp"
28 #include "tcuRenderTarget.hpp"
29 #include "tcuVectorUtil.hpp"
37 #include <tcuFloat.hpp>
45 typedef tcu::Vec2 vec2;
46 typedef tcu::Vec4 vec4;
47 typedef tcu::IVec4 ivec4;
48 typedef tcu::UVec4 uvec4;
49 typedef tcu::Mat4 mat4;
51 class ShaderImageLoadStoreBase : public deqp::SubcaseBase
53 virtual std::string Title()
58 virtual std::string Purpose()
63 virtual std::string Method()
68 virtual std::string PassCriteria()
74 bool SupportedInVS(int requiredVS)
77 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
78 if (imagesVS >= requiredVS)
82 std::ostringstream reason;
83 reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
85 OutputNotSupported(reason.str());
90 bool SupportedInTCS(int requiredTCS)
93 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
94 if (imagesTCS >= requiredTCS)
98 std::ostringstream reason;
99 reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
101 OutputNotSupported(reason.str());
106 bool SupportedInTES(int requiredTES)
109 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
110 if (imagesTES >= requiredTES)
114 std::ostringstream reason;
115 reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
117 OutputNotSupported(reason.str());
122 bool SupportedInGS(int requiredGS)
125 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
126 if (imagesGS >= requiredGS)
130 std::ostringstream reason;
131 reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
133 OutputNotSupported(reason.str());
138 bool SupportedInGeomStages(int required)
140 return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) &&
141 SupportedInGS(required);
144 bool SupportedInStage(int stage, int required)
149 return SupportedInVS(required);
151 return SupportedInTCS(required);
153 return SupportedInTES(required);
155 return SupportedInGS(required);
161 bool SupportedSamples(int required)
164 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
169 std::ostringstream reason;
170 reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
171 OutputNotSupported(reason.str());
178 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
179 return renderTarget.getWidth();
182 int getWindowHeight()
184 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
185 return renderTarget.getHeight();
188 inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon)
190 if (fabs(c0[0] - c1[0]) > epsilon[0])
192 if (fabs(c0[1] - c1[1]) > epsilon[1])
194 if (fabs(c0[2] - c1[2]) > epsilon[2])
196 if (fabs(c0[3] - c1[3]) > epsilon[3])
201 bool IsEqual(vec4 a, vec4 b)
203 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
206 bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat)
208 if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM)
210 return ColorEqual(v0, v1, vec4(0.0001f));
212 else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM)
214 return ColorEqual(v0, v1, vec4(0.01f));
216 return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
219 bool Equal(const ivec4& a, const ivec4& b, GLenum)
221 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
224 bool Equal(const uvec4& a, const uvec4& b, GLenum)
226 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
230 std::string ToString(T v)
232 std::ostringstream s;
234 for (int i = 0; i < 4; ++i)
235 s << v[i] << (i == 3 ? "" : ",");
240 bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected)
243 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
244 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat();
245 vec4 g_color_eps = vec4(
246 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
247 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
249 std::vector<vec4> fb(w * h);
250 glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
252 for (int yy = 0; yy < h; ++yy)
254 for (int xx = 0; xx < w; ++xx)
256 const int idx = yy * w + xx;
257 if (!ColorEqual(fb[idx], expected, g_color_eps))
259 m_context.getTestContext().getLog()
260 << tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
261 << tcu::TestLog::EndMessage;
270 bool CompileShader(GLuint shader)
272 glCompileShader(shader);
275 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
276 if (status == GL_FALSE)
280 glGetShaderInfoLog(shader, sizeof(log), &length, log);
283 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
284 << log << tcu::TestLog::EndMessage;
291 bool LinkProgram(GLuint program)
293 glLinkProgram(program);
296 glGetProgramiv(program, GL_LINK_STATUS, &status);
297 if (status == GL_FALSE)
301 glGetProgramInfoLog(program, sizeof(log), &length, log);
304 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
305 << log << tcu::TestLog::EndMessage;
312 GLuint BuildProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs,
313 const char* src_fs, bool* result = NULL)
315 const GLuint p = glCreateProgram();
319 GLuint sh = glCreateShader(GL_VERTEX_SHADER);
320 glAttachShader(p, sh);
322 glShaderSource(sh, 1, &src_vs, NULL);
323 if (!CompileShader(sh))
325 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
333 GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
334 glAttachShader(p, sh);
336 glShaderSource(sh, 1, &src_tcs, NULL);
337 if (!CompileShader(sh))
339 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
347 GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
348 glAttachShader(p, sh);
350 glShaderSource(sh, 1, &src_tes, NULL);
351 if (!CompileShader(sh))
353 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
361 GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
362 glAttachShader(p, sh);
364 glShaderSource(sh, 1, &src_gs, NULL);
365 if (!CompileShader(sh))
367 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
375 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
376 glAttachShader(p, sh);
378 glShaderSource(sh, 1, &src_fs, NULL);
379 if (!CompileShader(sh))
381 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
390 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
392 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
394 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
396 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
398 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
407 GLuint BuildShaderProgram(GLenum type, const char* src)
409 const GLuint p = glCreateShaderProgramv(type, 1, &src);
412 glGetProgramiv(p, GL_LINK_STATUS, &status);
413 if (status == GL_FALSE)
416 glGetProgramInfoLog(p, sizeof(log), NULL, log);
417 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
419 << src << tcu::TestLog::EndMessage;
425 void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo)
429 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
431 -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f,
432 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
433 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
435 glGenBuffers(1, vbo);
436 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
437 glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
438 glBindBuffer(GL_ARRAY_BUFFER, 0);
442 std::vector<GLushort> index_data(4);
443 for (int i = 0; i < 4; ++i)
445 index_data[i] = static_cast<GLushort>(i);
447 glGenBuffers(1, ebo);
448 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
449 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
450 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
453 glGenVertexArrays(1, vao);
454 glBindVertexArray(*vao);
455 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
456 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
457 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2));
458 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5));
459 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8));
460 glBindBuffer(GL_ARRAY_BUFFER, 0);
461 glEnableVertexAttribArray(0);
462 glEnableVertexAttribArray(1);
463 glEnableVertexAttribArray(2);
464 glEnableVertexAttribArray(3);
467 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
469 glBindVertexArray(0);
472 std::string FormatEnumToString(GLenum e)
484 case GL_R11F_G11F_B10F:
485 return "r11f_g11f_b10f";
546 case GL_RGBA16_SNORM:
547 return "rgba16_snorm";
549 return "rgba8_snorm";
564 const char* StageName(int stage)
569 return "Vertex Shader";
571 return "Tessellation Control Shader";
573 return "Tessellation Evaluation Shader";
575 return "Geometry Shader";
577 return "Compute Shader";
583 template <typename T>
586 template <typename T>
589 template <typename T>
590 std::string TypePrefix();
592 template <typename T>
593 GLenum ImageType(GLenum target);
595 void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color)
597 glClearBufferfv(buffer, drawbuffer, &color[0]);
600 void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color)
602 glClearBufferiv(buffer, drawbuffer, &color[0]);
605 void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color)
607 glClearBufferuiv(buffer, drawbuffer, &color[0]);
610 bool CheckUniform(GLuint program, const std::string& name, const std::map<std::string, GLuint>& name_index_map,
611 GLint size, GLenum type)
613 std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name);
614 assert(iter != name_index_map.end());
621 glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl);
623 if (std::string(name_gl) != name)
625 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl
626 << " should be " << name << tcu::TestLog::EndMessage;
629 if (length_gl != static_cast<GLsizei>(name.length()))
631 m_context.getTestContext().getLog()
632 << tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl
633 << ")" << tcu::TestLog::EndMessage;
638 m_context.getTestContext().getLog()
639 << tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl
640 << ")" << tcu::TestLog::EndMessage;
645 m_context.getTestContext().getLog()
646 << tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl
647 << ")" << tcu::TestLog::EndMessage;
654 bool CheckMax(GLenum pname, GLint min_value)
662 glGetIntegerv(pname, &i);
666 glGetBooleanv(pname, &b);
667 if (b != (i ? GL_TRUE : GL_FALSE))
670 glGetFloatv(pname, &f);
671 if (static_cast<GLint>(f) < min_value)
674 glGetDoublev(pname, &d);
675 if (static_cast<GLint>(d) < min_value)
678 glGetInteger64v(pname, &i64);
679 if (static_cast<GLint>(i64) < min_value)
685 bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
691 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
692 if (static_cast<GLuint>(i) != texture)
694 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
695 << " should be " << texture << tcu::TestLog::EndMessage;
698 glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b);
699 if (b != (i ? GL_TRUE : GL_FALSE))
701 m_context.getTestContext().getLog()
702 << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be "
703 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
707 glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
710 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
711 << " should be " << level << tcu::TestLog::EndMessage;
714 glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b);
715 if (b != (i ? GL_TRUE : GL_FALSE))
717 m_context.getTestContext().getLog()
718 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be "
719 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
723 glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
726 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
727 << " should be " << layered << tcu::TestLog::EndMessage;
730 glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
731 if (b != (i ? GL_TRUE : GL_FALSE))
733 m_context.getTestContext().getLog()
734 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be "
735 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
739 glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
742 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
743 << " should be " << layer << tcu::TestLog::EndMessage;
746 glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b);
747 if (b != (i ? GL_TRUE : GL_FALSE))
749 m_context.getTestContext().getLog()
750 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be "
751 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
755 glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
756 if (static_cast<GLenum>(i) != access)
758 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
759 << " should be " << access << tcu::TestLog::EndMessage;
762 glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b);
763 if (b != (i ? GL_TRUE : GL_FALSE))
765 m_context.getTestContext().getLog()
766 << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be "
767 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
771 glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
772 if (static_cast<GLenum>(i) != format)
774 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
775 << " should be " << format << tcu::TestLog::EndMessage;
778 glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b);
779 if (b != (i ? GL_TRUE : GL_FALSE))
781 m_context.getTestContext().getLog()
782 << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be "
783 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
789 const char* EnumToString(GLenum e)
794 return "GL_TEXTURE_1D";
796 return "GL_TEXTURE_2D";
798 return "GL_TEXTURE_3D";
799 case GL_TEXTURE_RECTANGLE:
800 return "GL_TEXTURE_RECTANGLE";
801 case GL_TEXTURE_CUBE_MAP:
802 return "GL_TEXTURE_CUBE_MAP";
803 case GL_TEXTURE_1D_ARRAY:
804 return "GL_TEXTURE_1D_ARRAY";
805 case GL_TEXTURE_2D_ARRAY:
806 return "GL_TEXTURE_2D_ARRAY";
807 case GL_TEXTURE_CUBE_MAP_ARRAY:
808 return "GL_TEXTURE_CUBE_MAP_ARRAY";
819 GLenum ShaderImageLoadStoreBase::Format<vec4>()
825 GLenum ShaderImageLoadStoreBase::Format<ivec4>()
827 return GL_RGBA_INTEGER;
831 GLenum ShaderImageLoadStoreBase::Format<uvec4>()
833 return GL_RGBA_INTEGER;
837 GLenum ShaderImageLoadStoreBase::Format<GLint>()
839 return GL_RED_INTEGER;
843 GLenum ShaderImageLoadStoreBase::Format<GLuint>()
845 return GL_RED_INTEGER;
849 GLenum ShaderImageLoadStoreBase::Type<vec4>()
855 GLenum ShaderImageLoadStoreBase::Type<ivec4>()
861 GLenum ShaderImageLoadStoreBase::Type<uvec4>()
863 return GL_UNSIGNED_INT;
867 GLenum ShaderImageLoadStoreBase::Type<GLint>()
873 GLenum ShaderImageLoadStoreBase::Type<GLuint>()
875 return GL_UNSIGNED_INT;
879 std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
885 std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
891 std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
897 std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
903 std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
909 GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
919 case GL_TEXTURE_RECTANGLE:
920 return GL_IMAGE_2D_RECT;
921 case GL_TEXTURE_CUBE_MAP:
922 return GL_IMAGE_CUBE;
923 case GL_TEXTURE_BUFFER:
924 return GL_IMAGE_BUFFER;
925 case GL_TEXTURE_1D_ARRAY:
926 return GL_IMAGE_1D_ARRAY;
927 case GL_TEXTURE_2D_ARRAY:
928 return GL_IMAGE_2D_ARRAY;
929 case GL_TEXTURE_CUBE_MAP_ARRAY:
930 return GL_IMAGE_CUBE_MAP_ARRAY;
931 case GL_TEXTURE_2D_MULTISAMPLE:
932 return GL_IMAGE_2D_MULTISAMPLE;
933 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
934 return GL_IMAGE_2D_MULTISAMPLE_ARRAY;
941 GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
946 return GL_INT_IMAGE_1D;
948 return GL_INT_IMAGE_2D;
950 return GL_INT_IMAGE_3D;
951 case GL_TEXTURE_RECTANGLE:
952 return GL_INT_IMAGE_2D_RECT;
953 case GL_TEXTURE_CUBE_MAP:
954 return GL_INT_IMAGE_CUBE;
955 case GL_TEXTURE_BUFFER:
956 return GL_INT_IMAGE_BUFFER;
957 case GL_TEXTURE_1D_ARRAY:
958 return GL_INT_IMAGE_1D_ARRAY;
959 case GL_TEXTURE_2D_ARRAY:
960 return GL_INT_IMAGE_2D_ARRAY;
961 case GL_TEXTURE_CUBE_MAP_ARRAY:
962 return GL_INT_IMAGE_CUBE_MAP_ARRAY;
963 case GL_TEXTURE_2D_MULTISAMPLE:
964 return GL_INT_IMAGE_2D_MULTISAMPLE;
965 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
966 return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
973 GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
978 return GL_UNSIGNED_INT_IMAGE_1D;
980 return GL_UNSIGNED_INT_IMAGE_2D;
982 return GL_UNSIGNED_INT_IMAGE_3D;
983 case GL_TEXTURE_RECTANGLE:
984 return GL_UNSIGNED_INT_IMAGE_2D_RECT;
985 case GL_TEXTURE_CUBE_MAP:
986 return GL_UNSIGNED_INT_IMAGE_CUBE;
987 case GL_TEXTURE_BUFFER:
988 return GL_UNSIGNED_INT_IMAGE_BUFFER;
989 case GL_TEXTURE_1D_ARRAY:
990 return GL_UNSIGNED_INT_IMAGE_1D_ARRAY;
991 case GL_TEXTURE_2D_ARRAY:
992 return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
993 case GL_TEXTURE_CUBE_MAP_ARRAY:
994 return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
995 case GL_TEXTURE_2D_MULTISAMPLE:
996 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
997 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
998 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1004 //-----------------------------------------------------------------------------
1005 // 1.1.1 BasicAPIGet
1006 //-----------------------------------------------------------------------------
1007 class BasicAPIGet : public ShaderImageLoadStoreBase
1011 if (!CheckMax(GL_MAX_IMAGE_UNITS, 8))
1013 m_context.getTestContext().getLog()
1014 << tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
1017 if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8))
1019 m_context.getTestContext().getLog()
1020 << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
1021 << tcu::TestLog::EndMessage;
1024 if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0))
1026 m_context.getTestContext().getLog()
1027 << tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage;
1030 if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
1032 m_context.getTestContext().getLog()
1033 << tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
1034 << tcu::TestLog::EndMessage;
1037 if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0))
1039 m_context.getTestContext().getLog()
1040 << tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid."
1041 << tcu::TestLog::EndMessage;
1044 if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0))
1046 m_context.getTestContext().getLog()
1047 << tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid."
1048 << tcu::TestLog::EndMessage;
1051 if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0))
1053 m_context.getTestContext().getLog()
1054 << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid."
1055 << tcu::TestLog::EndMessage;
1058 if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8))
1060 m_context.getTestContext().getLog()
1061 << tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
1062 << tcu::TestLog::EndMessage;
1065 if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8))
1067 m_context.getTestContext().getLog()
1068 << tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
1069 << tcu::TestLog::EndMessage;
1075 //-----------------------------------------------------------------------------
1076 // 1.1.2 BasicAPIBind
1077 //-----------------------------------------------------------------------------
1078 class BasicAPIBind : public ShaderImageLoadStoreBase
1082 virtual long Setup()
1090 for (GLuint index = 0; index < 8; ++index)
1092 if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8))
1094 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
1095 << " has invalid default state." << tcu::TestLog::EndMessage;
1100 glGenTextures(1, &m_texture);
1101 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
1102 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL);
1103 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL);
1104 glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL);
1105 glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL);
1106 glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL);
1107 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1109 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
1110 if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
1113 glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
1114 if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
1117 glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16);
1118 if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16))
1121 glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
1122 if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
1125 glDeleteTextures(1, &m_texture);
1128 for (GLuint index = 0; index < 8; ++index)
1131 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
1134 m_context.getTestContext().getLog()
1135 << tcu::TestLog::Message << "Binding point " << index
1136 << " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
1144 virtual long Cleanup()
1146 glDeleteTextures(1, &m_texture);
1150 //-----------------------------------------------------------------------------
1151 // 1.1.3 BasicAPIBarrier
1152 //-----------------------------------------------------------------------------
1153 class BasicAPIBarrier : public ShaderImageLoadStoreBase
1157 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
1158 glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
1159 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
1160 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1161 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1162 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1163 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1164 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1165 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1166 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1167 glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1168 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1170 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1171 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1172 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1173 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
1175 glMemoryBarrier(GL_ALL_BARRIER_BITS);
1180 //-----------------------------------------------------------------------------
1181 // 1.1.4 BasicAPITexParam
1182 //-----------------------------------------------------------------------------
1183 class BasicAPITexParam : public ShaderImageLoadStoreBase
1187 virtual long Setup()
1195 glGenTextures(1, &m_texture);
1196 glBindTexture(GL_TEXTURE_2D, m_texture);
1197 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL);
1203 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1204 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1206 m_context.getTestContext().getLog()
1207 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1208 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1209 << tcu::TestLog::EndMessage;
1212 glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1213 if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1215 m_context.getTestContext().getLog()
1216 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1217 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1218 << tcu::TestLog::EndMessage;
1221 glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1222 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1224 m_context.getTestContext().getLog()
1225 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1226 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1227 << tcu::TestLog::EndMessage;
1230 glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui);
1231 if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1233 m_context.getTestContext().getLog()
1234 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1235 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1236 << tcu::TestLog::EndMessage;
1243 virtual long Cleanup()
1245 glDeleteTextures(1, &m_texture);
1249 //-----------------------------------------------------------------------------
1250 // 1.2.1 BasicAllFormatsStore
1251 //-----------------------------------------------------------------------------
1252 class BasicAllFormatsStore : public ShaderImageLoadStoreBase
1257 virtual long Setup()
1266 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1268 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1270 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1272 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1275 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1277 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1279 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1282 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1284 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1286 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1289 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1292 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1294 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1296 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1299 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1301 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1303 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1306 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1308 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1310 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1312 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1315 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1317 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1319 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1322 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1324 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1326 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1329 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1331 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1333 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1335 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1338 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1340 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1342 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1345 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1347 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1349 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1352 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1354 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1356 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1362 template <typename T>
1363 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1365 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1366 " gl_Position = i_position;" NL "}";
1367 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
1368 const int kSize = 16;
1369 std::vector<T> data(kSize * kSize);
1371 glGenTextures(1, &texture);
1373 for (GLuint unit = 0; unit < 8; ++unit)
1375 glBindTexture(GL_TEXTURE_2D, texture);
1376 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1377 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1378 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1379 glBindTexture(GL_TEXTURE_2D, 0);
1381 glViewport(0, 0, kSize, kSize);
1382 glUseProgram(program);
1383 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1384 glBindVertexArray(m_vao);
1385 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1387 glBindTexture(GL_TEXTURE_2D, texture);
1388 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1389 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
1391 for (int i = 0; i < kSize * kSize; ++i)
1393 if (!Equal(data[i], expected_value, internalformat))
1395 glDeleteTextures(1, &texture);
1397 glDeleteProgram(program);
1398 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i])
1399 << ". Value should be: " << ToString(expected_value)
1400 << ". Format is: " << FormatEnumToString(internalformat)
1401 << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1408 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1412 glDeleteTextures(1, &texture);
1414 glDeleteProgram(program);
1419 virtual long Cleanup()
1421 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1422 glDeleteVertexArrays(1, &m_vao);
1423 glDeleteBuffers(1, &m_vbo);
1427 template <typename T>
1428 std::string GenFS(GLenum internalformat, const T& value)
1430 std::ostringstream os;
1431 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1432 << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1433 " imageStore(g_image, coord, "
1434 << TypePrefix<T>() << "vec4" << value << ");" NL " discard;" NL "}";
1438 //-----------------------------------------------------------------------------
1439 // 1.2.2 BasicAllFormatsLoad
1440 //-----------------------------------------------------------------------------
1441 class BasicAllFormatsLoad : public ShaderImageLoadStoreBase
1446 virtual long Setup()
1455 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1457 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1459 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1461 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1464 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1466 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1468 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1471 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1473 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1475 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1478 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1481 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1483 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1485 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1488 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1490 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1492 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1495 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1497 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1499 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1501 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1504 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1506 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1508 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1511 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1513 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1515 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1518 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1520 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1522 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1524 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1527 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1529 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1531 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1534 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1536 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1538 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1541 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1543 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1545 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1551 template <typename T>
1552 bool Read(GLenum internalformat, const T& value, const T& expected_value)
1554 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1555 " gl_Position = i_position;" NL "}";
1556 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
1557 const int kSize = 16;
1558 std::vector<T> data(kSize * kSize, value);
1560 glGenTextures(1, &texture);
1562 for (GLuint unit = 0; unit < 8; ++unit)
1564 glBindTexture(GL_TEXTURE_2D, texture);
1565 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1566 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1567 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1568 glBindTexture(GL_TEXTURE_2D, 0);
1570 glViewport(0, 0, kSize, kSize);
1571 glClear(GL_COLOR_BUFFER_BIT);
1572 glUseProgram(program);
1573 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1574 glBindVertexArray(m_vao);
1575 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1577 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
1579 glDeleteTextures(1, &texture);
1581 glDeleteProgram(program);
1582 m_context.getTestContext().getLog()
1583 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
1584 << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1590 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1594 glDeleteTextures(1, &texture);
1596 glDeleteProgram(program);
1601 virtual long Cleanup()
1603 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1604 glDeleteVertexArrays(1, &m_vao);
1605 glDeleteBuffers(1, &m_vbo);
1609 template <typename T>
1610 std::string GenFS(GLenum internalformat, const T& expected_value)
1612 std::ostringstream os;
1613 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
1614 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
1615 << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
1616 << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
1618 << ") o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " else o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1622 //-----------------------------------------------------------------------------
1623 // 1.2.3 BasicAllFormatsStoreGeometryStages
1624 //-----------------------------------------------------------------------------
1625 class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase
1629 virtual long Setup()
1631 glGenVertexArrays(1, &m_vao);
1637 if (!SupportedInGeomStages(1))
1638 return NOT_SUPPORTED;
1639 glEnable(GL_RASTERIZER_DISCARD);
1641 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1643 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1645 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1648 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1650 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1652 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1655 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1657 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1659 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1662 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1665 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1667 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1669 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1672 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1674 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1676 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1679 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1681 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1683 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1685 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1688 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1690 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1692 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1695 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1697 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1699 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1702 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1704 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1706 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1708 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1711 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1713 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1715 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1718 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1720 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1722 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1725 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1727 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1729 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1735 template <typename T>
1736 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1738 const GLuint program =
1739 BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(),
1740 GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL);
1741 const int kSize = 1;
1742 std::vector<T> data(kSize * kSize);
1744 glGenTextures(4, texture);
1746 for (int i = 0; i < 4; ++i)
1748 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1749 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1750 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1751 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1753 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1755 glUseProgram(program);
1756 glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1757 glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1758 glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1759 glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1760 for (GLuint i = 0; i < 4; ++i)
1762 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1764 glBindVertexArray(m_vao);
1765 glPatchParameteri(GL_PATCH_VERTICES, 1);
1766 glDrawArrays(GL_PATCHES, 0, 1);
1767 glPatchParameteri(GL_PATCH_VERTICES, 3);
1769 for (int i = 0; i < 4; ++i)
1771 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1772 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1773 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
1775 if (!Equal(data[0], expected_value, internalformat))
1777 glDeleteTextures(4, texture);
1779 glDeleteProgram(program);
1780 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0])
1781 << ". Value should be: " << ToString(expected_value)
1782 << ". Format is: " << FormatEnumToString(internalformat)
1783 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
1787 glDeleteTextures(4, texture);
1789 glDeleteProgram(program);
1793 virtual long Cleanup()
1795 glDisable(GL_RASTERIZER_DISCARD);
1796 glDeleteVertexArrays(1, &m_vao);
1800 template <typename T>
1801 std::string GenVS(GLenum internalformat, const T& value)
1803 std::ostringstream os;
1804 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1805 << TypePrefix<T>() << "image2DArray g_image0;" NL "void main() {" NL
1806 " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " imageStore(g_image0, coord, "
1807 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1811 template <typename T>
1812 std::string GenTCS(GLenum internalformat, const T& value)
1814 std::ostringstream os;
1815 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
1816 << ") writeonly uniform " << TypePrefix<T>()
1817 << "image2DArray g_image1;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
1818 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
1819 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
1820 " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " imageStore(g_image1, coord, "
1821 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1825 template <typename T>
1826 std::string GenTES(GLenum internalformat, const T& value)
1828 std::ostringstream os;
1829 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
1830 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1831 << "image2DArray g_image2;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL
1832 " imageStore(g_image2, coord, "
1833 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1837 template <typename T>
1838 std::string GenGS(GLenum internalformat, const T& value)
1840 std::ostringstream os;
1841 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
1842 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1843 << "image2DArray g_image3;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL
1844 " imageStore(g_image3, coord, "
1845 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1849 //-----------------------------------------------------------------------------
1850 // 1.2.4 BasicAllFormatsLoadGeometryStages
1851 //-----------------------------------------------------------------------------
1852 class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase
1856 virtual long Setup()
1858 glGenVertexArrays(1, &m_vao);
1864 if (!SupportedInGeomStages(2))
1865 return NOT_SUPPORTED;
1866 glEnable(GL_RASTERIZER_DISCARD);
1868 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1870 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1872 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1875 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1877 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1879 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1882 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1884 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1886 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1889 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1892 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1894 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1896 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1899 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1901 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1903 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1906 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1908 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1910 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1912 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1915 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1917 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1919 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1922 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1924 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1926 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1929 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1931 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1933 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1935 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1938 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1940 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1942 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1945 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1947 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1949 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1952 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1954 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1956 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1962 template <typename T>
1963 bool Read(GLenum internalformat, const T& value, const T& expected_value)
1965 const GLuint program = BuildProgram(
1966 GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(),
1967 GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL);
1968 const int kSize = 1;
1969 std::vector<T> data(kSize * kSize, value);
1971 glGenTextures(8, texture);
1973 for (int i = 0; i < 4; ++i)
1975 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1976 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1977 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1978 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1980 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1982 for (int i = 4; i < 8; ++i)
1984 glBindTexture(GL_TEXTURE_2D, texture[i]);
1985 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1986 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1987 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero);
1989 glBindTexture(GL_TEXTURE_2D, 0);
1991 glUseProgram(program);
1992 glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1993 glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1994 glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1995 glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1996 glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4);
1997 glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5);
1998 glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6);
1999 glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7);
2001 for (GLuint i = 0; i < 4; ++i)
2003 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2005 for (GLuint i = 4; i < 8; ++i)
2007 glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
2009 glBindVertexArray(m_vao);
2010 glPatchParameteri(GL_PATCH_VERTICES, 1);
2011 glDrawArrays(GL_PATCHES, 0, 1);
2012 glPatchParameteri(GL_PATCH_VERTICES, 3);
2014 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
2015 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat();
2016 vec4 g_color_eps = vec4(
2017 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
2018 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
2020 for (int i = 0; i < 4; ++i)
2022 glBindTexture(GL_TEXTURE_2D, texture[i + 4]);
2023 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2025 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]);
2026 if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps))
2028 glDeleteTextures(8, texture);
2030 glDeleteProgram(program);
2031 m_context.getTestContext().getLog()
2032 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
2033 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
2037 glDeleteTextures(8, texture);
2039 glDeleteProgram(program);
2043 virtual long Cleanup()
2045 glDisable(GL_RASTERIZER_DISCARD);
2046 glDeleteVertexArrays(1, &m_vao);
2050 template <typename T>
2051 std::string GenVS(GLenum internalformat, const T& expected_value)
2053 std::ostringstream os;
2054 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
2056 << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL
2057 "void main() {" NL " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " "
2058 << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2059 << expected_value << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2060 " else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2064 template <typename T>
2065 std::string GenTCS(GLenum internalformat, const T& expected_value)
2067 std::ostringstream os;
2068 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
2069 << ") readonly uniform " << TypePrefix<T>()
2070 << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL
2071 "void main() {" NL " gl_TessLevelInner[0] = 1;" NL " gl_TessLevelInner[1] = 1;" NL
2072 " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL " gl_TessLevelOuter[2] = 1;" NL
2073 " gl_TessLevelOuter[3] = 1;" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " "
2074 << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2075 << expected_value << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2076 " else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2080 template <typename T>
2081 std::string GenTES(GLenum internalformat, const T& expected_value)
2083 std::ostringstream os;
2084 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
2085 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2086 << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL
2087 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " "
2088 << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2089 << expected_value << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2090 " else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2094 template <typename T>
2095 std::string GenGS(GLenum internalformat, const T& expected_value)
2097 std::ostringstream os;
2098 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
2099 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2100 << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL
2101 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL " "
2102 << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2103 << expected_value << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2104 " else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2108 //-----------------------------------------------------------------------------
2109 // 1.2.5 BasicAllFormatsLoadStoreComputeStage
2110 //-----------------------------------------------------------------------------
2111 class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
2115 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
2117 m_context.getTestContext().getLog()
2118 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
2119 << tcu::TestLog::EndMessage;
2120 return NOT_SUPPORTED;
2123 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2125 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2127 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2130 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2132 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2134 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2137 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2139 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2141 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2144 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
2147 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2149 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2151 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2154 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2156 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2158 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2161 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2163 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2165 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2167 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2170 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2172 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2174 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2177 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2179 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2181 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2184 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
2186 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
2188 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2190 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2193 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
2195 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2197 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2200 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2202 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2204 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2207 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2209 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2211 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2217 template <typename T>
2218 bool Read(GLenum internalformat, const T& value, const T& expected_value)
2221 std::string source = GenCS<T>(internalformat);
2222 const char* const src = source.c_str();
2223 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
2224 glShaderSource(sh, 1, &src, NULL);
2225 glCompileShader(sh);
2226 program = glCreateProgram();
2227 glAttachShader(program, sh);
2228 glLinkProgram(program);
2231 const int kSize = 1;
2232 std::vector<T> data(kSize * kSize, value);
2234 glGenTextures(2, texture);
2236 glBindTexture(GL_TEXTURE_2D, texture[0]);
2237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2238 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2239 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2240 glBindTexture(GL_TEXTURE_2D, texture[1]);
2241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2244 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero);
2246 glBindTexture(GL_TEXTURE_2D, 0);
2248 glUseProgram(program);
2249 glUniform1i(glGetUniformLocation(program, "g_image_read"), 0);
2250 glUniform1i(glGetUniformLocation(program, "g_image_write"), 1);
2252 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2253 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2255 glDispatchCompute(1, 1, 1);
2257 for (int i = 0; i < 2; ++i)
2259 glBindTexture(GL_TEXTURE_2D, texture[i]);
2260 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2261 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2263 if (!Equal(data[0], expected_value, internalformat))
2265 glDeleteTextures(4, texture);
2267 glDeleteProgram(program);
2268 m_context.getTestContext().getLog()
2269 << tcu::TestLog::Message << "Value is: " << ToString(data[0])
2270 << ". Value should be: " << ToString(expected_value)
2271 << ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage;
2275 glDeleteTextures(2, texture);
2277 glDeleteProgram(program);
2281 template <typename T>
2282 std::string GenCS(GLenum internalformat)
2284 std::ostringstream os;
2285 os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL
2287 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2288 << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2289 << TypePrefix<T>() << "image2D g_image_write;" NL "void main() {" NL
2290 " ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL " "
2292 << "vec4 v = imageLoad(g_image_read, coord);" NL " imageStore(g_image_write, coord, v);" NL "}";
2296 //-----------------------------------------------------------------------------
2297 // 1.3.1 BasicAllTargetsStore
2298 //-----------------------------------------------------------------------------
2299 class BasicAllTargetsStore : public ShaderImageLoadStoreBase
2304 virtual long Setup()
2313 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2315 if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2317 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2319 if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2322 if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2324 if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2326 if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2329 if (SupportedSamples(4))
2331 if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2335 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
2338 if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2340 if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2347 virtual long Cleanup()
2349 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2350 glDeleteVertexArrays(1, &m_vao);
2351 glDeleteBuffers(1, &m_vbo);
2355 template <typename T>
2356 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
2358 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2359 " gl_Position = i_position;" NL "}";
2360 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
2363 glGenTextures(8, textures);
2364 glGenBuffers(1, &buffer);
2366 const int kSize = 16;
2367 std::vector<T> data(kSize * kSize * 2);
2369 glBindTexture(GL_TEXTURE_1D, textures[0]);
2370 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2371 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2372 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2373 glBindTexture(GL_TEXTURE_1D, 0);
2375 glBindTexture(GL_TEXTURE_2D, textures[1]);
2376 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2377 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2378 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2379 glBindTexture(GL_TEXTURE_2D, 0);
2381 glBindTexture(GL_TEXTURE_3D, textures[2]);
2382 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2383 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2384 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2385 glBindTexture(GL_TEXTURE_3D, 0);
2387 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2388 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2389 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2390 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2391 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2393 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2394 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2395 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2396 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2398 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2400 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2402 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2404 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2406 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2408 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2410 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2411 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2412 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2413 glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2414 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2415 glBindTexture(GL_TEXTURE_BUFFER, 0);
2417 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2418 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2419 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2420 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2421 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2423 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2424 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2425 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2426 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2427 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2429 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2430 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2431 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2432 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2433 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2434 glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2435 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2436 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2438 glUseProgram(program);
2439 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2440 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2441 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2442 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2443 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
2444 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
2445 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
2446 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
2448 glBindVertexArray(m_vao);
2449 glViewport(0, 0, kSize, kSize);
2450 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2454 glBindTexture(GL_TEXTURE_1D, textures[0]);
2455 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2456 glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]);
2457 glBindTexture(GL_TEXTURE_1D, 0);
2458 for (int i = 0; i < kSize; ++i)
2460 if (!tcu::allEqual(data[i], expected_value))
2463 m_context.getTestContext().getLog()
2464 << tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i])
2465 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2469 std::fill(data.begin(), data.end(), T(0));
2471 glBindTexture(GL_TEXTURE_2D, textures[1]);
2472 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2473 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2474 glBindTexture(GL_TEXTURE_2D, 0);
2475 for (int i = 0; i < kSize * kSize; ++i)
2477 if (!tcu::allEqual(data[i], expected_value))
2480 m_context.getTestContext().getLog()
2481 << tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i])
2482 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2487 glBindTexture(GL_TEXTURE_3D, textures[2]);
2488 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2489 glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]);
2490 glBindTexture(GL_TEXTURE_3D, 0);
2491 for (int i = 0; i < kSize * kSize * 2; ++i)
2493 if (!tcu::allEqual(data[i], expected_value))
2496 m_context.getTestContext().getLog()
2497 << tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i])
2498 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2503 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2504 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2505 glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]);
2506 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2507 for (int i = 0; i < kSize * kSize; ++i)
2509 if (!tcu::allEqual(data[i], expected_value))
2512 m_context.getTestContext().getLog()
2513 << tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i])
2514 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2520 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2521 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2522 for (int face = 0; face < 6; ++face)
2524 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
2525 for (int i = 0; i < kSize * kSize; ++i)
2527 if (!tcu::allEqual(data[i], expected_value))
2530 m_context.getTestContext().getLog()
2531 << tcu::TestLog::Message
2532 << "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i])
2533 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2538 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2541 glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2542 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2543 glBindTexture(GL_TEXTURE_BUFFER, 0);
2544 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2545 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]);
2546 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2547 for (int i = 0; i < kSize; ++i)
2549 if (!tcu::allEqual(data[i], expected_value))
2552 m_context.getTestContext().getLog()
2553 << tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i])
2554 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2559 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2560 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2561 glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2562 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2563 for (int i = 0; i < kSize * 2; ++i)
2565 if (!tcu::allEqual(data[i], expected_value))
2568 m_context.getTestContext().getLog()
2569 << tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i])
2570 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2575 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2576 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2577 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2578 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2579 for (int i = 0; i < kSize * kSize * 2; ++i)
2581 if (!tcu::allEqual(data[i], expected_value))
2584 m_context.getTestContext().getLog()
2585 << tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i])
2586 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2592 glDeleteProgram(program);
2593 glDeleteTextures(8, textures);
2594 glDeleteBuffers(1, &buffer);
2599 template <typename T>
2600 bool WriteMS(GLenum internalformat, const T& write_value, const T& expected_value)
2603 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2604 " gl_Position = i_position;" NL "}";
2605 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str());
2606 const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str());
2608 glGenTextures(2, textures);
2610 const int kSize = 16;
2612 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2613 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
2614 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
2616 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2617 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
2618 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
2620 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2621 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2623 glClear(GL_COLOR_BUFFER_BIT);
2624 glUseProgram(program);
2625 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
2626 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
2628 glBindVertexArray(m_vao);
2629 glViewport(0, 0, kSize, kSize);
2630 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2634 glActiveTexture(GL_TEXTURE0);
2635 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2636 glActiveTexture(GL_TEXTURE1);
2637 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2639 glUseProgram(val_program);
2640 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0);
2641 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1);
2643 glBindVertexArray(m_vao);
2644 glViewport(0, 0, kSize, kSize);
2645 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2646 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2648 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2651 m_context.getTestContext().getLog()
2652 << tcu::TestLog::Message
2653 << "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed."
2654 << tcu::TestLog::EndMessage;
2657 glActiveTexture(GL_TEXTURE0);
2658 glDeleteTextures(2, textures);
2660 glDeleteProgram(program);
2661 glDeleteProgram(val_program);
2666 template <typename T>
2667 bool WriteCubeArray(GLenum internalformat, const T& write_value, const T& expected_value)
2669 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2670 " gl_Position = i_position;" NL "}";
2671 const GLuint program =
2672 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str());
2674 glGenTextures(1, textures);
2676 const int kSize = 16;
2678 std::vector<T> data(kSize * kSize * 12);
2679 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2680 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2681 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
2683 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2685 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2687 glUseProgram(program);
2688 glBindVertexArray(m_vao);
2689 glViewport(0, 0, kSize, kSize);
2690 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2694 std::fill(data.begin(), data.end(), T(0));
2695 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2696 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2697 glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2698 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2699 for (int i = 0; i < kSize * kSize * 12; ++i)
2701 if (!tcu::allEqual(data[i], expected_value))
2704 m_context.getTestContext().getLog()
2705 << tcu::TestLog::Message
2706 << "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i])
2707 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2712 glDeleteTextures(1, textures);
2714 glDeleteProgram(program);
2719 template <typename T>
2720 std::string GenFS(GLenum internalformat, const T& write_value)
2722 std::ostringstream os;
2723 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2724 << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat)
2725 << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2726 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2727 << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2728 << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat)
2729 << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2730 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2731 << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2732 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
2733 << ") writeonly uniform " << TypePrefix<T>()
2734 << "image2DArray g_image_2darray;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2735 " imageStore(g_image_1d, coord.x, "
2736 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2d, coord, " << TypePrefix<T>()
2737 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>()
2738 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>()
2739 << "vec4" << write_value << ");" NL " imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4"
2740 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2741 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2742 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4"
2743 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4"
2744 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4"
2745 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4"
2746 << write_value << ");" NL " imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4"
2747 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4"
2748 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4"
2749 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2750 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2751 << write_value << ");" NL " discard;" NL "}";
2755 template <typename T>
2756 std::string GenFSMS(GLenum internalformat, const T& write_value)
2758 std::ostringstream os;
2759 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2760 << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat)
2761 << ") writeonly uniform " << TypePrefix<T>()
2762 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2763 " imageStore(g_image_2dms, coord, 0, "
2764 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 1, "
2765 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 2, "
2766 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 3, "
2767 << TypePrefix<T>() << "vec4" << write_value
2768 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4"
2769 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>()
2770 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 2, "
2771 << TypePrefix<T>() << "vec4" << write_value
2772 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4"
2773 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>()
2774 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 1, "
2775 << TypePrefix<T>() << "vec4" << write_value
2776 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4"
2777 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>()
2778 << "vec4" << write_value << ");" NL " discard;" NL "}";
2782 template <typename T>
2783 std::string GenFSMSVal(const T& expected_value)
2785 std::ostringstream os;
2786 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>()
2787 << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>()
2788 << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
2789 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (texelFetch(g_sampler_2dms, coord, 0) != "
2790 << TypePrefix<T>() << "vec4" << expected_value
2791 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 1) != "
2792 << TypePrefix<T>() << "vec4" << expected_value
2793 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 2) != "
2794 << TypePrefix<T>() << "vec4" << expected_value
2795 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 3) != "
2796 << TypePrefix<T>() << "vec4" << expected_value
2797 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
2798 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != "
2799 << TypePrefix<T>() << "vec4" << expected_value
2800 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2801 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != "
2802 << TypePrefix<T>() << "vec4" << expected_value
2803 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2804 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != "
2805 << TypePrefix<T>() << "vec4" << expected_value
2806 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2807 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != "
2808 << TypePrefix<T>() << "vec4" << expected_value
2809 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2810 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != "
2811 << TypePrefix<T>() << "vec4" << expected_value
2812 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2813 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != "
2814 << TypePrefix<T>() << "vec4" << expected_value
2815 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2816 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != "
2817 << TypePrefix<T>() << "vec4" << expected_value
2818 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2819 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != "
2820 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
2824 template <typename T>
2825 std::string GenFSCubeArray(GLenum internalformat, const T& write_value)
2827 std::ostringstream os;
2828 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2830 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2831 " imageStore(g_image_cube_array, ivec3(coord, 0), "
2832 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 1), "
2833 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 2), "
2834 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 3), "
2835 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 4), "
2836 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 5), "
2837 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 6), "
2838 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 7), "
2839 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 8), "
2840 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 9), "
2841 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 10), "
2842 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 11), "
2843 << TypePrefix<T>() << "vec4" << write_value << ");" NL " discard;" NL "}";
2847 //-----------------------------------------------------------------------------
2848 // 1.3.2.1 BasicAllTargetsLoadNonMS
2849 //-----------------------------------------------------------------------------
2850 class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase
2855 virtual long Setup()
2864 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2866 if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2868 if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2870 if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2873 if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2875 if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2877 if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2883 virtual long Cleanup()
2885 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2886 glDeleteVertexArrays(1, &m_vao);
2887 glDeleteBuffers(1, &m_vbo);
2891 template <typename T>
2892 bool Read(GLenum internalformat, const T& value, const T& expected_value)
2894 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2895 " gl_Position = i_position;" NL "}";
2896 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
2899 glGenTextures(7, textures);
2900 glGenBuffers(1, &buffer);
2902 const int kSize = 16;
2903 std::vector<T> data(kSize * kSize * 2, value);
2905 glBindTexture(GL_TEXTURE_1D, textures[0]);
2906 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2907 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2908 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2909 glBindTexture(GL_TEXTURE_1D, 0);
2911 glBindTexture(GL_TEXTURE_2D, textures[1]);
2912 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2913 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2914 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2915 glBindTexture(GL_TEXTURE_2D, 0);
2917 glBindTexture(GL_TEXTURE_3D, textures[2]);
2918 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2919 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2920 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2921 glBindTexture(GL_TEXTURE_3D, 0);
2923 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2924 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2925 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2926 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2927 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2929 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2930 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2931 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2932 glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
2933 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2934 glBindTexture(GL_TEXTURE_BUFFER, 0);
2936 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
2937 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2938 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2939 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2940 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2942 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
2943 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2944 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2945 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2946 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2948 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2949 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2950 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2951 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2952 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2953 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2954 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2956 glClear(GL_COLOR_BUFFER_BIT);
2958 glUseProgram(program);
2959 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2960 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2961 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2962 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2963 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
2964 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
2965 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
2967 glBindVertexArray(m_vao);
2968 glViewport(0, 0, kSize, kSize);
2969 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2973 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2978 std::map<std::string, GLuint> name_index_map;
2980 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
2984 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
2985 << " should be 7." << tcu::TestLog::EndMessage;
2987 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
2990 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
2991 name_index_map.insert(std::make_pair(std::string(name), index));
2994 if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D)))
2996 if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D)))
2998 if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D)))
3000 if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE)))
3002 if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER)))
3004 if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY)))
3006 if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY)))
3010 glDeleteProgram(program);
3011 glDeleteTextures(7, textures);
3012 glDeleteBuffers(1, &buffer);
3017 template <typename T>
3018 bool ReadCube(GLenum internalformat, const T& value, const T& expected_value)
3020 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3021 " gl_Position = i_position;" NL "}";
3022 const GLuint program =
3023 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str());
3025 glGenTextures(2, textures);
3027 const int kSize = 16;
3028 std::vector<T> data(kSize * kSize * 12, value);
3030 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3031 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3032 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3033 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3035 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3037 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3039 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3041 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3043 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3045 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3047 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3048 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3049 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3050 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3052 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3054 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3055 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3057 glClear(GL_COLOR_BUFFER_BIT);
3059 glUseProgram(program);
3060 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3061 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3063 glBindVertexArray(m_vao);
3064 glViewport(0, 0, kSize, kSize);
3065 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3069 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3074 std::map<std::string, GLuint> name_index_map;
3076 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3080 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3081 << " should be 2." << tcu::TestLog::EndMessage;
3083 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3086 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3087 name_index_map.insert(std::make_pair(std::string(name), index));
3090 if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP)))
3092 if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY)))
3096 glDeleteProgram(program);
3097 glDeleteTextures(2, textures);
3102 template <typename T>
3103 std::string GenFS(GLenum internalformat, const T& expected_value)
3105 std::ostringstream os;
3106 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3107 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3108 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3109 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3110 << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3111 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3112 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3113 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3114 << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3115 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3116 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3117 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
3119 << "vec4 v;" NL " v = imageLoad(g_image_1d, coord.x);" NL " if (v != " << TypePrefix<T>() << "vec4"
3121 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_2d, coord);" NL " if (v != "
3122 << TypePrefix<T>() << "vec4" << expected_value
3123 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL
3125 << TypePrefix<T>() << "vec4" << expected_value
3126 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
3128 << TypePrefix<T>() << "vec4" << expected_value
3129 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_2drect, coord);" NL " if (v != "
3130 << TypePrefix<T>() << "vec4" << expected_value
3131 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_buffer, coord.x);" NL " if (v != "
3132 << TypePrefix<T>() << "vec4" << expected_value
3133 << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL
3135 << TypePrefix<T>() << "vec4" << expected_value
3136 << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL
3138 << TypePrefix<T>() << "vec4" << expected_value
3139 << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL
3141 << TypePrefix<T>() << "vec4" << expected_value
3142 << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
3144 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}";
3148 template <typename T>
3149 std::string GenFSCube(GLenum internalformat, const T& expected_value)
3151 std::ostringstream os;
3152 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3153 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3154 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3156 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3157 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
3159 << "vec4 v;" NL " v = imageLoad(g_image_cube, ivec3(coord, 0));" NL " if (v != " << TypePrefix<T>()
3160 << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
3161 " v = imageLoad(g_image_cube, ivec3(coord, 1));" NL " if (v != "
3162 << TypePrefix<T>() << "vec4" << expected_value
3163 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
3165 << TypePrefix<T>() << "vec4" << expected_value
3166 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
3168 << TypePrefix<T>() << "vec4" << expected_value
3169 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
3171 << TypePrefix<T>() << "vec4" << expected_value
3172 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube, ivec3(coord, 5));" NL
3174 << TypePrefix<T>() << "vec4" << expected_value
3175 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL
3177 << TypePrefix<T>() << "vec4" << expected_value
3178 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL
3180 << TypePrefix<T>() << "vec4" << expected_value
3181 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL
3183 << TypePrefix<T>() << "vec4" << expected_value
3184 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL
3186 << TypePrefix<T>() << "vec4" << expected_value
3187 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL
3189 << TypePrefix<T>() << "vec4" << expected_value
3190 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL
3192 << TypePrefix<T>() << "vec4" << expected_value
3193 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL
3195 << TypePrefix<T>() << "vec4" << expected_value
3196 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL
3198 << TypePrefix<T>() << "vec4" << expected_value
3199 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL
3201 << TypePrefix<T>() << "vec4" << expected_value
3202 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL
3204 << TypePrefix<T>() << "vec4" << expected_value
3205 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL
3207 << TypePrefix<T>() << "vec4" << expected_value
3208 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL
3210 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}";
3214 //-----------------------------------------------------------------------------
3215 // 1.3.2.2 BasicAllTargetsLoadMS
3216 //-----------------------------------------------------------------------------
3217 class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase
3222 virtual long Setup()
3231 if (!SupportedSamples(4))
3232 return NOT_SUPPORTED;
3234 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3236 if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
3240 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3243 if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3245 if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
3252 virtual long Cleanup()
3254 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3255 glDeleteVertexArrays(1, &m_vao);
3256 glDeleteBuffers(1, &m_vbo);
3260 template <typename T>
3261 bool ReadMS(GLenum internalformat, const T& value, const T& expected_value)
3263 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3264 " gl_Position = i_position;" NL "}";
3265 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str());
3267 glGenTextures(2, textures);
3269 const int kSize = 16;
3271 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3272 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3273 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3275 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3276 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3277 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3280 glGenFramebuffers(1, &fbo);
3281 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3282 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3283 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3284 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3285 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3286 glDrawBuffers(3, draw_buffers);
3287 ClearBuffer(GL_COLOR, 0, value);
3288 ClearBuffer(GL_COLOR, 1, value);
3289 ClearBuffer(GL_COLOR, 2, value);
3290 glDeleteFramebuffers(1, &fbo);
3292 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3293 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3295 glUseProgram(program);
3296 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3297 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3299 glClear(GL_COLOR_BUFFER_BIT);
3300 glBindVertexArray(m_vao);
3301 glViewport(0, 0, kSize, kSize);
3302 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3306 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3311 std::map<std::string, GLuint> name_index_map;
3313 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3317 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3318 << " should be 2." << tcu::TestLog::EndMessage;
3320 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3323 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3324 name_index_map.insert(std::make_pair(std::string(name), index));
3327 if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE)))
3329 if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1,
3330 ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)))
3333 glDeleteTextures(2, textures);
3335 glDeleteProgram(program);
3340 template <typename T>
3341 std::string GenFSMS(GLenum internalformat, const T& expected_value)
3343 std::ostringstream os;
3344 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3345 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3346 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3348 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3349 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (imageLoad(g_image_2dms, coord, 0) != "
3350 << TypePrefix<T>() << "vec4" << expected_value
3351 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 1) != "
3352 << TypePrefix<T>() << "vec4" << expected_value
3353 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 2) != "
3354 << TypePrefix<T>() << "vec4" << expected_value
3355 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 3) != "
3356 << TypePrefix<T>() << "vec4" << expected_value
3357 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != "
3358 << TypePrefix<T>() << "vec4" << expected_value
3359 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != "
3360 << TypePrefix<T>() << "vec4" << expected_value
3361 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != "
3362 << TypePrefix<T>() << "vec4" << expected_value
3363 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != "
3364 << TypePrefix<T>() << "vec4" << expected_value
3365 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != "
3366 << TypePrefix<T>() << "vec4" << expected_value
3367 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != "
3368 << TypePrefix<T>() << "vec4" << expected_value
3369 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != "
3370 << TypePrefix<T>() << "vec4" << expected_value
3371 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != "
3372 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
3376 //-----------------------------------------------------------------------------
3377 // 1.3.3 BasicAllTargetsAtomic
3378 //-----------------------------------------------------------------------------
3379 class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase
3384 virtual long Setup()
3393 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3395 if (!Atomic<GLint>(GL_R32I))
3397 if (!Atomic<GLuint>(GL_R32UI))
3400 if (!AtomicCube<GLint>(GL_R32I))
3402 if (!AtomicCube<GLuint>(GL_R32UI))
3406 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3407 if (SupportedSamples(4) && isamples >= 4)
3409 if (!AtomicMS<GLint>(GL_R32I))
3411 if (!AtomicMS<GLuint>(GL_R32UI))
3418 virtual long Cleanup()
3420 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3421 glDeleteVertexArrays(1, &m_vao);
3422 glDeleteBuffers(1, &m_vbo);
3426 template <typename T>
3427 bool Atomic(GLenum internalformat)
3429 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3430 " gl_Position = i_position;" NL "}";
3431 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str());
3434 glGenTextures(7, textures);
3435 glGenBuffers(1, &buffer);
3437 const int kSize = 16;
3438 std::vector<T> data(kSize * kSize * 2);
3440 glBindTexture(GL_TEXTURE_1D, textures[0]);
3441 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3442 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3443 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3444 glBindTexture(GL_TEXTURE_1D, 0);
3446 glBindTexture(GL_TEXTURE_2D, textures[1]);
3447 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3448 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3449 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3450 glBindTexture(GL_TEXTURE_2D, 0);
3452 glBindTexture(GL_TEXTURE_3D, textures[2]);
3453 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3454 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3455 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3456 glBindTexture(GL_TEXTURE_3D, 0);
3458 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
3459 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3460 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3461 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3462 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
3464 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
3465 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
3466 glBindBuffer(GL_TEXTURE_BUFFER, 0);
3467 glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
3468 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
3469 glBindTexture(GL_TEXTURE_BUFFER, 0);
3471 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
3472 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3473 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3474 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3475 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
3477 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
3478 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3479 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3480 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3481 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3483 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3484 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3485 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3486 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3487 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3488 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3489 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3491 glClear(GL_COLOR_BUFFER_BIT);
3493 glUseProgram(program);
3494 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3495 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3496 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3497 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3498 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3499 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3500 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3502 glBindVertexArray(m_vao);
3503 glViewport(0, 0, kSize, 1);
3504 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3508 if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1)))
3514 glDeleteProgram(program);
3515 glDeleteTextures(7, textures);
3516 glDeleteBuffers(1, &buffer);
3521 template <typename T>
3522 bool AtomicCube(GLenum internalformat)
3524 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3525 " gl_Position = i_position;" NL "}";
3526 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str());
3528 glGenTextures(2, textures);
3530 const int kSize = 16;
3531 std::vector<T> data(kSize * kSize * 12);
3533 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3534 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3535 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3536 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3538 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3540 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3542 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3544 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3546 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3548 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3550 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3551 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3552 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3553 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3555 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3557 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3558 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3560 glClear(GL_COLOR_BUFFER_BIT);
3562 glUseProgram(program);
3563 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3564 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3566 glBindVertexArray(m_vao);
3567 glViewport(0, 0, kSize, kSize);
3568 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3572 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3578 glDeleteProgram(program);
3579 glDeleteTextures(2, textures);
3584 template <typename T>
3585 bool AtomicMS(GLenum internalformat)
3587 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3588 " gl_Position = i_position;" NL "}";
3589 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str());
3591 glGenTextures(2, textures);
3593 const int kSize = 16;
3595 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3596 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3597 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3599 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3600 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3601 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3604 glGenFramebuffers(1, &fbo);
3605 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3606 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3607 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3608 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3609 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3610 glDrawBuffers(3, draw_buffers);
3611 if (internalformat == GL_R32I)
3613 const GLint value[4] = { 0, 0, 0, 0 };
3614 glClearBufferiv(GL_COLOR, 0, value);
3615 glClearBufferiv(GL_COLOR, 1, value);
3616 glClearBufferiv(GL_COLOR, 2, value);
3620 const GLuint value[4] = { 0, 0, 0, 0 };
3621 glClearBufferuiv(GL_COLOR, 0, value);
3622 glClearBufferuiv(GL_COLOR, 1, value);
3623 glClearBufferuiv(GL_COLOR, 2, value);
3625 glDeleteFramebuffers(1, &fbo);
3627 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3628 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3630 glUseProgram(program);
3631 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3632 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3634 glClear(GL_COLOR_BUFFER_BIT);
3635 glBindVertexArray(m_vao);
3636 glViewport(0, 0, kSize, kSize);
3637 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3641 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3646 glDeleteTextures(2, textures);
3648 glDeleteProgram(program);
3653 template <typename T>
3654 std::string GenFS(GLenum internalformat)
3656 std::ostringstream os;
3657 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3658 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3659 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3660 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3661 << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3662 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3663 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3664 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3665 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3666 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3667 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3668 " ivec2 coord = ivec2(gl_FragCoord.xy);"
3670 NL " if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3671 " if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3672 " if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3673 " if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3674 " if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3675 " if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3676 " if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3677 " if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3678 " if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3680 NL " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3681 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3682 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3683 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3684 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3685 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3686 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3687 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3688 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3690 NL " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3691 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3692 " if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3693 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3694 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3695 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3696 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3697 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3699 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3701 NL " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3702 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3703 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3704 " if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3705 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3706 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3707 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3708 " if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3709 " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3711 NL " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3712 " if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3713 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3714 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3715 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3716 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3717 " if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3718 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3719 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3722 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3723 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3724 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3725 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3726 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3727 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3728 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3729 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = "
3730 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), "
3731 "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3733 NL " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3734 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3735 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3736 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3737 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3738 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3739 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3740 "1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, "
3741 "0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) "
3742 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3746 template <typename T>
3747 std::string GenFSCube(GLenum internalformat)
3749 std::ostringstream os;
3750 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3751 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3752 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3754 << "imageCube g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3755 " ivec2 coord = ivec2(gl_FragCoord.xy);"
3757 NL " if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3758 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3759 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3760 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3761 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3762 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3763 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3764 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3766 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3768 NL " if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3769 "1.0);" NL " if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, "
3770 "0.0, 1.0);" NL " if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color "
3771 "= vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicAnd(g_image_cube_array, "
3772 "ivec3(coord, 0), 0) != 4) o_color = "
3773 "vec4(1.0, 0.0, 0.0, 1.0);" NL
3774 " if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3775 " if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, "
3776 "1.0);" NL " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, "
3777 "0.0, 0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != "
3778 "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3779 " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, "
3784 template <typename T>
3785 std::string GenFSMS(GLenum internalformat)
3787 std::ostringstream os;
3788 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3789 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3790 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3792 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3793 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3794 " if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3795 " if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3796 " if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3797 " if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3798 " if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3799 " if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3800 " if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3801 " if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3802 " if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL
3803 " if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3804 "1.0);" NL " if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, "
3805 "0.0, 0.0, 1.0);" NL " if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) "
3806 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3807 " if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, "
3808 "1.0);" NL " if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, "
3809 "0.0, 0.0, 1.0);" NL " if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) "
3810 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3811 " if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, "
3812 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = "
3813 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2dms_array, "
3814 "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, "
3815 "0.0, 1.0);" NL "}";
3819 //-----------------------------------------------------------------------------
3821 //-----------------------------------------------------------------------------
3822 class LoadStoreMachine : public ShaderImageLoadStoreBase
3827 virtual long Setup()
3829 glGenVertexArrays(1, &m_vao);
3833 virtual long Cleanup()
3835 glDisable(GL_RASTERIZER_DISCARD);
3836 glDeleteVertexArrays(1, &m_vao);
3840 template <typename T>
3841 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
3843 const GLenum targets[] = { GL_TEXTURE_1D, GL_TEXTURE_2D,
3844 GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE,
3845 GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY,
3846 GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY };
3847 const int kTargets = sizeof(targets) / sizeof(targets[0]);
3848 GLuint program_store = 0;
3849 GLuint program_load = 0;
3853 BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL);
3855 BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL);
3857 else if (m_stage == 1)
3859 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3860 const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
3861 program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(),
3862 glsl_tes, NULL, NULL);
3863 program_load = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(),
3864 glsl_tes, NULL, NULL);
3866 else if (m_stage == 2)
3868 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3870 BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL);
3872 BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL);
3874 else if (m_stage == 3)
3876 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3878 BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL);
3880 BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL);
3882 else if (m_stage == 4)
3885 std::string source = GenStoreShader(m_stage, internalformat, write_value);
3886 const char* const src = source.c_str();
3887 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
3888 glShaderSource(sh, 1, &src, NULL);
3889 glCompileShader(sh);
3890 program_store = glCreateProgram();
3891 glAttachShader(program_store, sh);
3892 glLinkProgram(program_store);
3896 std::string source = GenLoadShader(m_stage, internalformat, expected_value);
3897 const char* const src = source.c_str();
3898 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
3899 glShaderSource(sh, 1, &src, NULL);
3900 glCompileShader(sh);
3901 program_load = glCreateProgram();
3902 glAttachShader(program_load, sh);
3903 glLinkProgram(program_load);
3907 GLuint textures[kTargets], texture_result;
3908 glGenTextures(kTargets, textures);
3909 glGenTextures(1, &texture_result);
3911 glBindTexture(GL_TEXTURE_2D, texture_result);
3912 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3913 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3914 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3916 for (int i = 0; i < kTargets; ++i)
3918 glBindTexture(targets[i], textures[i]);
3919 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3920 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3922 if (targets[i] == GL_TEXTURE_1D)
3924 glTexStorage1D(targets[i], 1, internalformat, 1);
3926 else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
3928 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3930 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3932 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
3934 else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3936 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3938 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
3940 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12);
3942 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
3944 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
3947 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3948 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3949 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3950 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3951 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3952 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3953 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3954 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3956 glUseProgram(program_store);
3957 glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0);
3958 glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1);
3959 glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2);
3960 glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3);
3961 glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4);
3962 glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5);
3963 glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6);
3964 glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7);
3966 glBindVertexArray(m_vao);
3967 if (m_stage == 1 || m_stage == 2)
3969 glPatchParameteri(GL_PATCH_VERTICES, 1);
3970 glDrawArrays(GL_PATCHES, 0, 1);
3971 glPatchParameteri(GL_PATCH_VERTICES, 3);
3973 else if (m_stage == 4)
3975 glDispatchCompute(1, 1, 1);
3979 glDrawArrays(GL_POINTS, 0, 1);
3983 for (int i = 0; i < kTargets; ++i)
3985 glBindTexture(targets[i], textures[i]);
3986 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
3988 if (targets[i] == GL_TEXTURE_CUBE_MAP)
3990 for (int face = 0; face < 6; ++face)
3993 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
3994 if (!Equal(data, expected_value, internalformat))
3997 m_context.getTestContext().getLog()
3998 << tcu::TestLog::Message << "Value is: " << ToString(data)
3999 << ". Value should be: " << ToString(expected_value)
4000 << ". Format is: " << FormatEnumToString(internalformat)
4001 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4002 << tcu::TestLog::EndMessage;
4009 memset(&data[0], 0, sizeof(data));
4010 glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]);
4013 if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4015 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
4017 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4020 for (int j = 0; j < count; ++j)
4022 if (!Equal(data[j], expected_value, internalformat))
4025 m_context.getTestContext().getLog()
4026 << tcu::TestLog::Message << "Value is: " << ToString(data[j])
4027 << ". Value should be: " << ToString(expected_value)
4028 << ". Format is: " << FormatEnumToString(internalformat)
4029 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4030 << tcu::TestLog::EndMessage;
4035 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4036 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4037 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4038 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4039 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4040 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4041 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4042 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4044 glUseProgram(program_load);
4045 glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0);
4046 glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1);
4047 glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2);
4048 glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3);
4049 glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4);
4050 glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5);
4051 glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6);
4052 glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7);
4054 if (m_stage == 1 || m_stage == 2)
4056 glPatchParameteri(GL_PATCH_VERTICES, 1);
4057 glDrawArrays(GL_PATCHES, 0, 1);
4058 glPatchParameteri(GL_PATCH_VERTICES, 3);
4060 else if (m_stage == 4)
4062 glDispatchCompute(1, 1, 1);
4066 glDrawArrays(GL_POINTS, 0, 1);
4070 glBindTexture(GL_TEXTURE_2D, texture_result);
4071 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4072 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4073 if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4076 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4077 << ". Format is: " << FormatEnumToString(internalformat)
4078 << ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage;
4082 glDeleteProgram(program_store);
4083 glDeleteProgram(program_load);
4084 glDeleteTextures(kTargets, textures);
4085 glDeleteTextures(1, &texture_result);
4089 template <typename T>
4090 std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value)
4092 std::ostringstream os;
4093 os << "#version 420 core";
4096 os << NL "#extension GL_ARB_compute_shader : require";
4098 os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4099 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4100 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
4101 << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
4102 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4103 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4104 << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
4105 << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4106 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4107 << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat)
4108 << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform "
4109 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value
4110 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4113 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4115 else if (stage == 1)
4117 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4118 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4119 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4120 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4122 else if (stage == 2)
4124 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4125 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4127 else if (stage == 3)
4129 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4130 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4132 else if (stage == 4)
4134 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4135 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4137 os << NL " imageStore(g_image_1d, coord.x, g_value);" NL " imageStore(g_image_2d, coord, g_value);" NL
4138 " imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
4139 " imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
4140 " imageStore(g_image_2drect, coord, g_value);" NL " for (int i = 0; i < 6; ++i) {" NL
4141 " imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL " }" NL
4142 " imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL
4143 " imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL
4144 " imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
4145 " imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL
4146 " for (int i = 0; i < 6; ++i) {" NL
4147 " imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL " }" NL
4148 " for (int i = 0; i < 6; ++i) {" NL
4149 " imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL " }" NL "}";
4153 template <typename T>
4154 std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value)
4156 std::ostringstream os;
4157 os << "#version 420 core";
4160 os << NL "#extension GL_ARB_compute_shader : require";
4162 os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4163 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4164 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4165 << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4166 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4167 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4168 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
4169 << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout("
4170 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4171 << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4173 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value
4174 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4177 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4179 else if (stage == 1)
4181 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4182 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4183 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4184 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4186 else if (stage == 2)
4188 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4189 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4191 else if (stage == 3)
4193 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4194 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4196 else if (stage == 4)
4198 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4199 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4201 os << NL " vec4 r = vec4(0, 1, 0, 1);" NL " " << TypePrefix<T>()
4202 << "vec4 v;" NL " v = imageLoad(g_image_2d, coord);" NL
4203 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4204 " v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
4205 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_2drect, coord);" NL
4206 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4207 " v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
4208 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_1darray, coord);" NL
4209 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4210 " v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
4211 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4212 " v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL
4213 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " imageStore(g_image_result, coord, r);" NL "}";
4218 long RunStage(int stage)
4220 if (!SupportedInStage(stage, 8))
4221 return NOT_SUPPORTED;
4223 glEnable(GL_RASTERIZER_DISCARD);
4226 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4228 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4230 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4233 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4235 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4237 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4240 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4242 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4244 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4247 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
4250 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4252 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4254 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4257 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4259 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4261 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4264 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4266 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4268 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4270 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4273 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4275 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4277 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4280 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4282 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4284 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4287 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
4289 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
4291 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4293 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4296 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
4298 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4300 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4305 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4307 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4309 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4312 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4314 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4316 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4322 //-----------------------------------------------------------------------------
4324 //-----------------------------------------------------------------------------
4325 class AtomicMachine : public ShaderImageLoadStoreBase
4329 virtual long Setup()
4331 glEnable(GL_RASTERIZER_DISCARD);
4332 glGenVertexArrays(1, &m_vao);
4336 virtual long Cleanup()
4338 glDisable(GL_RASTERIZER_DISCARD);
4339 glDeleteVertexArrays(1, &m_vao);
4343 template <typename T>
4344 bool Atomic(int stage, GLenum internalformat)
4349 program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL);
4351 else if (stage == 1)
4353 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4354 const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
4355 program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL);
4357 else if (stage == 2)
4359 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4360 program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL);
4362 else if (stage == 3)
4364 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4365 program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL);
4367 else if (stage == 4)
4369 std::string source = GenShader<T>(stage, internalformat);
4370 const char* const src = source.c_str();
4371 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
4372 glShaderSource(sh, 1, &src, NULL);
4373 glCompileShader(sh);
4374 program = glCreateProgram();
4375 glAttachShader(program, sh);
4376 glLinkProgram(program);
4379 GLuint texture_result;
4380 glGenTextures(1, &texture_result);
4381 glBindTexture(GL_TEXTURE_2D, texture_result);
4382 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4383 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4384 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
4386 const GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP,
4387 GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY };
4388 const int kTargets = sizeof(targets) / sizeof(targets[0]);
4390 GLuint textures[kTargets];
4392 glGenTextures(kTargets, textures);
4393 glGenBuffers(1, &buffer);
4395 for (int i = 0; i < kTargets; ++i)
4397 glBindTexture(targets[i], textures[i]);
4398 if (targets[i] != GL_TEXTURE_BUFFER)
4400 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4401 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4403 if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
4405 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4407 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4409 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
4411 else if (targets[i] == GL_TEXTURE_CUBE_MAP)
4413 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4415 else if (targets[i] == GL_TEXTURE_BUFFER)
4417 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
4418 glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
4419 glBindBuffer(GL_TEXTURE_BUFFER, 0);
4420 glTexBuffer(targets[i], internalformat, buffer);
4422 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4424 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
4427 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4428 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4429 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4430 glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4431 glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4432 glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4433 glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4434 glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4436 glUseProgram(program);
4437 glUniform1i(glGetUniformLocation(program, "g_image_result"), 0);
4438 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
4439 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
4440 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
4441 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
4442 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
4443 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
4444 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
4446 glBindVertexArray(m_vao);
4447 if (stage == 1 || stage == 2)
4449 glPatchParameteri(GL_PATCH_VERTICES, 1);
4450 glDrawArrays(GL_PATCHES, 0, 1);
4451 glPatchParameteri(GL_PATCH_VERTICES, 3);
4453 else if (stage == 4)
4455 glDispatchCompute(1, 1, 1);
4459 glDrawArrays(GL_POINTS, 0, 1);
4465 glBindTexture(GL_TEXTURE_2D, texture_result);
4466 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4467 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4468 if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4471 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4472 << ". Format is: " << FormatEnumToString(internalformat)
4473 << ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage;
4477 glDeleteProgram(program);
4478 glDeleteTextures(7, textures);
4479 glDeleteTextures(1, &texture_result);
4480 glDeleteBuffers(1, &buffer);
4484 template <typename T>
4485 std::string GenShader(int stage, GLenum internalformat)
4487 std::ostringstream os;
4488 os << "#version 420 core";
4491 os << NL "#extension GL_ARB_compute_shader : require";
4493 os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4494 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4495 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4496 << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4497 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4498 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4499 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
4500 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4501 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4502 << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4503 "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);";
4506 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
4508 else if (stage == 1)
4510 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4511 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4512 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4513 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4515 else if (stage == 2)
4517 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4518 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4520 else if (stage == 3)
4522 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4523 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);";
4525 else if (stage == 4)
4527 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4528 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
4531 " vec4 o_color = vec4(0, 1, 0, 1);" NL " imageAtomicExchange(g_image_2d, coord, 0);" NL
4532 " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4533 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4534 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4535 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4536 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4537 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4538 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4539 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4540 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4542 NL " imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL
4543 " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4544 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4545 " if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4546 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4547 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4548 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4549 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4550 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4551 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4553 NL " imageAtomicExchange(g_image_2drect, coord, 0);" NL
4554 " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4555 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4556 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4557 " if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4558 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4559 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4560 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4561 " if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
4562 "1.0);" NL " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4564 NL " imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL " if (imageAtomicAdd(g_image_cube, "
4565 "ivec3(coord, 0), g_value[2]) != 0) "
4566 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4567 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4568 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4569 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4570 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4571 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4572 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4573 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, "
4575 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4577 NL " imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL
4578 " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4579 " if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4580 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4581 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4582 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4583 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4584 " if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4586 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4587 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4589 NL " imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL
4590 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4591 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4592 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, "
4594 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4595 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4596 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4597 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4598 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, "
4599 "0.0, 0.0, 1.0);" NL
4600 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4602 NL " imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL
4603 " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4604 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4605 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4606 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4607 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4608 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, "
4609 "1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, "
4610 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) "
4611 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4612 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4614 NL " imageStore(g_image_result, coord, o_color);" NL "}";
4619 long RunStage(int stage)
4621 if (!SupportedInStage(stage, 8))
4622 return NOT_SUPPORTED;
4623 if (!Atomic<GLint>(stage, GL_R32I))
4625 if (!Atomic<GLuint>(stage, GL_R32UI))
4630 //-----------------------------------------------------------------------------
4631 // 1.3.4 BasicAllTargetsLoadStoreVS
4632 //-----------------------------------------------------------------------------
4633 class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
4640 //-----------------------------------------------------------------------------
4641 // 1.3.5 BasicAllTargetsLoadStoreTCS
4642 //-----------------------------------------------------------------------------
4643 class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine
4650 //-----------------------------------------------------------------------------
4651 // 1.3.6 BasicAllTargetsLoadStoreTES
4652 //-----------------------------------------------------------------------------
4653 class BasicAllTargetsLoadStoreTES : public LoadStoreMachine
4660 //-----------------------------------------------------------------------------
4661 // 1.3.7 BasicAllTargetsLoadStoreGS
4662 //-----------------------------------------------------------------------------
4663 class BasicAllTargetsLoadStoreGS : public LoadStoreMachine
4670 //-----------------------------------------------------------------------------
4671 // 1.3.8 BasicAllTargetsLoadStoreCS
4672 //-----------------------------------------------------------------------------
4673 class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
4677 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4679 m_context.getTestContext().getLog()
4680 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4681 << tcu::TestLog::EndMessage;
4688 //-----------------------------------------------------------------------------
4689 // 1.3.9 BasicAllTargetsAtomicVS
4690 //-----------------------------------------------------------------------------
4691 class BasicAllTargetsAtomicVS : public AtomicMachine
4698 //-----------------------------------------------------------------------------
4699 // 1.3.10 BasicAllTargetsAtomicTCS
4700 //-----------------------------------------------------------------------------
4701 class BasicAllTargetsAtomicTCS : public AtomicMachine
4708 //-----------------------------------------------------------------------------
4709 // 1.3.11 BasicAllTargetsAtomicTES
4710 //-----------------------------------------------------------------------------
4711 class BasicAllTargetsAtomicTES : public AtomicMachine
4718 //-----------------------------------------------------------------------------
4719 // 1.3.12 BasicAllTargetsAtomicGS
4720 //-----------------------------------------------------------------------------
4721 class BasicAllTargetsAtomicGS : public AtomicMachine
4728 //-----------------------------------------------------------------------------
4729 // 1.3.13 BasicAllTargetsAtomicCS
4730 //-----------------------------------------------------------------------------
4731 class BasicAllTargetsAtomicCS : public AtomicMachine
4735 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4737 m_context.getTestContext().getLog()
4738 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4739 << tcu::TestLog::EndMessage;
4746 //-----------------------------------------------------------------------------
4747 // 1.4.1 BasicGLSLMisc
4748 //-----------------------------------------------------------------------------
4749 class BasicGLSLMisc : public ShaderImageLoadStoreBase
4753 GLuint m_vao, m_vbo;
4755 virtual long Setup()
4765 const int kSize = 32;
4766 std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f));
4768 glGenTextures(1, &m_texture);
4769 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4770 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4771 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]);
4772 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
4774 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4775 " gl_Position = i_position;" NL "}";
4776 const char* src_fs =
4777 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4778 "layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL
4779 "layout(rgba32f) volatile uniform image2D g_image_layer1;" NL
4780 "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
4781 " imageStore(g_image_layer0, coord, vec4(1.0));" NL " memoryBarrier();" NL
4782 " imageStore(g_image_layer0, coord, vec4(2.0));" NL " memoryBarrier();" NL
4783 " imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL " memoryBarrier();" NL
4784 " o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}";
4785 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs);
4787 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4789 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4790 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F);
4792 glClear(GL_COLOR_BUFFER_BIT);
4793 glViewport(0, 0, kSize, kSize);
4795 glUseProgram(m_program);
4796 glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0);
4797 glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1);
4799 glBindVertexArray(m_vao);
4800 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4802 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
4809 virtual long Cleanup()
4811 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4812 glDeleteTextures(1, &m_texture);
4813 glDeleteVertexArrays(1, &m_vao);
4814 glDeleteBuffers(1, &m_vbo);
4816 glDeleteProgram(m_program);
4820 //-----------------------------------------------------------------------------
4821 // 1.4.2 BasicGLSLEarlyFragTests
4822 //-----------------------------------------------------------------------------
4823 class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
4825 GLuint m_texture[2];
4826 GLuint m_program[2];
4827 GLuint m_vao, m_vbo;
4829 virtual long Setup()
4831 m_texture[0] = m_texture[1] = 0;
4832 m_program[0] = m_program[1] = 0;
4839 int ds = m_context.getRenderContext().getRenderTarget().getDepthBits();
4841 const int kSize = 32;
4842 std::vector<vec4> data(kSize * kSize);
4844 glGenTextures(2, m_texture);
4845 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4846 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4847 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4848 glBindTexture(GL_TEXTURE_2D, 0);
4850 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4851 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4852 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4853 glBindTexture(GL_TEXTURE_2D, 0);
4855 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4856 " gl_Position = i_position;" NL "}";
4857 const char* glsl_early_frag_tests_fs =
4858 "#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
4859 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4860 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL
4861 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4862 const char* glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4863 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4864 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL
4865 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4866 m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs);
4867 m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
4869 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4871 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4872 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4874 glViewport(0, 0, kSize, kSize);
4875 glBindVertexArray(m_vao);
4877 glEnable(GL_DEPTH_TEST);
4878 glClearColor(0.0, 1.0f, 0.0, 1.0f);
4879 glClearDepthf(0.0f);
4881 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4882 glUseProgram(m_program[0]);
4883 glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0);
4885 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4887 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4888 glUseProgram(m_program[1]);
4889 glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1);
4890 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4892 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4893 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4894 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4895 for (int i = 0; i < kSize * kSize; ++i)
4897 if (IsEqual(data[i], vec4(1.0f)) && ds != 0)
4901 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4902 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4903 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4904 for (int i = 0; i < kSize * kSize; ++i)
4906 if (!IsEqual(data[i], vec4(1.0f)) && ds != 0)
4913 virtual long Cleanup()
4915 glDisable(GL_DEPTH_TEST);
4916 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4917 glClearDepthf(1.0f);
4918 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4919 glDeleteTextures(2, m_texture);
4920 glDeleteVertexArrays(1, &m_vao);
4921 glDeleteBuffers(1, &m_vbo);
4923 glDeleteProgram(m_program[0]);
4924 glDeleteProgram(m_program[1]);
4928 //-----------------------------------------------------------------------------
4929 // 1.4.3 BasicGLSLConst
4930 //-----------------------------------------------------------------------------
4931 class BasicGLSLConst : public ShaderImageLoadStoreBase
4934 GLuint m_vao, m_vbo;
4936 virtual long Setup()
4945 bool isAtLeast44Context =
4946 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4));
4948 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4949 " gl_Position = i_position;" NL "}";
4950 std::ostringstream src_fs;
4951 src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core";
4952 src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL
4953 "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL
4954 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL
4955 "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL
4956 "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL
4957 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
4958 " if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);";
4959 if (isAtLeast44Context)
4960 src_fs << NL " if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = "
4961 "vec4(0.2, 0.0, 0.0, 0.2);";
4963 src_fs << NL " if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) "
4964 "o_color = vec4(0.2, 0.0, 0.0, 0.2);";
4966 " if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
4967 " if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL
4968 " if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, "
4969 "0.5);" NL " if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, "
4970 "0.0, 0.0, 0.6);" NL
4971 " if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL
4972 " if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL
4973 " if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}";
4975 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str());
4976 glUseProgram(m_program);
4979 glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
4980 glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
4982 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
4983 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
4985 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
4986 glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i);
4988 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
4989 glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
4991 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i);
4992 glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i);
4994 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i);
4995 glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i);
4997 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i);
4998 glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i);
5000 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
5001 glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
5003 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
5004 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
5006 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5008 glClear(GL_COLOR_BUFFER_BIT);
5009 glBindVertexArray(m_vao);
5010 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5012 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5019 virtual long Cleanup()
5021 glDeleteVertexArrays(1, &m_vao);
5022 glDeleteBuffers(1, &m_vbo);
5024 glDeleteProgram(m_program);
5028 //-----------------------------------------------------------------------------
5029 // 2.1.1 AdvancedSyncImageAccess
5030 //-----------------------------------------------------------------------------
5031 class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
5034 GLuint m_buffer_tex;
5035 GLuint m_store_program;
5036 GLuint m_draw_program;
5037 GLuint m_attribless_vao;
5039 virtual long Setup()
5043 m_store_program = 0;
5045 m_attribless_vao = 0;
5051 if (!SupportedInVS(1))
5052 return NOT_SUPPORTED;
5053 const char* const glsl_store_vs =
5054 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5055 " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5056 " imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}";
5057 const char* const glsl_draw_vs =
5058 "#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL
5059 "uniform samplerBuffer g_sampler;" NL "void main() {" NL " vec4 pi = imageLoad(g_image, gl_VertexID);" NL
5060 " vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL
5061 " if (pi != ps) vs_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " else vs_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5062 " gl_Position = pi;" NL "}";
5063 const char* const glsl_draw_fs =
5064 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5065 " o_color = vs_color;" NL "}";
5066 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5067 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5069 glGenVertexArrays(1, &m_attribless_vao);
5070 glBindVertexArray(m_attribless_vao);
5072 glGenBuffers(1, &m_buffer);
5073 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5074 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5075 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5077 glGenTextures(1, &m_buffer_tex);
5078 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5079 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer);
5081 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
5083 glEnable(GL_RASTERIZER_DISCARD);
5084 glUseProgram(m_store_program);
5085 glDrawArrays(GL_POINTS, 0, 4);
5087 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
5089 glDisable(GL_RASTERIZER_DISCARD);
5090 glClear(GL_COLOR_BUFFER_BIT);
5091 glUseProgram(m_draw_program);
5092 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5094 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5101 virtual long Cleanup()
5104 glDeleteBuffers(1, &m_buffer);
5105 glDeleteTextures(1, &m_buffer_tex);
5106 glDeleteProgram(m_store_program);
5107 glDeleteProgram(m_draw_program);
5108 glDeleteVertexArrays(1, &m_attribless_vao);
5112 //-----------------------------------------------------------------------------
5113 // 2.1.2 AdvancedSyncVertexArray
5114 //-----------------------------------------------------------------------------
5115 class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
5117 GLuint m_position_buffer;
5118 GLuint m_color_buffer;
5119 GLuint m_element_buffer;
5120 GLuint m_position_buffer_tex;
5121 GLuint m_color_buffer_tex;
5122 GLuint m_element_buffer_tex;
5123 GLuint m_store_program;
5124 GLuint m_draw_program;
5125 GLuint m_attribless_vao;
5128 virtual long Setup()
5130 m_position_buffer = 0;
5132 m_element_buffer = 0;
5133 m_position_buffer_tex = 0;
5134 m_color_buffer_tex = 0;
5135 m_element_buffer_tex = 0;
5136 m_store_program = 0;
5138 m_attribless_vao = 0;
5145 if (!SupportedInVS(3))
5146 return NOT_SUPPORTED;
5147 const char* const glsl_store_vs =
5148 "#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL
5149 "layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL
5150 "layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL
5151 "void main() {" NL " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5152 " imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL
5153 " imageStore(g_color_buffer, gl_VertexID, g_color);" NL
5154 " imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}";
5155 const char* const glsl_draw_vs =
5156 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5157 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL
5158 " gl_Position = i_position;" NL " vs_color = i_color;" NL "}";
5159 const char* const glsl_draw_fs =
5160 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5161 " o_color = vs_color;" NL "}";
5162 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5163 glUseProgram(m_store_program);
5164 glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0);
5165 glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1);
5166 glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2);
5169 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5171 glGenBuffers(1, &m_position_buffer);
5172 glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer);
5173 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5174 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5176 glGenBuffers(1, &m_color_buffer);
5177 glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer);
5178 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW);
5179 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5181 glGenBuffers(1, &m_element_buffer);
5182 glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer);
5183 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW);
5184 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5186 glGenTextures(1, &m_position_buffer_tex);
5187 glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex);
5188 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer);
5189 glBindTexture(GL_TEXTURE_BUFFER, 0);
5191 glGenTextures(1, &m_color_buffer_tex);
5192 glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex);
5193 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer);
5194 glBindTexture(GL_TEXTURE_BUFFER, 0);
5196 glGenTextures(1, &m_element_buffer_tex);
5197 glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex);
5198 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer);
5199 glBindTexture(GL_TEXTURE_BUFFER, 0);
5201 glGenVertexArrays(1, &m_attribless_vao);
5203 glGenVertexArrays(1, &m_draw_vao);
5204 glBindVertexArray(m_draw_vao);
5205 glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
5206 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5207 glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
5208 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
5209 glBindBuffer(GL_ARRAY_BUFFER, 0);
5210 glEnableVertexAttribArray(0);
5211 glEnableVertexAttribArray(1);
5212 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
5213 glBindVertexArray(0);
5215 glEnable(GL_RASTERIZER_DISCARD);
5216 glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F);
5217 glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5218 glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
5219 glUseProgram(m_store_program);
5220 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5221 glBindVertexArray(m_attribless_vao);
5222 glDrawArrays(GL_POINTS, 0, 4);
5224 glDisable(GL_RASTERIZER_DISCARD);
5225 glClear(GL_COLOR_BUFFER_BIT);
5226 glUseProgram(m_draw_program);
5227 glBindVertexArray(m_draw_vao);
5228 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5229 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5231 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5236 glEnable(GL_RASTERIZER_DISCARD);
5237 glUseProgram(m_store_program);
5238 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
5239 glBindVertexArray(m_attribless_vao);
5240 glDrawArrays(GL_POINTS, 0, 4);
5242 glDisable(GL_RASTERIZER_DISCARD);
5243 glClear(GL_COLOR_BUFFER_BIT);
5244 glUseProgram(m_draw_program);
5245 glBindVertexArray(m_draw_vao);
5246 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5247 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5249 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1)))
5256 virtual long Cleanup()
5258 glDisable(GL_RASTERIZER_DISCARD);
5260 glDeleteBuffers(1, &m_position_buffer);
5261 glDeleteBuffers(1, &m_color_buffer);
5262 glDeleteBuffers(1, &m_element_buffer);
5263 glDeleteTextures(1, &m_position_buffer_tex);
5264 glDeleteTextures(1, &m_color_buffer_tex);
5265 glDeleteTextures(1, &m_element_buffer_tex);
5266 glDeleteProgram(m_store_program);
5267 glDeleteProgram(m_draw_program);
5268 glDeleteVertexArrays(1, &m_attribless_vao);
5269 glDeleteVertexArrays(1, &m_draw_vao);
5274 //-----------------------------------------------------------------------------
5275 // 2.1.4 AdvancedSyncDrawIndirect
5276 //-----------------------------------------------------------------------------
5277 class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase
5279 GLuint m_draw_command_buffer;
5280 GLuint m_draw_command_buffer_tex;
5281 GLuint m_store_program;
5282 GLuint m_draw_program;
5283 GLuint m_attribless_vao;
5287 virtual long Setup()
5289 m_draw_command_buffer = 0;
5290 m_draw_command_buffer_tex = 0;
5291 m_store_program = 0;
5293 m_attribless_vao = 0;
5301 if (!SupportedInVS(1))
5302 return NOT_SUPPORTED;
5303 const char* const glsl_store_vs =
5304 "#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL
5305 " imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}";
5306 const char* const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5307 "void main() {" NL " gl_Position = i_position;" NL "}";
5308 const char* const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5309 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5310 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5311 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5313 glGenBuffers(1, &m_draw_command_buffer);
5314 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5315 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW);
5316 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
5318 glGenTextures(1, &m_draw_command_buffer_tex);
5319 glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex);
5320 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer);
5321 glBindTexture(GL_TEXTURE_BUFFER, 0);
5323 glGenVertexArrays(1, &m_attribless_vao);
5324 CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL);
5326 glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
5328 glEnable(GL_RASTERIZER_DISCARD);
5329 glUseProgram(m_store_program);
5330 glBindVertexArray(m_attribless_vao);
5331 glDrawArrays(GL_POINTS, 0, 1);
5333 glDisable(GL_RASTERIZER_DISCARD);
5334 glClear(GL_COLOR_BUFFER_BIT);
5335 glUseProgram(m_draw_program);
5336 glBindVertexArray(m_draw_vao);
5337 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5338 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
5339 glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0);
5341 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5348 virtual long Cleanup()
5351 glDeleteBuffers(1, &m_draw_command_buffer);
5352 glDeleteTextures(1, &m_draw_command_buffer_tex);
5353 glDeleteProgram(m_store_program);
5354 glDeleteProgram(m_draw_program);
5355 glDeleteVertexArrays(1, &m_attribless_vao);
5356 glDeleteVertexArrays(1, &m_draw_vao);
5357 glDeleteBuffers(1, &m_draw_vbo);
5361 //-----------------------------------------------------------------------------
5362 // 2.1.5 AdvancedSyncTextureUpdate
5363 //-----------------------------------------------------------------------------
5364 class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase
5367 GLuint m_store_program;
5368 GLuint m_draw_program;
5373 virtual long Setup()
5376 m_store_program = 0;
5386 const char* const glsl_vs =
5387 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5388 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5389 const char* const glsl_store_fs =
5390 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
5391 " imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL " discard;" NL "}";
5392 const char* const glsl_draw_fs =
5393 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5394 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}";
5395 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5396 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5398 std::vector<vec4> data(16 * 16, vec4(1.0f));
5399 glGenBuffers(1, &m_pbo);
5400 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5401 glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ);
5402 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5404 glGenTextures(1, &m_texture);
5405 glBindTexture(GL_TEXTURE_2D, m_texture);
5406 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5407 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
5408 glBindTexture(GL_TEXTURE_2D, 0);
5410 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5412 glViewport(0, 0, 16, 16);
5413 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5414 glUseProgram(m_store_program);
5415 glBindVertexArray(m_vao);
5416 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5418 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5419 glBindTexture(GL_TEXTURE_2D, m_texture);
5420 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
5421 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0);
5422 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5424 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5425 glClear(GL_COLOR_BUFFER_BIT);
5426 glUseProgram(m_draw_program);
5427 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5429 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1)))
5436 virtual long Cleanup()
5439 glDeleteBuffers(1, &m_vbo);
5440 glDeleteBuffers(1, &m_pbo);
5441 glDeleteTextures(1, &m_texture);
5442 glDeleteProgram(m_store_program);
5443 glDeleteProgram(m_draw_program);
5444 glDeleteVertexArrays(1, &m_vao);
5448 //-----------------------------------------------------------------------------
5449 // 2.1.6 AdvancedSyncImageAccess2
5450 //-----------------------------------------------------------------------------
5451 class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
5454 GLuint m_store_program;
5455 GLuint m_draw_program;
5459 virtual long Setup()
5462 m_store_program = 0;
5471 const char* const glsl_vs =
5472 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5473 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5474 const char* const glsl_store_fs =
5475 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
5476 " imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL " discard;" NL "}";
5477 const char* const glsl_draw_fs =
5478 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5479 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}";
5480 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5481 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5483 glGenTextures(1, &m_texture);
5484 glBindTexture(GL_TEXTURE_2D, m_texture);
5485 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5486 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_FLOAT, NULL);
5487 glBindTexture(GL_TEXTURE_2D, 0);
5489 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5491 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5492 glUseProgram(m_store_program);
5493 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
5494 glBindVertexArray(m_vao);
5495 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5497 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5499 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5500 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5502 glClear(GL_COLOR_BUFFER_BIT);
5503 glBindTexture(GL_TEXTURE_2D, m_texture);
5504 glUseProgram(m_draw_program);
5505 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5507 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5514 virtual long Cleanup()
5517 glDeleteBuffers(1, &m_vbo);
5518 glDeleteTextures(1, &m_texture);
5519 glDeleteProgram(m_store_program);
5520 glDeleteProgram(m_draw_program);
5521 glDeleteVertexArrays(1, &m_vao);
5525 //-----------------------------------------------------------------------------
5526 // 2.1.7 AdvancedSyncBufferUpdate
5527 //-----------------------------------------------------------------------------
5528 class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase
5531 GLuint m_buffer_tex;
5532 GLuint m_store_program;
5533 GLuint m_attribless_vao;
5535 virtual long Setup()
5539 m_store_program = 0;
5540 m_attribless_vao = 0;
5546 if (!SupportedInVS(1))
5547 return NOT_SUPPORTED;
5548 const char* const glsl_store_vs =
5549 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5550 " imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}";
5551 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5553 glGenVertexArrays(1, &m_attribless_vao);
5554 glBindVertexArray(m_attribless_vao);
5556 glGenBuffers(1, &m_buffer);
5557 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5558 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW);
5559 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5561 glGenTextures(1, &m_buffer_tex);
5562 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5563 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5565 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5567 glEnable(GL_RASTERIZER_DISCARD);
5568 glUseProgram(m_store_program);
5569 glDrawArrays(GL_POINTS, 0, 1000);
5571 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5573 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5575 reinterpret_cast<vec4*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT));
5576 for (int i = 0; i < 1000; ++i)
5578 if (!IsEqual(ptr[i], vec4(static_cast<float>(i))))
5580 m_context.getTestContext().getLog()
5581 << tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage;
5588 virtual long Cleanup()
5590 glDisable(GL_RASTERIZER_DISCARD);
5592 glDeleteBuffers(1, &m_buffer);
5593 glDeleteTextures(1, &m_buffer_tex);
5594 glDeleteProgram(m_store_program);
5595 glDeleteVertexArrays(1, &m_attribless_vao);
5599 //-----------------------------------------------------------------------------
5600 // 2.2.1 AdvancedAllStagesOneImage
5601 //-----------------------------------------------------------------------------
5602 class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
5609 GLuint m_buffer_tex;
5612 virtual long Setup()
5626 if (!SupportedInGeomStages(2))
5627 return NOT_SUPPORTED;
5628 const char* const glsl_vs =
5629 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5630 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5631 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5632 " gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL " imageAtomicAdd(g_buffer, 0, 1);" NL
5633 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5634 const char* const glsl_tcs =
5635 "#version 420 core" NL "layout(vertices = 1) out;" NL
5636 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5637 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5638 " gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL " gl_TessLevelInner[0] = 1.0;" NL
5639 " gl_TessLevelInner[1] = 1.0;" NL " gl_TessLevelOuter[0] = 1.0;" NL " gl_TessLevelOuter[1] = 1.0;" NL
5640 " gl_TessLevelOuter[2] = 1.0;" NL " gl_TessLevelOuter[3] = 1.0;" NL " imageAtomicAdd(g_buffer, 0, 1);" NL
5641 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5642 const char* const glsl_tes =
5643 "#version 420 core" NL "layout(triangles, point_mode) in;" NL
5644 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5645 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5646 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5647 " gl_Position = gl_in[0].gl_Position;" NL "}";
5648 const char* const glsl_gs =
5649 "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
5650 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5651 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5652 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5653 " gl_Position = gl_in[0].gl_Position;" NL " EmitVertex();" NL "}";
5654 const char* const glsl_fs =
5655 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5656 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5657 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5658 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5659 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5660 m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs);
5661 glUseProgram(m_program);
5662 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5663 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5665 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
5668 glGenBuffers(1, &m_buffer);
5669 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5670 glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW);
5671 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5673 glGenTextures(1, &m_buffer_tex);
5674 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5675 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer);
5676 glBindTexture(GL_TEXTURE_BUFFER, 0);
5679 glGenTextures(1, &m_texture);
5680 glBindTexture(GL_TEXTURE_2D, m_texture);
5681 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5682 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5683 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5684 glBindTexture(GL_TEXTURE_2D, 0);
5686 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5687 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5689 glBindVertexArray(m_vao);
5690 glPatchParameteri(GL_PATCH_VERTICES, 1);
5692 glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0);
5693 glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1);
5695 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5696 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5697 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32);
5698 if (i32 < 20 || i32 > 50)
5700 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32
5701 << " should be in the range [20;50]" << tcu::TestLog::EndMessage;
5705 glBindTexture(GL_TEXTURE_2D, m_texture);
5706 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5707 if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32))
5709 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be "
5710 << (2 * i32) << tcu::TestLog::EndMessage;
5717 virtual long Cleanup()
5719 glPatchParameteri(GL_PATCH_VERTICES, 3);
5721 glDeleteBuffers(1, &m_buffer);
5722 glDeleteBuffers(1, &m_vbo);
5723 glDeleteBuffers(1, &m_ebo);
5724 glDeleteTextures(1, &m_buffer_tex);
5725 glDeleteTextures(1, &m_texture);
5726 glDeleteProgram(m_program);
5727 glDeleteVertexArrays(1, &m_vao);
5731 //-----------------------------------------------------------------------------
5732 // 2.3.1 AdvancedMemoryDependentInvocation
5733 //-----------------------------------------------------------------------------
5734 class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase
5737 GLuint m_buffer_tex;
5743 virtual long Setup()
5756 if (!SupportedInVS(2))
5757 return NOT_SUPPORTED;
5758 const char* const glsl_vs =
5759 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5760 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL
5761 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5762 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " gl_Position = i_position;" NL
5763 " vs_color = i_color;" NL " imageStore(g_buffer, 0, vec4(1.0));" NL
5764 " imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL " memoryBarrier();" NL "}";
5765 const char* const glsl_fs =
5766 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5767 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5768 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL
5769 " if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
5770 " if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}";
5771 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5772 glUseProgram(m_program);
5773 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5774 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5777 glGenBuffers(1, &m_buffer);
5778 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5779 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW);
5780 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5782 glGenTextures(1, &m_buffer_tex);
5783 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5784 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5785 glBindTexture(GL_TEXTURE_BUFFER, 0);
5787 glGenTextures(1, &m_texture);
5788 glBindTexture(GL_TEXTURE_2D, m_texture);
5789 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5790 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero);
5791 glBindTexture(GL_TEXTURE_2D, 0);
5793 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5794 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5796 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5798 glClear(GL_COLOR_BUFFER_BIT);
5799 glBindVertexArray(m_vao);
5800 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5802 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5809 virtual long Cleanup()
5812 glDeleteBuffers(1, &m_vbo);
5813 glDeleteBuffers(1, &m_buffer);
5814 glDeleteTextures(1, &m_texture);
5815 glDeleteTextures(1, &m_buffer_tex);
5816 glDeleteProgram(m_program);
5817 glDeleteVertexArrays(1, &m_vao);
5821 //-----------------------------------------------------------------------------
5822 // 2.3.2 AdvancedMemoryOrder
5823 //-----------------------------------------------------------------------------
5824 class AdvancedMemoryOrder : public ShaderImageLoadStoreBase
5827 GLuint m_buffer_tex;
5833 virtual long Setup()
5846 if (!SupportedInVS(1))
5847 return NOT_SUPPORTED;
5848 const char* const glsl_vs =
5849 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
5850 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL
5851 " gl_Position = i_position;" NL " vs_color = vec4(0, 1, 0, 1);" NL
5852 " imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL " imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL
5853 " imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL
5854 " if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}";
5855 const char* const glsl_fs =
5856 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5857 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL
5858 " ivec2 coord = ivec2(gl_FragCoord);" NL " for (int i = 0; i < 3; ++i) {" NL
5859 " imageStore(g_image, coord, vec4(i));" NL " vec4 v = imageLoad(g_image, coord);" NL
5860 " if (v != vec4(i)) {" NL " o_color = vec4(v.xyz, 0.0);" NL " break;" NL " }" NL " }" NL
5862 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5863 glUseProgram(m_program);
5864 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5865 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5867 glGenBuffers(1, &m_buffer);
5868 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5869 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
5870 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5872 glGenTextures(1, &m_buffer_tex);
5873 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5874 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5875 glBindTexture(GL_TEXTURE_BUFFER, 0);
5877 std::vector<vec4> data(getWindowWidth() * getWindowHeight());
5878 glGenTextures(1, &m_texture);
5879 glBindTexture(GL_TEXTURE_2D, m_texture);
5880 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5881 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_FLOAT, &data[0]);
5882 glBindTexture(GL_TEXTURE_2D, 0);
5884 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5885 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5887 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5889 glClear(GL_COLOR_BUFFER_BIT);
5890 glBindVertexArray(m_vao);
5891 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5893 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5900 virtual long Cleanup()
5903 glDeleteBuffers(1, &m_vbo);
5904 glDeleteBuffers(1, &m_buffer);
5905 glDeleteTextures(1, &m_texture);
5906 glDeleteTextures(1, &m_buffer_tex);
5907 glDeleteProgram(m_program);
5908 glDeleteVertexArrays(1, &m_vao);
5912 //-----------------------------------------------------------------------------
5913 // 2.4.1 AdvancedSSOSimple
5914 //-----------------------------------------------------------------------------
5915 class AdvancedSSOSimple : public ShaderImageLoadStoreBase
5918 GLuint m_pipeline[2];
5919 GLuint m_vsp, m_fsp0, m_fsp1;
5920 GLuint m_vao, m_vbo;
5922 virtual long Setup()
5924 glGenTextures(1, &m_texture);
5925 glGenProgramPipelines(2, m_pipeline);
5926 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5928 const char* const glsl_vs =
5929 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
5930 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}";
5931 const char* const glsl_fs0 =
5932 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL
5933 " for (int i = 0; i < g_image.length(); ++i) {" NL
5934 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL " }" NL " discard;" NL "}";
5935 const char* const glsl_fs1 =
5936 "#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL
5937 " for (int i = 0; i < g_image.length(); ++i) {" NL
5938 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL " }" NL " discard;" NL "}";
5939 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
5940 m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
5941 m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
5948 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0);
5949 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2);
5950 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4);
5951 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6);
5953 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1);
5954 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3);
5955 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5);
5956 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7);
5958 glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
5959 glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
5961 glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
5962 glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
5964 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
5965 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5966 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 8, 0, GL_RGBA, GL_FLOAT,
5969 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5970 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
5971 glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F);
5972 glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
5973 glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
5974 glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F);
5975 glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
5976 glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F);
5978 glBindVertexArray(m_vao);
5980 glBindProgramPipeline(m_pipeline[0]);
5981 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5983 glBindProgramPipeline(m_pipeline[1]);
5984 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5986 std::vector<vec4> data(getWindowWidth() * getWindowHeight() * 8);
5987 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
5989 for (int layer = 0; layer < 8; ++layer)
5991 for (int h = 0; h < getWindowHeight(); ++h)
5993 for (int w = 0; w < getWindowWidth(); ++w)
5995 const vec4 c = data[layer * getWindowWidth() * getWindowHeight() + h * getWindowWidth() + w];
5998 if (!IsEqual(c, vec4(2.0f)))
6005 if (!IsEqual(c, vec4(1.0f)))
6016 virtual long Cleanup()
6018 glDeleteBuffers(1, &m_vbo);
6019 glDeleteTextures(1, &m_texture);
6020 glDeleteProgram(m_vsp);
6021 glDeleteProgram(m_fsp0);
6022 glDeleteProgram(m_fsp1);
6023 glDeleteVertexArrays(1, &m_vao);
6024 glDeleteProgramPipelines(2, m_pipeline);
6028 //-----------------------------------------------------------------------------
6029 // 2.4.2 AdvancedSSOAtomicCounters
6030 //-----------------------------------------------------------------------------
6031 class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase
6033 GLuint m_buffer, m_buffer_tex;
6034 GLuint m_counter_buffer;
6035 GLuint m_transform_buffer;
6037 GLuint m_vao, m_vbo;
6038 GLuint m_vsp, m_fsp;
6040 virtual long Setup()
6046 glGenBuffers(1, &m_buffer);
6047 glGenTextures(1, &m_buffer_tex);
6048 glGenBuffers(1, &m_counter_buffer);
6049 glGenBuffers(1, &m_transform_buffer);
6050 glGenProgramPipelines(1, &m_pipeline);
6056 if (!SupportedInVS(1))
6057 return NOT_SUPPORTED;
6059 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
6060 const char* const glsl_vs =
6061 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6062 "layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL
6063 "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL
6064 " mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL
6065 "layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL
6066 " gl_Position = g_transform.mvp * i_position;" NL " o_color = i_color;" NL
6067 " const uint index = atomicCounterIncrement(g_counter);" NL
6068 " imageStore(g_buffer, int(index), gl_Position);" NL "}";
6069 const char* const glsl_fs =
6070 "#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL
6071 "layout(location = 0) out vec4 o_color;" NL "void main() {" NL " o_color = i_color;" NL "}";
6072 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6073 m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
6075 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6076 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
6078 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6079 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
6081 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
6082 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
6084 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer);
6086 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW);
6088 glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer);
6090 glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW);
6092 glClear(GL_COLOR_BUFFER_BIT);
6093 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
6094 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer);
6095 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6096 glBindVertexArray(m_vao);
6097 glBindProgramPipeline(m_pipeline);
6098 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6100 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6105 std::vector<vec4> data(4);
6106 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6107 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]);
6109 for (int i = 0; i < 4; ++i)
6111 if (!IsEqual(data[i], vec4(-1.0f, -1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, -1.0f, 0.0f, 1.0f)) &&
6112 !IsEqual(data[i], vec4(-1.0f, 1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, 1.0f, 0.0f, 1.0f)))
6121 virtual long Cleanup()
6123 glDeleteBuffers(1, &m_buffer);
6124 glDeleteBuffers(1, &m_vbo);
6125 glDeleteBuffers(1, &m_counter_buffer);
6126 glDeleteBuffers(1, &m_transform_buffer);
6127 glDeleteTextures(1, &m_buffer_tex);
6128 glDeleteProgram(m_vsp);
6129 glDeleteProgram(m_fsp);
6130 glDeleteVertexArrays(1, &m_vao);
6131 glDeleteProgramPipelines(1, &m_pipeline);
6135 //-----------------------------------------------------------------------------
6136 // 2.4.3 AdvancedSSOSubroutine
6137 //-----------------------------------------------------------------------------
6138 class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase
6141 GLuint m_attribless_vao;
6143 GLint m_draw_buffer;
6145 virtual long Setup()
6147 glGenTextures(1, &m_texture);
6148 glGenVertexArrays(1, &m_attribless_vao);
6150 const char* const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL
6151 "const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL
6152 "void main() {" NL " gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}";
6153 const char* const glsl_fs =
6154 "#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL
6155 "writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL
6156 "subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL
6157 " imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL
6158 " imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL
6159 " imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL
6160 "subroutine(Brush) void Brush1(ivec2 coord) {" NL
6161 " imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL
6162 " imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL
6163 " imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL
6164 " g_brush(ivec2(gl_FragCoord));" NL "}";
6165 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6172 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1);
6173 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1);
6175 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6176 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6177 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 3, 0, GL_RGBA, GL_FLOAT,
6180 glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer);
6182 glDrawBuffer(GL_NONE);
6183 glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);
6184 glUseProgram(m_program);
6185 glBindVertexArray(m_attribless_vao);
6187 const GLuint indices[2] = { glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"),
6188 glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1") };
6190 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]);
6191 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6193 std::vector<vec4> data(getWindowWidth() * getWindowHeight() * 3);
6194 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6195 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6197 for (int layer = 0; layer < 3; ++layer)
6199 for (int h = 0; h < getWindowHeight(); ++h)
6201 for (int w = 0; w < getWindowWidth(); ++w)
6203 const vec4 c = data[layer * getWindowWidth() * getWindowHeight() + h * getWindowWidth() + w];
6204 if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6206 m_context.getTestContext().getLog()
6207 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6208 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6211 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6213 m_context.getTestContext().getLog()
6214 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6215 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6218 else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6220 m_context.getTestContext().getLog()
6221 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6222 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6229 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]);
6230 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6232 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6233 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6235 for (int layer = 0; layer < 3; ++layer)
6237 for (int h = 0; h < getWindowHeight(); ++h)
6239 for (int w = 0; w < getWindowWidth(); ++w)
6241 const vec4 c = data[layer * getWindowWidth() * getWindowHeight() + h * getWindowWidth() + w];
6242 if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6244 m_context.getTestContext().getLog()
6245 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6246 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6249 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6251 m_context.getTestContext().getLog()
6252 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6253 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6256 else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6258 m_context.getTestContext().getLog()
6259 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6260 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6269 virtual long Cleanup()
6271 glDrawBuffer(m_draw_buffer);
6272 glDeleteTextures(1, &m_texture);
6274 glDeleteProgram(m_program);
6275 glDeleteVertexArrays(1, &m_attribless_vao);
6279 //-----------------------------------------------------------------------------
6280 // 2.4.4 AdvancedSSOPerSample
6281 //-----------------------------------------------------------------------------
6282 class AdvancedSSOPerSample : public ShaderImageLoadStoreBase
6286 GLuint m_vao, m_vbo, m_ebo;
6287 GLuint m_vsp, m_store_fsp, m_load_fsp;
6289 virtual long Setup()
6297 glGenTextures(1, &m_texture);
6298 glGenProgramPipelines(1, &m_pipeline);
6305 if (!SupportedSamples(4))
6306 return NOT_SUPPORTED;
6308 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6310 const char* const glsl_vs =
6311 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6312 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}";
6313 const char* const glsl_store_fs =
6314 "#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL
6315 " imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}";
6316 const char* const glsl_load_fs =
6317 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6318 "layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL
6319 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != "
6320 "vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6321 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6322 m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs);
6323 m_load_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs);
6325 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture);
6326 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, getWindowWidth(), getWindowHeight(),
6328 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
6330 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6331 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp);
6333 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6335 glClear(GL_COLOR_BUFFER_BIT);
6336 glBindVertexArray(m_vao);
6337 glBindProgramPipeline(m_pipeline);
6338 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6340 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6342 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp);
6343 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6345 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6352 virtual long Cleanup()
6354 glDeleteBuffers(1, &m_vbo);
6355 glDeleteBuffers(1, &m_ebo);
6356 glDeleteTextures(1, &m_texture);
6357 glDeleteProgram(m_vsp);
6358 glDeleteProgram(m_store_fsp);
6359 glDeleteProgram(m_load_fsp);
6360 glDeleteVertexArrays(1, &m_vao);
6361 glDeleteProgramPipelines(1, &m_pipeline);
6366 //-----------------------------------------------------------------------------
6367 // 2.5 AdvancedCopyImage
6368 //-----------------------------------------------------------------------------
6369 class AdvancedCopyImage : public ShaderImageLoadStoreBase
6371 GLuint m_texture[2];
6373 GLuint m_vao, m_vbo, m_ebo;
6375 virtual long Setup()
6377 glGenTextures(2, m_texture);
6378 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6380 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6381 "void main() {" NL " gl_Position = i_position;" NL "}";
6382 const char* const glsl_fs =
6383 "#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL
6384 "layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL
6385 " ivec2 coord = ivec2(gl_FragCoord);" NL
6386 " imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL " discard;" NL "}";
6387 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6394 glUseProgram(m_program);
6395 glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0);
6396 glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1);
6398 std::vector<vec4> data(getWindowWidth() * getWindowHeight(), vec4(7.0f));
6399 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6400 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6401 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_FLOAT, &data[0]);
6403 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6404 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6405 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_FLOAT, NULL);
6407 glBindTexture(GL_TEXTURE_2D, 0);
6409 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6410 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
6412 glClear(GL_COLOR_BUFFER_BIT);
6413 glBindVertexArray(m_vao);
6414 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6416 std::vector<vec4> rdata(getWindowWidth() * getWindowHeight());
6417 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6418 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]);
6420 for (int h = 0; h < getWindowHeight(); ++h)
6422 for (int w = 0; w < getWindowWidth(); ++w)
6424 if (!IsEqual(rdata[h * getWindowWidth() + w], vec4(7.0f)))
6433 virtual long Cleanup()
6436 glDeleteBuffers(1, &m_vbo);
6437 glDeleteBuffers(1, &m_ebo);
6438 glDeleteTextures(2, m_texture);
6439 glDeleteProgram(m_program);
6440 glDeleteVertexArrays(1, &m_vao);
6444 //-----------------------------------------------------------------------------
6445 // 2.6 AdvancedAllMips
6446 //-----------------------------------------------------------------------------
6447 class AdvancedAllMips : public ShaderImageLoadStoreBase
6450 GLuint m_store_program, m_load_program;
6451 GLuint m_vao, m_vbo, m_ebo;
6453 virtual long Setup()
6455 glGenTextures(1, &m_texture);
6456 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6458 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6459 "void main() {" NL " gl_Position = i_position;" NL "}";
6460 const char* const glsl_store_fs =
6461 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6462 " for (int i = 0; i < 6; ++i) {" NL " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL " }" NL
6464 const char* const glsl_load_fs =
6465 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6466 "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6467 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " for (int i = 0; i < 6; ++i) {" NL
6468 " const ivec2 coord = ivec2(gl_FragCoord);" NL " const vec4 c = imageLoad(g_image[i], coord);" NL
6469 " if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " }" NL "}";
6470 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
6471 m_load_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs);
6478 glUseProgram(m_store_program);
6479 glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0);
6480 glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1);
6481 glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2);
6482 glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3);
6483 glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4);
6484 glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5);
6487 glUseProgram(m_load_program);
6488 glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0);
6489 glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1);
6490 glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2);
6491 glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3);
6492 glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4);
6493 glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5);
6496 glBindTexture(GL_TEXTURE_2D, m_texture);
6497 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
6498 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
6499 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6500 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
6501 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
6502 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
6503 glBindTexture(GL_TEXTURE_2D, 0);
6505 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6506 glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6507 glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6508 glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6509 glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6510 glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6512 glViewport(0, 0, 32, 32);
6513 glBindVertexArray(m_vao);
6515 glClear(GL_COLOR_BUFFER_BIT);
6516 glUseProgram(m_store_program);
6517 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6519 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6521 glUseProgram(m_load_program);
6522 glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6524 if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1)))
6531 virtual long Cleanup()
6533 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6535 glDeleteBuffers(1, &m_vbo);
6536 glDeleteBuffers(1, &m_ebo);
6537 glDeleteTextures(1, &m_texture);
6538 glDeleteProgram(m_store_program);
6539 glDeleteProgram(m_load_program);
6540 glDeleteVertexArrays(1, &m_vao);
6544 //-----------------------------------------------------------------------------
6546 //-----------------------------------------------------------------------------
6547 class AdvancedCast : public ShaderImageLoadStoreBase
6549 GLuint m_texture[2];
6551 GLuint m_vao, m_vbo, m_ebo;
6553 virtual long Setup()
6555 glGenTextures(2, m_texture);
6556 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6558 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6559 "void main() {" NL " gl_Position = i_position;" NL "}";
6560 const char* const glsl_fs =
6561 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6562 "layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL
6563 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " ivec2 coord = ivec2(gl_FragCoord);" NL
6564 " if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6565 " if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6566 " if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6567 " if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6568 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6575 glUseProgram(m_program);
6576 glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0);
6577 glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1);
6580 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6581 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6582 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6583 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6586 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6587 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6588 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6591 glBindTexture(GL_TEXTURE_2D, 0);
6594 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
6595 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
6597 glClear(GL_COLOR_BUFFER_BIT);
6598 glBindVertexArray(m_vao);
6599 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6601 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6602 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6603 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6604 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6606 for (int h = 0; h < getWindowHeight(); ++h)
6608 for (int w = 0; w < getWindowWidth(); ++w)
6610 const GLubyte c[4] = {
6611 data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6612 data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6614 if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6616 m_context.getTestContext().getLog()
6617 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6618 << ") should be (1 0 0 0)" << tcu::TestLog::EndMessage;
6624 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6625 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6627 for (int h = 0; h < getWindowHeight(); ++h)
6629 for (int w = 0; w < getWindowWidth(); ++w)
6631 const GLubyte c[4] = {
6632 data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6633 data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6635 if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6637 m_context.getTestContext().getLog()
6638 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6639 << ") should be (3 0 0 0)" << tcu::TestLog::EndMessage;
6645 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6652 virtual long Cleanup()
6655 glDeleteBuffers(1, &m_vbo);
6656 glDeleteBuffers(1, &m_ebo);
6657 glDeleteTextures(2, m_texture);
6658 glDeleteProgram(m_program);
6659 glDeleteVertexArrays(1, &m_vao);
6664 /** Test "imageLoad() and imageStore() for single-byte data alignment" description follows.
6667 * - create two textures: "source" and "destination". Fill "source"
6668 * texture with unique values. Fill "destination" texture with zeros,
6669 * - prepare a program object that will read texel from "source" image at given
6670 * coordinates and write its value to "destination" image at same
6672 * - bind "source" and "destination" textures as "source" and "destination"
6674 * - render "full screen" quad (left bottom corner at -1,-1 and right top
6676 * - verify that texel values in "destination" texture match those in
6677 * "source" texture (use glGetTexImage).
6679 * Test with 2D R8UI textures with following dimensions:
6691 * Note that default data alignment should cause problems with packing/
6692 * /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters
6693 * of pixel storage mode have to be changed to one byte alignment.
6695 * Program should consist of vertex and fragment shader. Vertex shader should
6696 * pass vertex position through. Fragment shader should do imageLoad() and
6697 * imageStore() operations at coordinates gl_FragCoord.
6699 class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase
6703 struct TextureDimensions
6708 TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height)
6714 typedef std::deque<TextureDimensions> TextureDimensionsList;
6717 GLuint m_destination_texture_id;
6718 GLuint m_program_id;
6719 TextureDimensionsList m_texture_dimensions;
6720 GLuint m_source_texture_id;
6721 GLuint m_vertex_array_object_id;
6722 GLuint m_vertex_buffer_id;
6726 ImageLoadStoreDataAlignmentTest()
6727 : m_destination_texture_id(0)
6729 , m_source_texture_id(0)
6730 , m_vertex_array_object_id(0)
6731 , m_vertex_buffer_id(0)
6733 /* Nothing to be done here */
6736 /* Methods inherited from SubcaseBase */
6737 virtual long Setup()
6740 const char* const vertex_shader_code = "#version 400 core\n"
6741 "#extension GL_ARB_shader_image_load_store : require\n"
6743 "precision highp float;\n"
6745 "in vec4 vs_in_position;\n"
6749 " gl_Position = vs_in_position;\n"
6752 const char* const fragment_shader_code =
6753 "#version 400 core\n"
6754 "#extension GL_ARB_shader_image_load_store : require\n"
6756 "precision highp float;\n"
6758 "layout(r8ui) writeonly uniform uimage2D u_destination_image;\n"
6759 "layout(r8ui) readonly uniform uimage2D u_source_image;\n"
6763 " uvec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n"
6764 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
6769 /* Vertex postions for "full screen" quad, made with triangle strip */
6770 static const GLfloat m_vertex_buffer_data[] = {
6771 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
6772 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
6773 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
6774 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
6777 /* Result of BuildProgram operation */
6778 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
6780 /* Add all tested texture dimensions */
6781 m_texture_dimensions.push_back(TextureDimensions(16, 16));
6782 m_texture_dimensions.push_back(TextureDimensions(16, 17));
6783 m_texture_dimensions.push_back(TextureDimensions(17, 16));
6784 m_texture_dimensions.push_back(TextureDimensions(17, 17));
6785 m_texture_dimensions.push_back(TextureDimensions(16, 18));
6786 m_texture_dimensions.push_back(TextureDimensions(18, 16));
6787 m_texture_dimensions.push_back(TextureDimensions(18, 18));
6788 m_texture_dimensions.push_back(TextureDimensions(16, 19));
6789 m_texture_dimensions.push_back(TextureDimensions(19, 16));
6790 m_texture_dimensions.push_back(TextureDimensions(19, 19));
6792 /* Clean previous error */
6795 /* Set single-byte data alignment */
6796 glPixelStorei(GL_PACK_ALIGNMENT, 1);
6797 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6798 GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei");
6800 /* Prepare buffer with vertex positions of "full screen" quad" */
6801 glGenBuffers(1, &m_vertex_buffer_id);
6802 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
6804 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
6805 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
6807 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
6808 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
6810 /* Generate vertex array object */
6811 glGenVertexArrays(1, &m_vertex_array_object_id);
6812 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
6814 /* Prepare program object */
6815 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
6816 fragment_shader_code, &is_program_correct);
6817 if (false == is_program_correct)
6826 virtual long Cleanup()
6828 /* Reset OpenGL state */
6829 glBindBuffer(GL_ARRAY_BUFFER, 0);
6830 glBindTexture(GL_TEXTURE_2D, 0);
6831 glBindVertexArray(0);
6834 /* Delete program */
6835 if (0 != m_program_id)
6837 glDeleteProgram(m_program_id);
6841 /* Delete textures */
6842 if (0 != m_destination_texture_id)
6844 glDeleteTextures(1, &m_destination_texture_id);
6845 m_destination_texture_id = 0;
6848 if (0 != m_source_texture_id)
6850 glDeleteTextures(1, &m_source_texture_id);
6851 m_source_texture_id = 0;
6854 /* Delete vertex array object */
6855 if (0 != m_vertex_array_object_id)
6857 glDeleteVertexArrays(1, &m_vertex_array_object_id);
6858 m_vertex_array_object_id = 0;
6862 if (0 != m_vertex_buffer_id)
6864 glDeleteBuffers(1, &m_vertex_buffer_id);
6865 m_vertex_buffer_id = 0;
6876 /* For each dimension */
6877 for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it;
6880 /* Prepare "source" and "destination" textures */
6881 GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id),
6882 "Create2DR8UIDestinationTexture");
6883 GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id),
6884 "Create2DR8UISourceTexture");
6886 /* Copy texture data with imageLoad() and imageStore() operations */
6887 Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id);
6889 /* Compare "source" and "destination" textures */
6891 Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height))
6893 m_context.getTestContext().getLog()
6894 << tcu::TestLog::Message
6895 << "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height
6896 << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
6901 /* Destroy "source" and "destination" textures */
6902 glDeleteTextures(1, &m_destination_texture_id);
6903 glDeleteTextures(1, &m_source_texture_id);
6905 m_destination_texture_id = 0;
6906 m_source_texture_id = 0;
6909 if (false == result)
6919 /* Private methods */
6921 /** Binds a texture to user-specified image unit and updates relevant sampler uniform
6923 * @param program_id Program object id
6924 * @param texture_id Texture id
6925 * @param image_unit Index of image unit
6926 * @param uniform_name Name of image uniform
6928 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char* uniform_name)
6930 /* Uniform location and invalid value */
6931 static const GLint invalid_uniform_location = -1;
6932 GLint image_uniform_location = 0;
6934 /* Get uniform location */
6935 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
6936 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
6937 if (invalid_uniform_location == image_uniform_location)
6939 throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__);
6942 /* Bind texture to image unit */
6943 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI);
6944 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
6946 /* Set uniform to image unit */
6947 glUniform1i(image_uniform_location, image_unit);
6948 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
6951 /** Compare two 2D R8UI textures
6953 * @param left_texture_id Id of "left" texture object
6954 * @param right_texture_id Id of "right" texture object
6955 * @param width Width of the textures
6956 * @param height Height of the textures
6958 * @return true when texture data is identical, false otherwise
6960 bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height)
6962 /* Size of textures */
6963 const GLuint texture_data_size = width * height;
6965 /* Storage for texture data */
6966 std::vector<GLubyte> left_texture_data;
6967 std::vector<GLubyte> right_texture_data;
6969 /* Alocate memory for texture data */
6970 left_texture_data.resize(texture_data_size);
6971 right_texture_data.resize(texture_data_size);
6973 /* Get "left" texture data */
6974 glBindTexture(GL_TEXTURE_2D, left_texture_id);
6975 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
6977 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]);
6978 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
6980 /* Get "right" texture data */
6981 glBindTexture(GL_TEXTURE_2D, right_texture_id);
6982 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
6984 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]);
6985 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
6987 /* Compare texels */
6988 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
6991 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
6993 * @param destination_texture_id Id of "destination" texture object
6994 * @param source_texture_id Id of "source" texture object
6996 void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id)
6999 static const char* const destination_image_uniform_name = "u_destination_image";
7000 static const char* const source_image_uniform_name = "u_source_image";
7002 /* Attribute name */
7003 static const char* const position_attribute_name = "vs_in_position";
7005 /* Attribute location and invalid value */
7006 static const GLint invalid_attribute_location = -1;
7007 GLint position_attribute_location = 0;
7009 /* Set current program */
7010 glUseProgram(m_program_id);
7011 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7013 /* Bind vertex array object */
7014 glBindVertexArray(m_vertex_array_object_id);
7015 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7017 /* Bind buffer with quad vertex positions */
7018 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7019 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7021 /* Set up position attribute */
7022 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7023 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7024 if (invalid_attribute_location == position_attribute_location)
7026 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7030 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7032 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7034 glEnableVertexAttribArray(position_attribute_location);
7035 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7037 /* Set up textures as source and destination images */
7038 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name);
7039 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name);
7042 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7043 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7046 /** Create 2D R8UI texture and fills it with zeros
7048 * @param width Width of created texture
7049 * @param height Height of created texture
7050 * @param out_texture_id Id of created texture, not modified if operation fails
7052 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7054 GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7057 const GLuint texture_size = width * height;
7059 /* Prepare storage for texture data */
7060 std::vector<GLubyte> texture_data;
7061 texture_data.resize(texture_size);
7063 /* Set all texels */
7064 for (GLuint i = 0; i < texture_size; ++i)
7066 texture_data[i] = 0;
7069 /* Create texture */
7070 return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7073 /** Create 2D R8UI texture and fills it with increasing values, starting from 0
7075 * @param width Width of created texture
7076 * @param height Height of created texture
7077 * @param out_texture_id Id of created texture, not modified if operation fails
7079 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7081 GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7084 const GLuint texture_size = width * height;
7086 /* Value of texel */
7087 GLubyte texel_value = 0;
7089 /* Prepare storage for texture data */
7090 std::vector<GLubyte> texture_data;
7091 texture_data.resize(texture_size);
7093 /* Set all texels */
7094 for (GLuint i = 0; i < texture_size; ++i)
7096 texture_data[i] = texel_value++;
7099 /* Create texture */
7100 return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7103 /** Create 2D R8UI texture and fills it with user-provided data
7105 * @param width Width of created texture
7106 * @param height Height of created texture
7107 * @param texture_data Texture data
7108 * @param out_texture_id Id of created texture, not modified if operation fails
7110 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7112 GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte>& texture_data,
7113 GLuint& out_texture_id)
7116 GLuint texture_id = 0;
7118 /* Generate texture */
7119 glGenTextures(1, &texture_id);
7121 if (GL_NO_ERROR != err)
7127 glBindTexture(GL_TEXTURE_2D, texture_id);
7129 if (GL_NO_ERROR != err)
7131 glDeleteTextures(1, &texture_id);
7135 /* Allocate storage and fill texture */
7136 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER,
7137 GL_UNSIGNED_BYTE, &texture_data[0]);
7139 if (GL_NO_ERROR != err)
7141 glDeleteTextures(1, &texture_id);
7145 /* Make texture complete */
7146 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7150 if (GL_NO_ERROR != err)
7152 glDeleteTextures(1, &texture_id);
7156 /* Set out_texture_id */
7157 out_texture_id = texture_id;
7164 /** Test "imageLoad() and imageStore() for non-layered image bindings" description follows.
7166 * Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest).
7168 * Test non-layered image bindings (BindImageTexture <layered>: false) with:
7169 * | Type | Dimensions |
7170 * | 2D_ARRAY | 64x64x6 |
7173 * | CUBE_MAP_ARRAY | 64x3 |
7175 * Use RGBA8 format. All layers shall be tested.
7177 * Program should consist of vertex and fragment shader. Vertex shader should
7178 * pass vertex position through. Fragment shader should do imageLoad() and
7179 * imageStore() operations at coordinates gl_FragCoord. Fragment shader should
7180 * use image2D as image type.
7182 class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase
7186 struct TextureShapeDefinition
7189 GLuint m_n_elements;
7192 TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type)
7193 : m_edge(edge), m_n_elements(n_elements), m_type(type)
7199 typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList;
7202 GLuint m_destination_texture_id;
7203 GLuint m_program_id;
7204 TextureShapeDefinitionList m_texture_shape_definitions;
7205 GLuint m_source_texture_id;
7206 GLuint m_vertex_array_object_id;
7207 GLuint m_vertex_buffer_id;
7211 ImageLoadStoreNonLayeredBindingTest()
7212 : m_destination_texture_id(0)
7214 , m_source_texture_id(0)
7215 , m_vertex_array_object_id(0)
7216 , m_vertex_buffer_id(0)
7218 /* Nothing to be done here */
7221 /* Methods inherited from SubcaseBase */
7222 virtual long Setup()
7225 const char* const vertex_shader_code = "#version 400 core\n"
7226 "#extension GL_ARB_shader_image_load_store : require\n"
7228 "precision highp float;\n"
7230 "in vec4 vs_in_position;\n"
7234 " gl_Position = vs_in_position;\n"
7237 const char* const fragment_shader_code =
7238 "#version 400 core\n"
7239 "#extension GL_ARB_shader_image_load_store : require\n"
7241 "precision highp float;\n"
7243 "layout(rgba8) writeonly uniform image2D u_destination_image;\n"
7244 "layout(rgba8) readonly uniform image2D u_source_image;\n"
7248 " vec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n"
7249 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
7254 /* Vertex postions for "full screen" quad, defined as a triangle strip */
7255 static const GLfloat m_vertex_buffer_data[] = {
7256 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7257 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
7258 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
7259 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
7262 /* Result of BuildProgram operation */
7263 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7265 /* Add all tested texture shapes */
7266 int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7267 m_texture_shape_definitions.push_back(
7268 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY));
7269 m_texture_shape_definitions.push_back(
7270 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D));
7271 m_texture_shape_definitions.push_back(
7272 TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP));
7273 m_texture_shape_definitions.push_back(
7274 TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY));
7276 /* Prepare buffer with vertex positions of "full screen" quad" */
7277 glGenBuffers(1, &m_vertex_buffer_id);
7278 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7280 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7281 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7283 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7284 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7286 /* Generate vertex array object */
7287 glGenVertexArrays(1, &m_vertex_array_object_id);
7288 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7290 /* Prepare program object */
7291 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */,
7292 fragment_shader_code, &is_program_correct);
7293 if (false == is_program_correct)
7302 virtual long Cleanup()
7304 /* Reset OpenGL state */
7305 glBindBuffer(GL_ARRAY_BUFFER, 0);
7306 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
7307 glBindTexture(GL_TEXTURE_3D, 0);
7308 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
7309 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
7310 glBindVertexArray(0);
7313 /* Delete program */
7314 if (0 != m_program_id)
7316 glDeleteProgram(m_program_id);
7320 /* Delete textures */
7321 if (0 != m_destination_texture_id)
7323 glDeleteTextures(1, &m_destination_texture_id);
7324 m_destination_texture_id = 0;
7327 if (0 != m_source_texture_id)
7329 glDeleteTextures(1, &m_source_texture_id);
7330 m_source_texture_id = 0;
7333 /* Delete vertex array object */
7334 if (0 != m_vertex_array_object_id)
7336 glDeleteVertexArrays(1, &m_vertex_array_object_id);
7337 m_vertex_array_object_id = 0;
7341 if (0 != m_vertex_buffer_id)
7343 glDeleteBuffers(1, &m_vertex_buffer_id);
7344 m_vertex_buffer_id = 0;
7355 /* For each shape */
7356 for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin();
7357 m_texture_shape_definitions.end() != it; ++it)
7359 const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type);
7361 /* Prepare "source" and "destination" textures */
7362 GLU_EXPECT_NO_ERROR(
7363 CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id),
7364 "Create2DR8UIDestinationTexture");
7365 GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id),
7366 "Create2DR8UISourceTexture");
7368 /* Copy texture data with imageLoad() and imageStore() operations */
7369 CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers);
7371 /* Compare "source" and "destination" textures */
7373 CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type))
7375 const char* texture_type = "";
7378 case GL_TEXTURE_2D_ARRAY:
7379 texture_type = "2d array";
7382 texture_type = "3d";
7384 case GL_TEXTURE_CUBE_MAP:
7385 texture_type = "Cube map";
7387 case GL_TEXTURE_CUBE_MAP_ARRAY:
7388 texture_type = "Cube map array";
7392 m_context.getTestContext().getLog()
7393 << tcu::TestLog::Message
7394 << "Copy with imageLoad and imageStore failed for texture type: " << texture_type
7395 << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
7400 /* Destroy "source" and "destination" textures */
7401 glDeleteTextures(1, &m_destination_texture_id);
7402 glDeleteTextures(1, &m_source_texture_id);
7404 m_destination_texture_id = 0;
7405 m_source_texture_id = 0;
7408 if (false == result)
7418 /* Private methods */
7420 /** Binds a texture to user-specified image unit and update relevant sampler uniform
7422 * @param program_id Program object id
7423 * @param texture_id Texture id
7424 * @param image_unit Index of image unit
7425 * @param layer Index of layer bound to unit
7426 * @param uniform_name Name of image uniform
7428 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer,
7429 const char* uniform_name)
7431 static const GLint invalid_uniform_location = -1;
7432 GLint image_uniform_location = 0;
7434 /* Get uniform location */
7435 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7436 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7437 if (invalid_uniform_location == image_uniform_location)
7439 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
7442 /* Bind texture to image unit */
7443 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE,
7445 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7447 /* Set uniform to image unit */
7448 glUniform1i(image_uniform_location, image_unit);
7449 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7452 /** Compare two 2D R8UI textures
7454 * @param left_texture_id Id of "left" texture object
7455 * @param right_texture_id Id of "right" texture object
7456 * @param edge Length of texture edge
7457 * @param n_layers Number of layers to compare
7458 * @param type Type of texture
7460 * @return true when texture data is found identical, false otherwise
7462 bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers,
7465 static const GLuint n_components = 4; /* RGBA */
7466 const GLuint texture_data_size = edge * edge * n_layers * n_components;
7468 /* Storage for texture data */
7469 std::vector<GLubyte> left_texture_data;
7470 std::vector<GLubyte> right_texture_data;
7472 ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data);
7473 ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data);
7475 /* Compare texels */
7476 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7479 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7481 * @param destination_texture_id Id of "destination" texture object
7482 * @param source_texture_id Id of "source" texture object
7483 * @param n_layers Number of layers
7485 void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers)
7487 for (GLuint layer = 0; layer < n_layers; ++layer)
7489 CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer);
7493 /** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations
7495 * @param destination_texture_id Id of "destination" texture object
7496 * @param source_texture_id Id of "source" texture object
7497 * @param layer Index of layer
7499 void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer)
7502 static const char* const destination_image_uniform_name = "u_destination_image";
7503 static const char* const source_image_uniform_name = "u_source_image";
7505 /* Attribute name */
7506 static const char* const position_attribute_name = "vs_in_position";
7508 /* Attribute location and invalid value */
7509 static const GLint invalid_attribute_location = -1;
7510 GLint position_attribute_location = 0;
7512 /* Set current program */
7513 glUseProgram(m_program_id);
7514 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7516 /* Bind vertex array object */
7517 glBindVertexArray(m_vertex_array_object_id);
7518 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7520 /* Bind buffer with quad vertex positions */
7521 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7522 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7524 /* Set up vertex attribute array for position attribute */
7525 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7526 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7527 if (invalid_attribute_location == position_attribute_location)
7529 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7533 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7534 0 /* stride */, 0 /* pointer */);
7535 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7537 glEnableVertexAttribArray(position_attribute_location);
7538 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7540 /* Set up textures as source and destination image samplers */
7541 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer,
7542 destination_image_uniform_name);
7543 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name);
7546 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7547 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7550 /** Creates RGBA8 texture of given type and fills it with zeros
7552 * @param edge Edge of created texture
7553 * @param n_elements Number of elements in texture array
7554 * @param target Target of created texture
7555 * @param out_texture_id Id of created texture, not modified if operation fails
7557 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7559 GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7561 /* Constasts to calculate texture size */
7562 static const GLuint n_components = 4; /* RGBA */
7563 const GLuint layer_size = edge * edge * n_components;
7564 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target);
7565 const GLuint texture_size = layer_size * n_layers;
7567 /* Prepare storage for texture data */
7568 std::vector<GLubyte> texture_data;
7569 texture_data.resize(texture_size);
7571 /* Set all texels */
7572 for (GLuint i = 0; i < texture_size; ++i)
7574 texture_data[i] = 0;
7577 /* Create texture */
7578 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7581 /** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa]
7583 * @param edge Edge of created texture
7584 * @param n_elements Number of elements in texture array
7585 * @param target Target of created texture
7586 * @param out_texture_id Id of created texture, not modified if operation fails
7588 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7590 GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7592 /* Constants to calculate texture size */
7593 static const GLuint n_components = 4; /* RGBA */
7594 const GLuint layer_size = edge * edge * n_components;
7595 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target);
7596 const GLuint texture_size = layer_size * n_layers;
7598 /* Value of texel */
7599 GLubyte texel[4] = { 0, 0, 0, 0xaa };
7601 /* Prepare storage for texture data */
7602 std::vector<GLubyte> texture_data;
7603 texture_data.resize(texture_size);
7605 /* Set all texels */
7606 for (GLuint layer = 0; layer < n_layers; ++layer)
7608 const GLuint layer_offset = layer_size * layer;
7610 texel[2] = static_cast<GLubyte>(layer);
7612 for (GLuint y = 0; y < edge; ++y)
7614 const GLuint line_offset = y * edge * n_components + layer_offset;
7616 texel[1] = static_cast<GLubyte>(y);
7618 for (GLuint x = 0; x < edge; ++x)
7620 const GLuint texel_offset = x * n_components + line_offset;
7621 texel[0] = static_cast<GLubyte>(x);
7623 for (GLuint component = 0; component < n_components; ++component)
7625 texture_data[texel_offset + component] = texel[component];
7631 /* Create texture */
7632 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7635 /** Creates RGBA8 texture of given type and fills it provided data
7637 * @param edge Edge of created texture
7638 * @param n_elements Number of elements in texture array
7639 * @param target Target of created texture
7640 * @param texture_data Texture data
7641 * @param out_texture_id Id of created texture, not modified if operation fails
7643 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7645 GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte>& texture_data,
7646 GLuint& out_texture_id)
7649 GLuint texture_id = 0;
7651 /* Generate texture */
7652 glGenTextures(1, &texture_id);
7654 if (GL_NO_ERROR != err)
7660 glBindTexture(target, texture_id);
7662 if (GL_NO_ERROR != err)
7664 glDeleteTextures(1, &texture_id);
7668 /* Allocate storage and fill texture */
7669 if (GL_TEXTURE_CUBE_MAP != target)
7671 glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA,
7672 GL_UNSIGNED_BYTE, &texture_data[0]);
7676 const GLuint n_components = 4;
7677 const GLuint layer_size = edge * edge * n_components;
7679 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7680 GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7681 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7682 GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7683 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7684 GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7685 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7686 GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7687 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7688 GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7689 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7690 GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7693 if (GL_NO_ERROR != err)
7695 glDeleteTextures(1, &texture_id);
7699 /* Make texture complete */
7700 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
7701 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
7702 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7704 if (GL_NO_ERROR != err)
7706 glDeleteTextures(1, &texture_id);
7710 /* Set out_texture_id */
7711 out_texture_id = texture_id;
7717 /** Extracts texture data
7719 * @param texture_id Id of texture object
7720 * @param edge Length of texture edge
7721 * @param n_layers Number of layers
7722 * @param target Target of texture
7723 * @param texture_data Extracted texture data
7725 void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target,
7726 std::vector<GLubyte>& texture_data)
7728 static const GLuint n_components = 4; /* RGBA */
7729 const GLuint texture_data_size = edge * edge * n_layers * n_components;
7731 /* Alocate memory for texture data */
7732 texture_data.resize(texture_data_size);
7735 glBindTexture(target, texture_id);
7736 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7739 if (GL_TEXTURE_CUBE_MAP != target)
7741 glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
7745 const GLuint layer_size = edge * edge * n_components;
7747 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7748 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7749 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7750 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7751 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7752 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7755 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7758 /** Get number of layers per single element for given type of texture
7760 * @param target Target of texture
7762 * @return Number of layers
7764 GLuint GetLayersPerElement(GLenum target)
7768 case GL_TEXTURE_2D_ARRAY:
7772 case GL_TEXTURE_CUBE_MAP:
7773 case GL_TEXTURE_CUBE_MAP_ARRAY:
7777 throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__);
7782 /** Get total number of layers in texture of given type and number of array elements
7784 * @param n_elements Number of elements in texture array
7785 * @param target Target of texture
7787 * @return Number of layers
7789 GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target)
7791 return GetLayersPerElement(target) * n_elements;
7795 /** Test "imageLoad() and imageStore() for incomplete textures" description follows.
7797 * Load from incomplete textures should return 0.
7798 * Store to incomplete textures should be ignored.
7801 * - create two incomplete textures: "incomplete_source" and
7802 * "incomplete_destination",
7803 * - create two complete textures: "complete_source" and
7804 * "complete_destination",
7805 * - fill all textures with unique values,
7806 * - prepare program that will:
7807 * * load texel from "incomplete_source" and store its value to
7808 * "complete_destination",
7809 * * load texel from "complete_source" and store its value to
7810 * "incomplete_destination".
7811 * - bind textures to corresponding image uniforms
7812 * - execute program for all texels,
7813 * - verify that "incomplete_destination" was not modified and
7814 * "complete_destination" is filled with zeros.
7816 * Texture is considered incomplete when it has enabled mipmaping (see below)
7817 * and does not have all mipmap levels defined. But for the case of Image
7818 * accessing, it is considered invalid if it is mipmap-incomplete and the
7819 * level is different to the base level (base-incomplete).
7821 * Creation of incomplete texture:
7822 * - generate and bind texture object id,
7823 * - call TexImage2D with <level>: 0,
7824 * - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make
7825 * sure, it should be initial value),
7826 * - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7827 * - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width,
7830 * Creation of complete texture:
7831 * - generate and bind texture object id,
7832 * - call TexImage2D with <level>: 0,
7833 * - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7834 * - set GL_TEXTURE_MAX_LEVEL parameter to 0.
7837 * - Set level == base_level for complete destinations.
7838 * - Set level != base_level for incomplete destinations that are using
7839 * mipmap-incomplete textures.
7841 * Test with 2D 64x64 RGBA8 textures.
7843 * Program should consist of vertex and fragment shader. Vertex shader should
7844 * pass vertex position through. Fragment shader should do imageLoad() and
7845 * imageStore() operations at coordinates gl_FragCoord.
7847 class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase
7851 /* Magic numbers that will identify textures, which will be used as their
7854 static const GLubyte m_complete_destination_magic_number = 0x11;
7855 static const GLubyte m_complete_source_magic_number = 0x22;
7856 static const GLubyte m_incomplete_destination_magic_number = 0x33;
7857 static const GLubyte m_incomplete_source_magic_number = 0x44;
7860 GLuint m_texture_edge;
7863 GLuint m_complete_destination_texture_id;
7864 GLuint m_complete_source_texture_id;
7865 GLuint m_incomplete_destination_texture_id;
7866 GLuint m_incomplete_source_texture_id;
7867 GLuint m_program_id;
7868 GLuint m_vertex_array_object_id;
7869 GLuint m_vertex_buffer_id;
7873 ImageLoadStoreIncompleteTexturesTest()
7875 , m_complete_destination_texture_id(0)
7876 , m_complete_source_texture_id(0)
7877 , m_incomplete_destination_texture_id(0)
7878 , m_incomplete_source_texture_id(0)
7880 , m_vertex_array_object_id(0)
7881 , m_vertex_buffer_id(0)
7883 /* Nothing to be done here */
7886 /* Methods inherited from SubcaseBase */
7887 virtual long Setup()
7890 const char* const vertex_shader_code = "#version 400 core\n"
7891 "#extension GL_ARB_shader_image_load_store : require\n"
7893 "precision highp float;\n"
7895 "in vec4 vs_in_position;\n"
7899 " gl_Position = vs_in_position;\n"
7902 const char* const fragment_shader_code =
7903 "#version 400 core\n"
7904 "#extension GL_ARB_shader_image_load_store : require\n"
7906 "precision highp float;\n"
7908 "layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n"
7909 "layout(rgba8) readonly uniform image2D u_complete_source_image;\n"
7910 "layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n"
7911 "layout(rgba8) readonly uniform image2D u_incomplete_source_image;\n"
7915 " vec4 complete_loaded_color = imageLoad (u_complete_source_image, ivec2(gl_FragCoord));\n"
7916 " vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n"
7918 " imageStore(u_complete_destination_image,\n"
7919 " ivec2(gl_FragCoord),\n"
7920 " incomplete_loaded_color);\n"
7921 " imageStore(u_incomplete_destination_image,\n"
7922 " ivec2(gl_FragCoord),\n"
7923 " complete_loaded_color);\n"
7928 /* Vertex postions for "full screen" quad, made with triangle strip */
7929 static const GLfloat m_vertex_buffer_data[] = {
7930 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7931 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
7932 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
7933 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
7936 /* Result of BuildProgram operation */
7937 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7939 /* Clean previous error */
7942 m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7944 /* Prepare textures */
7945 GLU_EXPECT_NO_ERROR(
7946 Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id),
7947 "Create2DRGBA8CompleteTexture");
7948 GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id),
7949 "Create2DRGBA8CompleteTexture");
7950 GLU_EXPECT_NO_ERROR(
7951 Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id),
7952 "Create2DRGBA8IncompleteTexture");
7953 GLU_EXPECT_NO_ERROR(
7954 Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id),
7955 "Create2DRGBA8IncompleteTexture");
7957 /* Prepare buffer with vertex positions of "full screen" quad" */
7958 glGenBuffers(1, &m_vertex_buffer_id);
7959 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7961 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7962 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7964 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7965 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7967 /* Generate vertex array object */
7968 glGenVertexArrays(1, &m_vertex_array_object_id);
7969 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7971 /* Prepare program object */
7972 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
7973 fragment_shader_code, &is_program_correct);
7975 if (false == is_program_correct)
7984 virtual long Cleanup()
7986 /* Reset OpenGL state */
7987 glBindBuffer(GL_ARRAY_BUFFER, 0);
7988 glBindTexture(GL_TEXTURE_2D, 0);
7989 glBindVertexArray(0);
7992 /* Delete program */
7993 if (0 != m_program_id)
7995 glDeleteProgram(m_program_id);
7999 /* Delete textures */
8000 if (0 != m_complete_destination_texture_id)
8002 glDeleteTextures(1, &m_complete_destination_texture_id);
8003 m_complete_destination_texture_id = 0;
8006 if (0 != m_complete_source_texture_id)
8008 glDeleteTextures(1, &m_complete_source_texture_id);
8009 m_complete_source_texture_id = 0;
8012 if (0 != m_incomplete_destination_texture_id)
8014 glDeleteTextures(1, &m_incomplete_destination_texture_id);
8015 m_incomplete_destination_texture_id = 0;
8018 if (0 != m_incomplete_source_texture_id)
8020 glDeleteTextures(1, &m_incomplete_source_texture_id);
8021 m_incomplete_source_texture_id = 0;
8024 /* Delete vertex array object */
8025 if (0 != m_vertex_array_object_id)
8027 glDeleteVertexArrays(1, &m_vertex_array_object_id);
8028 m_vertex_array_object_id = 0;
8032 if (0 != m_vertex_buffer_id)
8034 glDeleteBuffers(1, &m_vertex_buffer_id);
8035 m_vertex_buffer_id = 0;
8046 /* Copy textures data with imageLoad() and imageStore() operations */
8047 Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id,
8048 m_complete_source_texture_id, m_incomplete_source_texture_id);
8050 glMemoryBarrier(GL_ALL_BARRIER_BITS);
8052 /* Verify that store to "incomplete destination" was ignored */
8054 CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number))
8056 m_context.getTestContext().getLog()
8057 << tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture"
8058 << tcu::TestLog::EndMessage;
8063 /* Verify that load from "incomplete source" returned 0 */
8064 if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id))
8066 m_context.getTestContext().getLog()
8067 << tcu::TestLog::Message
8068 << "Problem with imageLoad, operation returned non 0 result for incomplete texture"
8069 << tcu::TestLog::EndMessage;
8074 if (false == result)
8084 /* Private methods */
8086 /** Bind texture to image unit and sets image uniform to that unit
8088 * @param program_id Program object id
8089 * @param texture_id Texture id
8090 * @param level Texture level
8091 * @param image_unit Index of image unit
8092 * @param uniform_name Name of image uniform
8094 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit, const char* uniform_name)
8096 /* Uniform location and invalid value */
8097 static const GLint invalid_uniform_location = -1;
8098 GLint image_uniform_location = 0;
8100 /* Get uniform location */
8101 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
8102 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
8103 if (invalid_uniform_location == image_uniform_location)
8105 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
8108 /* Bind texture to image unit */
8109 glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8);
8110 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
8112 /* Set uniform to image unit */
8113 glUniform1i(image_uniform_location, image_unit);
8114 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
8117 /** Check if texture is filled with black color, zeros
8119 * @param texture_id Id of texture object
8121 * @return true when texture is fully black, false otherwise
8123 bool CheckIfTextureIsBlack(GLuint texture_id)
8125 /* Constants to calculate size of texture */
8126 static const GLuint n_components = 4; /* RGBA */
8127 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8129 /* Storage for texture data */
8130 std::vector<GLubyte> black_texture_data;
8131 std::vector<GLubyte> texture_data;
8133 /* Allocate memory */
8134 black_texture_data.resize(texture_data_size);
8135 texture_data.resize(texture_data_size);
8137 /* Set all texels to black */
8138 for (GLuint i = 0; i < texture_data_size; ++i)
8140 black_texture_data[i] = 0;
8144 glBindTexture(GL_TEXTURE_2D, texture_id);
8145 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8147 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8148 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8150 /* Compare texels */
8151 return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size));
8154 /** Check if texture was modified
8156 * @param texture_id Id of texture object
8157 * @param nagic_number Magic number that was to create texture
8159 * @return true if texture contents match expected values, false otherwise
8161 bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number)
8163 /* Constants to calculate size of texture */
8164 static const GLuint n_components = 4; /* RGBA */
8165 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8167 /* Storage for texture data */
8168 std::vector<GLubyte> expected_texture_data;
8169 std::vector<GLubyte> texture_data;
8171 /* Allocate memory */
8172 expected_texture_data.resize(texture_data_size);
8173 texture_data.resize(texture_data_size);
8175 /* Prepare expected texels */
8176 for (GLuint y = 0; y < m_texture_edge; ++y)
8178 const GLuint line_offset = y * m_texture_edge * n_components;
8180 for (GLuint x = 0; x < m_texture_edge; ++x)
8182 const GLuint texel_offset = x * n_components + line_offset;
8184 SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y),
8190 glBindTexture(GL_TEXTURE_2D, texture_id);
8191 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8193 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8194 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8196 /* Compare texels, true when textures are different */
8197 return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size));
8200 /** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations
8202 * @param complete_destination_texture_id Id of "complete destination" texture object
8203 * @param incomplete_destination_texture_id Id of "incomplete destination" texture object
8204 * @param complete_source_texture_id Id of "complete source" texture object
8205 * @param incomplete_source_texture_id Id of "incomplete source" texture object
8207 void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id,
8208 GLuint complete_source_texture_id, GLuint incomplete_source_texture_id)
8211 static const char* const complete_destination_image_uniform_name = "u_complete_destination_image";
8212 static const char* const complete_source_image_uniform_name = "u_complete_source_image";
8213 static const char* const incomplete_destination_image_uniform_name = "u_incomplete_destination_image";
8214 static const char* const incomplete_source_image_uniform_name = "u_incomplete_source_image";
8216 /* Attribute name */
8217 static const char* const position_attribute_name = "vs_in_position";
8219 /* Attribute location and invalid value */
8220 static const GLint invalid_attribute_location = -1;
8221 GLint position_attribute_location = 0;
8223 /* Set current program */
8224 glUseProgram(m_program_id);
8225 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
8227 /* Bind vertex array object */
8228 glBindVertexArray(m_vertex_array_object_id);
8229 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8231 /* Bind buffer with quad vertex positions */
8232 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8233 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8235 /* Setup position attribute */
8236 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
8237 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
8238 if (invalid_attribute_location == position_attribute_location)
8240 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
8244 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0);
8245 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
8247 glEnableVertexAttribArray(position_attribute_location);
8248 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
8250 /* Setup textures as source and destination images */
8251 BindTextureToImage(m_program_id, complete_destination_texture_id,
8252 0 /* texture level */, 0 /* image_unit */,
8253 complete_destination_image_uniform_name);
8254 BindTextureToImage(m_program_id, complete_source_texture_id,
8255 0 /* texture level */, 1 /* image_unit */,
8256 complete_source_image_uniform_name);
8257 BindTextureToImage(m_program_id, incomplete_destination_texture_id,
8258 2 /* texture level */, 2 /* image_unit */,
8259 incomplete_destination_image_uniform_name);
8260 BindTextureToImage(m_program_id, incomplete_source_texture_id,
8261 2 /* texture level */, 3 /* image_unit */,
8262 incomplete_source_image_uniform_name);
8265 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
8266 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
8269 /** Create complete 2D RGBA8 texture.
8271 * @param magic_number Magic number of texture
8272 * @param out_texture_id Id of created texture, not modified if operation fails
8274 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8276 GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8278 /* Constants to calculate size of texture */
8279 static const GLuint n_components = 4; /* RGBA */
8280 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8286 GLuint texture_id = 0;
8288 /* Prepare storage for texture data */
8289 std::vector<GLubyte> texture_data;
8290 texture_data.resize(texture_data_size);
8292 /* Prepare texture data */
8293 for (GLuint y = 0; y < m_texture_edge; ++y)
8295 const GLuint line_offset = y * m_texture_edge * n_components;
8297 for (GLuint x = 0; x < m_texture_edge; ++x)
8299 const GLuint texel_offset = x * n_components + line_offset;
8301 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8305 /* Generate texture */
8306 glGenTextures(1, &texture_id);
8308 if (GL_NO_ERROR != err)
8314 glBindTexture(GL_TEXTURE_2D, texture_id);
8316 if (GL_NO_ERROR != err)
8318 glDeleteTextures(1, &texture_id);
8322 /* Allocate storage and fill texture */
8323 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8324 GL_UNSIGNED_BYTE, &texture_data[0]);
8326 if (GL_NO_ERROR != err)
8328 glDeleteTextures(1, &texture_id);
8332 /* Make texture complete */
8333 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8334 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8335 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8337 if (GL_NO_ERROR != err)
8339 glDeleteTextures(1, &texture_id);
8343 /* Set out_texture_id */
8344 out_texture_id = texture_id;
8350 /** Create incomplete 2D RGBA8 texture
8352 * @param magic_number Magic number of texture
8353 * @param out_texture_id Id of created texture, not modified if operation fails
8355 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8357 GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8359 /* Constants to calculate size of texture */
8360 static const GLuint n_components = 4; /* RGBA */
8361 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8367 GLuint texture_id = 0;
8369 /* Prepare storage for texture data */
8370 std::vector<GLubyte> texture_data;
8371 texture_data.resize(texture_data_size);
8373 /* Prepare texture data */
8374 for (GLuint y = 0; y < m_texture_edge; ++y)
8376 const GLuint line_offset = y * m_texture_edge * n_components;
8378 for (GLuint x = 0; x < m_texture_edge; ++x)
8380 const GLuint texel_offset = x * n_components + line_offset;
8382 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8386 /* Generate texture */
8387 glGenTextures(1, &texture_id);
8389 if (GL_NO_ERROR != err)
8395 glBindTexture(GL_TEXTURE_2D, texture_id);
8397 if (GL_NO_ERROR != err)
8399 glDeleteTextures(1, &texture_id);
8403 /* Allocate storage and fill texture */
8404 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8405 GL_UNSIGNED_BYTE, &texture_data[0]);
8407 if (GL_NO_ERROR != err)
8409 glDeleteTextures(1, &texture_id);
8413 /* Make texture incomplete */
8414 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8415 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7);
8416 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
8418 if (GL_NO_ERROR != err)
8420 glDeleteTextures(1, &texture_id);
8424 /* Set out_texture_id */
8425 out_texture_id = texture_id;
8431 /** Prepare "unique" texels.
8432 * Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc].
8434 * @param texel Storage of texel
8435 * @param x_coordinate X coordiante of texel
8436 * @param y_coordinate Y coordinate of texel
8437 * @param magic_number Magic number of texture
8439 void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number)
8441 texel[0] = x_coordinate;
8442 texel[1] = y_coordinate;
8443 texel[2] = magic_number;
8448 /** Test "Refer to the same image unit using multiple uniforms", description follows.
8451 * - prepare program object, see details below,
8452 * - prepare 2D R32I texture, width should be equal to the number of image
8453 * uniforms used by program object, height should be 2, fill first row with
8454 * unique values, fill second row with zeros,
8455 * - bind texture to first image unit,
8456 * - set all image uniforms to first image unit,
8457 * - execute program for a single vertex,
8459 * - values in first row were negated,
8460 * - values from first row were copied to second row,
8462 * Repeat steps to test all shader stages that support at least 2 image
8465 * Program has to contain all necessary shader stages. Use boilerplate shaders
8466 * for shader stages that are not important for the test.
8468 * Tested shader stage should:
8469 * - Use as many different image formats as possible, image formats compatible
8486 * - Declare maximum allowed number of image uniforms,
8488 * layout(format) uniform gimage2D u_image;
8490 * where <format> is selected image format, <gimage2D> is type of 2D image
8491 * compatible with <format> and <u_image> is unique name of uniform.
8492 * Note that image uniforms cannot be declared as array, due to different image
8493 * formats. Therefore separate uniforms have to be used.
8494 * - Include following code snippet:
8495 * for (int i = 0; i < gl_Max*ImageUniforms; ++i)
8497 * vec row_1_coord(i,0);
8498 * vec row_2_coord(i,1);
8500 * row_1_value = imageLoad(u_image[i], row_1_coord);
8501 * imageStore(u_image[i], row_1_coord, -row_1_value);
8502 * imageStore(u_image[i], row_2_coord, row_1_value);
8504 * where gl_Max*ImageUniforms is the constant corresponding to tested shader
8507 class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase
8511 /** Details of image format
8514 struct imageFormatDetails
8516 typedef bool (*verificationRoutine)(GLint, GLint, GLint);
8518 const char* m_image_format;
8519 const char* m_image_type;
8520 const char* m_color_type;
8521 GLenum m_image_unit_format;
8522 verificationRoutine m_verification_routine;
8525 template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)>
8528 /** Get mask of bits used to store in bit-field
8532 static inline T RawMask()
8534 static const T mask = ValueMask() << OFFSET;
8539 /** Get mask of bits used to store value.
8543 static inline T ValueMask()
8545 static const T mask = (1 << SIZE) - 1;
8554 static inline T Offset()
8560 template <typename T, GLuint SIZE, GLuint OFFSET>
8561 struct Masks<T, SIZE, OFFSET, false>
8563 /** Get mask of bits used to store in bit-field
8567 static inline T RawMask()
8569 DE_ASSERT(DE_FALSE && "Shouldn't be called");
8573 /** Get mask of bits used to store value.
8577 static inline T ValueMask()
8579 DE_ASSERT(DE_FALSE && "Shouldn't be called");
8587 static inline T Offset()
8589 DE_ASSERT(DE_FALSE && "Shouldn't be called");
8594 /** Template class for accessing integer values stored in bit-fields
8597 template <typename T, GLuint SIZE, GLuint OFFSET>
8604 Integer(T raw) : m_raw(raw)
8608 /** Extract value from bit-field
8614 const T mask = Masks<T, SIZE, OFFSET>::RawMask();
8616 const T bits = m_raw & mask;
8617 const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset();
8622 /** Extract value from bit-field and negate it
8624 * @return Negated value
8626 T GetNegated() const
8628 const T mask = Masks<T, SIZE, OFFSET>::ValueMask();
8629 const T value = Get();
8631 return Clamp((~value) + 1) & mask;
8636 const bool isUnsigned = (T(0) < T(-1));
8637 const T min = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1)));
8638 const T max = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L);
8639 const T x = n > max ? max : n;
8640 return x < min ? min : x;
8648 /** Shader stage identification
8653 fragmentShaderStage = 2,
8654 geometryShaderStage = 4,
8655 tesselationControlShaderStage = 8,
8656 tesselationEvalutaionShaderStage = 16,
8657 vertexShaderStage = 32,
8666 testNotSupported = 1,
8671 static const GLint m_min_required_image_uniforms = 2;
8674 GLuint m_program_to_test_fs_stage_id;
8675 GLuint m_program_to_test_gs_stage_id;
8676 GLuint m_program_to_test_tcs_stage_id;
8677 GLuint m_program_to_test_tes_stage_id;
8678 GLuint m_program_to_test_vs_stage_id;
8679 GLuint m_texture_to_test_fs_stage_id;
8680 GLuint m_texture_to_test_gs_stage_id;
8681 GLuint m_texture_to_test_tcs_stage_id;
8682 GLuint m_texture_to_test_tes_stage_id;
8683 GLuint m_texture_to_test_vs_stage_id;
8684 GLuint m_vertex_array_object_id;
8688 ImageLoadStoreMultipleUniformsTest()
8689 : m_program_to_test_fs_stage_id(0)
8690 , m_program_to_test_gs_stage_id(0)
8691 , m_program_to_test_tcs_stage_id(0)
8692 , m_program_to_test_tes_stage_id(0)
8693 , m_program_to_test_vs_stage_id(0)
8694 , m_texture_to_test_fs_stage_id(0)
8695 , m_texture_to_test_gs_stage_id(0)
8696 , m_texture_to_test_tcs_stage_id(0)
8697 , m_texture_to_test_tes_stage_id(0)
8698 , m_texture_to_test_vs_stage_id(0)
8699 , m_vertex_array_object_id(0)
8701 /* Nothing to be done here */
8704 /* Methods inherited from SubcaseBase */
8705 virtual long Setup()
8707 /* Prepare programs */
8708 m_program_to_test_fs_stage_id = buildProgramToTestShaderStage(fragmentShaderStage);
8709 m_program_to_test_gs_stage_id = buildProgramToTestShaderStage(geometryShaderStage);
8710 m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage);
8711 m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage);
8712 m_program_to_test_vs_stage_id = buildProgramToTestShaderStage(vertexShaderStage);
8714 /* Prepare textures */
8715 m_texture_to_test_fs_stage_id = createTextureToTestShaderStage(fragmentShaderStage);
8716 m_texture_to_test_gs_stage_id = createTextureToTestShaderStage(geometryShaderStage);
8717 m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage);
8718 m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage);
8719 m_texture_to_test_vs_stage_id = createTextureToTestShaderStage(vertexShaderStage);
8721 /* Generate vertex array object */
8722 glGenVertexArrays(1, &m_vertex_array_object_id);
8723 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8725 /* Bind vertex array object */
8726 glBindVertexArray(m_vertex_array_object_id);
8727 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8729 /* Set vertices number for patches */
8730 glPatchParameteri(GL_PATCH_VERTICES, 1);
8736 virtual long Cleanup()
8740 /* Delete programs */
8741 if (0 != m_program_to_test_fs_stage_id)
8743 glDeleteProgram(m_program_to_test_fs_stage_id);
8744 m_program_to_test_fs_stage_id = 0;
8747 if (0 != m_program_to_test_gs_stage_id)
8749 glDeleteProgram(m_program_to_test_gs_stage_id);
8750 m_program_to_test_gs_stage_id = 0;
8753 if (0 != m_program_to_test_tcs_stage_id)
8755 glDeleteProgram(m_program_to_test_tcs_stage_id);
8756 m_program_to_test_tcs_stage_id = 0;
8759 if (0 != m_program_to_test_tes_stage_id)
8761 glDeleteProgram(m_program_to_test_tes_stage_id);
8762 m_program_to_test_tes_stage_id = 0;
8765 if (0 != m_program_to_test_vs_stage_id)
8767 glDeleteProgram(m_program_to_test_vs_stage_id);
8768 m_program_to_test_vs_stage_id = 0;
8771 /* Delete textures */
8772 if (0 != m_texture_to_test_fs_stage_id)
8774 glDeleteTextures(1, &m_texture_to_test_fs_stage_id);
8775 m_texture_to_test_fs_stage_id = 0;
8778 if (0 != m_texture_to_test_gs_stage_id)
8780 glDeleteTextures(1, &m_texture_to_test_gs_stage_id);
8781 m_texture_to_test_gs_stage_id = 0;
8784 if (0 != m_texture_to_test_tcs_stage_id)
8786 glDeleteTextures(1, &m_texture_to_test_tcs_stage_id);
8787 m_texture_to_test_tcs_stage_id = 0;
8790 if (0 != m_texture_to_test_tes_stage_id)
8792 glDeleteTextures(1, &m_texture_to_test_tes_stage_id);
8793 m_texture_to_test_tes_stage_id = 0;
8796 if (0 != m_texture_to_test_vs_stage_id)
8798 glDeleteTextures(1, &m_texture_to_test_vs_stage_id);
8799 m_texture_to_test_vs_stage_id = 0;
8802 /* Delete vertex array object id */
8803 if (0 != m_vertex_array_object_id)
8805 glDeleteVertexArrays(1, &m_vertex_array_object_id);
8806 m_vertex_array_object_id = 0;
8817 if (testFailed == testShaderStage(fragmentShaderStage))
8819 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with fragment shader stage!"
8820 << tcu::TestLog::EndMessage;
8825 if (testFailed == testShaderStage(geometryShaderStage))
8827 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with geometry shader stage!"
8828 << tcu::TestLog::EndMessage;
8833 if (testFailed == testShaderStage(tesselationControlShaderStage))
8835 m_context.getTestContext().getLog() << tcu::TestLog::Message
8836 << "Problems with tesselation control shader stage!"
8837 << tcu::TestLog::EndMessage;
8842 if (testFailed == testShaderStage(tesselationEvalutaionShaderStage))
8844 m_context.getTestContext().getLog() << tcu::TestLog::Message
8845 << "Problems with tesselation evaluation shader stage!"
8846 << tcu::TestLog::EndMessage;
8851 if (testFailed == testShaderStage(vertexShaderStage))
8853 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with vertex shader stage!"
8854 << tcu::TestLog::EndMessage;
8859 if (false == result)
8869 /* Static routines */
8870 /** Provide image format details for given index
8872 * @param index Index
8873 * @param out_details Image format detail instance
8875 static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails& out_details)
8877 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = {
8878 "r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger
8881 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = {
8882 { "rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort> },
8883 { "r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F,
8884 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8885 { "r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint> },
8886 { "rgb10_a2", "image2D", "vec4", GL_RGB10_A2,
8887 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8888 { "rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8889 { "rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8890 { "rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM,
8891 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte> },
8892 { "rg16_snorm", "image2D", "vec4", GL_RG16_SNORM,
8893 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort> },
8894 { "rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI,
8895 ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint> },
8896 { "rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI,
8897 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint> },
8898 { "rg16ui", "uimage2D", "uvec4", GL_RG16UI,
8899 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint> },
8900 { "r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger },
8901 { "rgba8i", "iimage2D", "ivec4", GL_RGBA8I,
8902 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint> },
8903 { "rg16i", "iimage2D", "ivec4", GL_RG16I,
8904 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint> }
8907 static const GLuint n_imageUniformFormatDetails =
8908 sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails);
8910 if (n_imageUniformFormatDetails <= index)
8912 out_details = default_format_details;
8916 out_details = format_details[index];
8920 /** Write name of image uniform at given index to output stream
8922 * @param stream Output stream
8923 * @param index Index
8925 static void writeImageUniformNameToStream(std::ostream& stream, GLuint index)
8928 stream << "u_image_" << index;
8931 /** Write name of variable used to store value loaded from image at given index to output stream
8933 * @param stream Output stream
8934 * @param index Index
8936 static void writeLoadedValueVariableNameToStream(std::ostream& stream, GLuint index)
8938 /* loaded_value_0 */
8939 stream << "loaded_value_" << index;
8942 /** Write name of variable used to store coordinate of texel at given row to output stream
8944 * @param stream Output stream
8945 * @param index Index of image uniform
8946 * @param row Row of image
8948 static void writeCoordinatesVariableNameToStream(std::ostream& stream, GLuint index, GLuint row)
8950 /* row_0_coordinates_0 */
8951 stream << "row_" << row << "_coordinates_" << index;
8954 struct imageUniformDeclaration
8956 imageUniformDeclaration(GLuint index) : m_index(index)
8963 /** Write declaration of image uniform at given index to output stream
8965 * @param stream Output stream
8966 * @param imageUniformDeclaration Declaration details
8970 friend std::ostream& operator<<(std::ostream& stream, const imageUniformDeclaration& declaration)
8972 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
8973 getImageUniformDeclarationDetails(declaration.m_index, format_details);
8975 /* layout(r32f) uniform image2D u_image_0; */
8976 stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " ";
8978 ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index);
8985 struct imageLoadCall
8987 imageLoadCall(GLuint index) : m_index(index)
8994 /* Stream operators */
8995 /** Write code that execute imageLoad routine for image at given index to output stream
8997 * @param stream Output stream
8998 * @param load imageLoad call details
9002 friend std::ostream& operator<<(std::ostream& stream, const imageLoadCall& load)
9004 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9005 getImageUniformDeclarationDetails(load.m_index, format_details);
9007 /* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */
9008 stream << format_details.m_color_type << " ";
9010 writeLoadedValueVariableNameToStream(stream, load.m_index);
9012 stream << " = imageLoad(";
9014 writeImageUniformNameToStream(stream, load.m_index);
9018 writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */);
9025 struct imageStoreCall
9027 imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row)
9035 /** Write code that execute imageStore to image at given index to output stream
9037 * @param stream Output stream
9038 * @param store imageStore call details
9042 friend std::ostream& operator<<(std::ostream& stream, const imageStoreCall& store)
9044 /* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */
9045 stream << "imageStore(";
9047 writeImageUniformNameToStream(stream, store.m_index);
9051 writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row);
9053 if (0 == store.m_row)
9062 writeLoadedValueVariableNameToStream(stream, store.m_index);
9068 struct coordinatesVariableDeclaration
9070 coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row)
9077 /** Write declaration of variable for coordinate at given row to output stream
9079 * @param stream Output stream
9080 * @param declaration Declaration details
9084 friend std::ostream& operator<<(std::ostream& stream, const coordinatesVariableDeclaration& declaration)
9086 stream << "const ivec2 ";
9088 writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row);
9090 stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");";
9096 /** Build program to test specified shader stage
9098 * Throws exception in case of any failure
9100 * @param stage Stage id
9102 * @return Program id
9104 GLuint buildProgramToTestShaderStage(shaderStage stage)
9106 static const char* const boilerplate_fragment_shader_code =
9107 "#version 400 core\n"
9108 "#extension GL_ARB_shader_image_load_store : require\n"
9110 "precision highp float;\n"
9117 static const char* const boilerplate_tesselation_evaluation_shader_code =
9118 "#version 400 core\n"
9119 "#extension GL_ARB_shader_image_load_store : require\n"
9121 "precision highp float;\n"
9123 "layout(quads, equal_spacing, ccw) in;\n"
9130 static const char* const boilerplate_vertex_shader_code =
9131 "#version 400 core\n"
9132 "#extension GL_ARB_shader_image_load_store : require\n"
9134 "precision highp float;\n"
9136 "layout(location = 0) in vec4 i_position;\n"
9140 " gl_Position = i_position;\n"
9143 const char* fragment_shader_code = boilerplate_fragment_shader_code;
9144 const char* geometry_shader_code = 0;
9145 bool is_program_built = true;
9146 GLuint program_object_id = 0;
9147 const char* tesselation_control_shader_code = 0;
9148 const char* tesselation_evaluation_shader_code = 0;
9149 std::string tested_shader_stage_code;
9150 const char* vertex_shader_code = boilerplate_vertex_shader_code;
9152 /* Get source code for tested shader stage */
9153 prepareShaderForTestedShaderStage(stage, tested_shader_stage_code);
9155 if (true == tested_shader_stage_code.empty())
9160 /* Set up source code for all required stages */
9163 case fragmentShaderStage:
9164 fragment_shader_code = tested_shader_stage_code.c_str();
9167 case geometryShaderStage:
9168 geometry_shader_code = tested_shader_stage_code.c_str();
9171 case tesselationControlShaderStage:
9172 tesselation_control_shader_code = tested_shader_stage_code.c_str();
9173 tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code;
9176 case tesselationEvalutaionShaderStage:
9177 tesselation_evaluation_shader_code = tested_shader_stage_code.c_str();
9180 case vertexShaderStage:
9181 vertex_shader_code = tested_shader_stage_code.c_str();
9185 TCU_FAIL("Invalid shader stage");
9190 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
9191 geometry_shader_code, fragment_shader_code, &is_program_built);
9193 /* Check if program was built */
9194 if (false == is_program_built)
9196 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
9200 return program_object_id;
9203 /** Create texture to test given shader stage
9205 * Throws exception in case of any failure
9207 * @param stage Stage id
9209 * @return Texture id
9211 GLuint createTextureToTestShaderStage(shaderStage stage)
9213 GLenum error = glGetError();
9214 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9215 GLuint texture_id = 0;
9216 std::vector<GLint> texture_data;
9218 const GLsizei height = 2;
9219 const GLsizei width = max_image_uniforms;
9221 if (m_min_required_image_uniforms > max_image_uniforms)
9226 /* Generate texture id */
9227 glGenTextures(1, &texture_id);
9228 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
9231 glBindTexture(GL_TEXTURE_2D, texture_id);
9232 error = glGetError();
9233 if (GL_NO_ERROR != error)
9235 glDeleteTextures(1, &texture_id);
9236 GLU_EXPECT_NO_ERROR(error, "BindTexture");
9239 /* Prepare storage for texture data */
9240 texture_data.resize(width * height);
9241 for (GLint i = 0; i < max_image_uniforms; ++i)
9243 texture_data[i] = getExpectedValue(i);
9244 texture_data[i + width] = 0;
9247 /* Create first level of texture */
9248 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT,
9250 error = glGetError();
9251 if (GL_NO_ERROR != error)
9253 glDeleteTextures(1, &texture_id);
9254 GLU_EXPECT_NO_ERROR(error, "TexImage2D");
9257 /* Make texture complete */
9258 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
9259 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
9260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9261 error = glGetError();
9262 if (GL_NO_ERROR != error)
9264 glDeleteTextures(1, &texture_id);
9265 GLU_EXPECT_NO_ERROR(error, "TexParameteri");
9272 /** Get value of texel for image at given index
9274 * @param index Index of image uniform
9276 * @return Value of texel
9278 GLint getExpectedValue(GLint index)
9280 // To fix denorm issues with r32f, rg16f and r11f_g11f_b10f
9281 // we set one bit in the exponent of each component of those pixel format
9282 return 0x40104200 + index;
9285 /** Get name of uniform at given index
9287 * @param index Index of uniform
9288 * @param out_name Name of uniform
9290 void getImageUniformName(GLuint index, std::string& out_name)
9292 std::stringstream stream;
9294 writeImageUniformNameToStream(stream, index);
9296 out_name = stream.str();
9299 /** Get maximum number of image uniforms allowed for given shader stage
9301 * @param stage Stage id
9303 * @return Maximum allowed image uniforms
9305 GLint getMaximumImageUniformsForStage(shaderStage stage)
9307 GLint max_image_uniforms = 0;
9312 case fragmentShaderStage:
9313 pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS;
9316 case geometryShaderStage:
9317 pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
9320 case tesselationControlShaderStage:
9321 pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
9324 case tesselationEvalutaionShaderStage:
9325 pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
9328 case vertexShaderStage:
9329 pname = GL_MAX_VERTEX_IMAGE_UNIFORMS;
9333 TCU_FAIL("Invalid shader stage");
9336 glGetIntegerv(pname, &max_image_uniforms);
9337 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
9339 return max_image_uniforms;
9342 /** Prepare source for tested shader stage
9344 * @param stage Stage id
9345 * @param out_code Source code
9347 void prepareShaderForTestedShaderStage(shaderStage stage, std::string& out_code)
9349 GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9350 const char* stage_specific_layout = "";
9351 const char* stage_specific_predicate = "true";
9352 std::stringstream stream;
9354 if (m_min_required_image_uniforms > max_image_uniforms)
9359 /* Expected result follows
9362 * #extension GL_ARB_shader_image_load_store : require
9364 * precision highp float;
9366 * stage_specific_layout goes here
9368 * Uniform declarations go here
9372 * const ivec2 row_0_coordinates(0, 0);
9373 * const ivec2 row_1_coordinates(0, 1);
9375 * For each index <0, GL_MAX_*_IMAGE_UNIFORMS>
9377 * vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates);
9379 * imageStore(u_image_0, row_0_coordinates, -loaded_value_0);
9380 * imageStore(u_image_0, row_1_coordinates, loaded_value_0);
9384 /* Get piece of code specific for stage */
9387 case fragmentShaderStage:
9390 case geometryShaderStage:
9391 stage_specific_layout = "layout(points) in;\n"
9392 "layout(points, max_vertices = 1) out;\n"
9396 case tesselationControlShaderStage:
9397 stage_specific_layout = "layout(vertices = 4) out;\n"
9399 stage_specific_predicate = "gl_InvocationID == 0";
9402 case tesselationEvalutaionShaderStage:
9403 stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n"
9407 case vertexShaderStage:
9411 TCU_FAIL("Invalid shader stage");
9415 stream << "#version 400 core\n"
9416 "#extension GL_ARB_shader_image_load_store : require\n"
9418 "precision highp float;\n"
9420 << stage_specific_layout;
9422 /* Image uniforms declarations */
9423 for (GLint i = 0; i < max_image_uniforms; ++i)
9425 stream << imageUniformDeclaration(i) << "\n";
9433 stream << " if (" << stage_specific_predicate << ")\n";
9436 /* imageLoad and imageStores for each uniform */
9437 for (GLint i = 0; i < max_image_uniforms; ++i)
9439 stream << " " << coordinatesVariableDeclaration(i, 0) << "\n"
9440 << " " << coordinatesVariableDeclaration(i, 1) << "\n"
9442 << " " << imageLoadCall(i) << "\n"
9444 << " " << imageStoreCall(i, 0) << "\n"
9445 << " " << imageStoreCall(i, 1) << "\n";
9447 if (max_image_uniforms > i + 1)
9459 out_code = stream.str();
9462 /** Test given shader stage
9464 * @param stage Stage id
9466 * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms;
9467 * testFailed when test result is negative;
9468 * m_test_passed when test result is positive;
9470 testResult testShaderStage(shaderStage stage)
9472 std::string image_uniform_name;
9473 static const GLint invalid_uniform_location = -1;
9474 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9475 GLenum primitive_mode = GL_POINTS;
9476 GLuint program_id = 0;
9477 testResult result = testPassed;
9478 std::vector<GLint> texture_data;
9479 GLuint texture_id = 0;
9481 static const GLuint height = 2;
9482 const GLuint width = max_image_uniforms;
9484 const GLuint positive_value_index = width;
9485 static const GLuint negated_value_index = 0;
9487 if (m_min_required_image_uniforms > max_image_uniforms)
9489 return testNotSupported;
9492 /* Select program and texture ids for given stage */
9495 case fragmentShaderStage:
9496 program_id = m_program_to_test_fs_stage_id;
9497 texture_id = m_texture_to_test_fs_stage_id;
9500 case geometryShaderStage:
9501 program_id = m_program_to_test_gs_stage_id;
9502 texture_id = m_texture_to_test_gs_stage_id;
9505 case tesselationControlShaderStage:
9506 primitive_mode = GL_PATCHES;
9507 program_id = m_program_to_test_tcs_stage_id;
9508 texture_id = m_texture_to_test_tcs_stage_id;
9511 case tesselationEvalutaionShaderStage:
9512 primitive_mode = GL_PATCHES;
9513 program_id = m_program_to_test_tes_stage_id;
9514 texture_id = m_texture_to_test_tes_stage_id;
9517 case vertexShaderStage:
9518 program_id = m_program_to_test_vs_stage_id;
9519 texture_id = m_texture_to_test_vs_stage_id;
9523 TCU_FAIL("Invalid shader stage");
9527 glUseProgram(program_id);
9528 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
9530 /* Bind texture to image units */
9531 for (GLint i = 0; i < max_image_uniforms; ++i)
9533 imageFormatDetails format_details;
9534 getImageUniformDeclarationDetails(i, format_details);
9536 glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9537 GL_READ_WRITE, format_details.m_image_unit_format);
9538 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9541 /* Set all image uniforms to corresponding image units */
9542 for (GLint i = 0; i < max_image_uniforms; ++i)
9545 getImageUniformName(i, image_uniform_name);
9548 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str());
9549 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
9551 if (invalid_uniform_location == image_uniform_location)
9553 throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__,
9557 /* Set uniform value */
9558 glUniform1i(image_uniform_location, i /* image_unit */);
9559 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
9563 glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */);
9564 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
9566 glMemoryBarrier(GL_ALL_BARRIER_BITS);
9568 texture_data.resize(width * height);
9570 /* Get texture data */
9571 glBindTexture(GL_TEXTURE_2D, texture_id);
9572 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
9574 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]);
9575 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
9577 /* Verify each image uniform */
9578 for (GLint i = 0; i < max_image_uniforms; ++i)
9580 imageFormatDetails format_details;
9581 getImageUniformDeclarationDetails(i, format_details);
9584 format_details.m_verification_routine(getExpectedValue(i), texture_data[positive_value_index + i],
9585 texture_data[negated_value_index + i]))
9587 m_context.getTestContext().getLog()
9588 << tcu::TestLog::Message << "Invalid result!"
9589 << " Image format: " << format_details.m_image_format << " Original value: "
9590 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i)
9591 << " Copied value: "
9592 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9593 << texture_data[positive_value_index + i] << " Negated value: "
9594 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9595 << texture_data[negated_value_index + i] << tcu::TestLog::EndMessage;
9597 result = testFailed;
9605 /** Verifies if original_value, positive_value and negated_value match
9607 * @tparam T Type used during verification process, it should match float values by size
9609 * @param original_value Original value of texel, used when creating a texture
9610 * @param positive_value Value stored by shader as read
9611 * @param negated_value Value stored by shader after negation
9613 * @return true if values match, false otherwise
9615 template <typename T>
9616 static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value)
9618 if (original_value != positive_value)
9623 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9624 static const GLuint sign_bit_index = sizeof(T) * 8 - 1; /* 7, 15, 31 */
9625 static const T sign_bit_mask = 1 << sign_bit_index; /* 0x80.. */
9626 static const T sign_bit_inv_mask = (T)~sign_bit_mask; /* 0x7f.. */
9628 const T* positive_elements = (T*)&positive_value;
9629 const T* negated_elements = (T*)&negated_value;
9631 for (GLuint i = 0; i < n_elements; ++i)
9633 const T positive_element = positive_elements[i];
9634 const T negated_element = negated_elements[i];
9636 const T positive_sign_bit = positive_element & sign_bit_mask;
9637 const T negated_sign_bit = negated_element & sign_bit_mask;
9639 const T positive_data = positive_element & sign_bit_inv_mask;
9640 const T negated_data = negated_element & sign_bit_inv_mask;
9642 /* Compare data bits */
9643 if (positive_data != negated_data)
9648 /* Verify that sign bit is inverted */
9649 if (positive_sign_bit == negated_sign_bit)
9658 /** Verifies if original_value, positive_value and negated_value match
9660 * @tparam T Type used during verification process, it should match float values by size
9662 * @param original_value Original value of texel, used when creating a texture
9663 * @param positive_value Value stored by shader as read
9664 * @param negated_value Value stored by shader after negation
9666 * @return true if values match, false otherwise
9668 template <typename T>
9669 static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value)
9671 if (original_value != positive_value)
9676 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9678 const T* positive_elements = (T*)&positive_value;
9679 const T* negated_elements = (T*)&negated_value;
9681 for (GLuint i = 0; i < n_elements; ++i)
9683 const T positive_element = positive_elements[i];
9684 const T negated_element = negated_elements[i];
9686 /* Compare data bits */
9687 if (positive_element != -negated_element)
9696 /** Verifies if original_value, positive_value and negated_value match
9698 * @tparam R Number of bits for red channel
9699 * @tparam G Number of bits for green channel
9700 * @tparam B Number of bits for blue channel
9701 * @tparam A Number of bits for alpha channel
9703 * @param original_value Original value of texel, used when creating a texture
9704 * @param positive_value Value stored by shader as read
9705 * @param negated_value Value stored by shader after negation
9707 * @return true if values match, false otherwise
9709 template <GLuint R, GLuint G, GLuint B, GLuint A, typename T>
9710 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9712 if (original_value != positive_value)
9717 Integer<T, R, 0> positive_red(positive_value);
9718 Integer<T, R, 0> negated_red(negated_value);
9720 Integer<T, G, R> positive_green(positive_value);
9721 Integer<T, G, R> negated_green(negated_value);
9723 Integer<T, B, R + G> positive_blue(positive_value);
9724 Integer<T, B, R + G> negated_blue(negated_value);
9726 Integer<T, A, R + G + B> positive_alpha(positive_value);
9727 Integer<T, A, R + G + B> negated_alpha(negated_value);
9729 if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) ||
9730 ((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) ||
9731 ((0 != G) && (positive_green.GetNegated() != negated_green.Get())) ||
9732 ((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get())))
9740 /** Verifies if original_value, positive_value and negated_value match
9742 * @param original_value Original value of texel, used when creating a texture
9743 * @param positive_value Value stored by shader as read
9744 * @param negated_value Value stored by shader after negation
9746 * @return true if values match, false otherwise
9748 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9750 if (original_value != positive_value)
9755 if (positive_value != -negated_value)
9763 /** Verifies if original_value, positive_value and negated_value match
9765 * @param original_value Original value of texel, used when creating a texture
9766 * @param positive_value Value stored by shader as read
9767 * @param negated_value Value stored by shader after negation
9769 * @return true if values match, false otherwise
9771 template <typename T>
9772 static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value)
9774 if (original_value != positive_value)
9779 if (0 != negated_value)
9788 /** Test "Early fragment tests" description follows.
9790 * BasicGLSLEarlyFragTests verifies that:
9791 * - early z test is applied when enabled,
9792 * - early z test is not applied when disabled.
9794 * Proposed modifications:
9795 * - verify that early z test does not discard all fragments when enabled,
9796 * - verify that early stencil test is applied when enabled,
9797 * - verify that early stencil test does not discard all fragments when
9799 * - verify that early stencil test is not applied when disabled.
9802 * - prepare 2 programs that store 1.0 at red channel to image in fragment
9804 * a) one program should enable early fragment tests
9805 * ("layout(early_fragment_tests) in;"),
9806 * b) second program should disable early fragment tests,
9807 * - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL
9808 * depth-stencil attachments,
9809 * - prepare 2D texture 64x64 R32F,
9810 * - enable depth test,
9811 * - verify that early z test is applied when enabled:
9812 * - use program enabling early fragment tests,
9813 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9814 * - fill texture with zeros,
9815 * - bind texture to image uniform,
9816 * - draw "full screen" quad (left bottom corner at -1,-1 and right top
9817 * corner at 1,1) at z: 0.75
9818 * - verify that texture is still filled with zeros,
9819 * - verify that early z test does not discard all fragments:
9820 * - use program enabling early fragment tests,
9821 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9822 * - fill texture with zeros,
9823 * - bind texture to image uniform,
9824 * - draw "full screen" quad at z: 0.25
9825 * - verify that texture is now filled with 1.0,
9826 * -verify that early z test is not applied when disabled:
9827 * - use program disabling early fragment tests,
9828 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9829 * - fill texture with zeros,
9830 * - bind texture to image uniform,
9831 * - draw "full screen" quad at z: 0.75
9832 * - verify that texture is now filled with 1.0.
9833 * - disable depth test
9834 * - enable stencil test
9835 * - verify that early stencil test is applied when enabled:
9836 * - use program enabling early fragment tests,
9837 * - clean frame buffer with color: 0, stencil: 0 and depth 1,
9838 * - fill texture with zeros,
9839 * - set stencil test to:
9840 * - <func> to GL_LESS,
9842 * - <mask> 0xffffffff,
9843 * - bind texture to image uniform,
9844 * - draw "full screen" quad at z: 0,
9845 * - verify that texture is still filled with zeros,
9846 * - verify that early stencil test does not discard all fragments:
9847 * - use program enabling early fragment tests,
9848 * - clean frame buffer with color: 0, stencil: 128 and depth 1,
9849 * - fill texture with zeros,
9850 * - set stencil test to:
9851 * - <func> to GL_LESS,
9853 * - <mask> 0xffffffff,
9854 * - bind texture to image uniform,
9855 * - draw "full screen" quad at z: 0,
9856 * - verify that texture is now filled with 1.0,
9857 * - verify that early stencil test is not applied when disabled:
9858 * - use program disabling early fragment tests,
9859 * - clean frame buffer with color: 0, stencil: 0 and depth 1,
9860 * - fill texture with zeros,
9861 * - set stencil test to:
9862 * - <func> to GL_LESS,
9864 * - <mask> 0xffffffff,
9865 * - bind texture to image uniform,
9866 * - draw "full screen" quad at z: 0,
9867 * - verify that texture is now filled with 1.0
9869 class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase
9873 GLuint m_image_edge;
9874 static const GLint m_invalid_uniform_location = -1;
9877 /** Store id and uniform locations for a single program object
9880 struct programDetails
9882 GLint m_depth_uniform_location;
9883 GLint m_image_uniform_location;
9884 GLuint m_program_id;
9887 : m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9888 , m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9891 /* Nothing to be done here */
9896 /* Storage for texture data */
9897 std::vector<GLfloat> m_clean_texture_data;
9898 std::vector<GLfloat> m_extracted_texture_data;
9900 /* Program details */
9901 programDetails m_disabled_early_tests;
9902 programDetails m_enabled_early_tests;
9904 /* Ids of GL objects */
9905 GLuint m_color_renderbuffer_id;
9906 GLuint m_depth_stencil_renderbuffer_id;
9907 GLuint m_framebuffer_id;
9908 GLuint m_texture_id;
9909 GLuint m_vertex_array_object_id;
9913 ImageLoadStoreEarlyFragmentTestsTest()
9915 , m_color_renderbuffer_id(0)
9916 , m_depth_stencil_renderbuffer_id(0)
9917 , m_framebuffer_id(0)
9919 , m_vertex_array_object_id(0)
9921 /* Nothing to be done here */
9924 /* Methods inherited from SubcaseBase */
9925 virtual long Cleanup()
9927 /* Restore defaults */
9928 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
9929 glBindRenderbuffer(GL_RENDERBUFFER, 0);
9930 glBindTexture(GL_TEXTURE_2D, 0);
9931 glBindVertexArray(0);
9932 glDisable(GL_DEPTH_TEST);
9933 glDisable(GL_STENCIL_TEST);
9936 /* Delete objects */
9937 if (0 != m_disabled_early_tests.m_program_id)
9939 glDeleteProgram(m_disabled_early_tests.m_program_id);
9940 m_disabled_early_tests.m_program_id = 0;
9943 if (0 != m_enabled_early_tests.m_program_id)
9945 glDeleteProgram(m_enabled_early_tests.m_program_id);
9946 m_enabled_early_tests.m_program_id = 0;
9949 if (0 != m_color_renderbuffer_id)
9951 glDeleteRenderbuffers(1, &m_color_renderbuffer_id);
9952 m_color_renderbuffer_id = 0;
9955 if (0 != m_depth_stencil_renderbuffer_id)
9957 glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
9958 m_depth_stencil_renderbuffer_id = 0;
9961 if (0 != m_framebuffer_id)
9963 glDeleteFramebuffers(1, &m_framebuffer_id);
9964 m_framebuffer_id = 0;
9967 if (0 != m_texture_id)
9969 glDeleteTextures(1, &m_texture_id);
9973 if (0 != m_vertex_array_object_id)
9975 glDeleteVertexArrays(1, &m_vertex_array_object_id);
9976 m_vertex_array_object_id = 0;
9987 /* Bind texture to first image unit */
9988 glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9989 GL_READ_WRITE, GL_R32F);
9990 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9992 /* Run tests for depth test */
9993 if (false == testEarlyZ())
9998 /* Run tests for stencil test */
9999 if (false == testEarlyStencil())
10004 /* Return ERROR if any problem was found */
10005 if (false == result)
10014 virtual long Setup()
10016 m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
10018 /* Prepare storage for texture data */
10019 m_clean_texture_data.resize(m_image_edge * m_image_edge);
10020 m_extracted_texture_data.resize(m_image_edge * m_image_edge);
10022 /* Prepare programs, framebuffer and texture */
10024 createFramebuffer();
10027 /* Generate vertex array object */
10028 glGenVertexArrays(1, &m_vertex_array_object_id);
10029 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
10031 /* Bind vertex array object */
10032 glBindVertexArray(m_vertex_array_object_id);
10033 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
10035 /* Set clear color */
10036 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
10037 GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor");
10044 /** Build two programs: with enabled and disabled early fragment tests
10047 void buildPrograms()
10049 static const char* const fragment_shader_with_disabled_early_tests =
10050 "#version 400 core\n"
10051 "#extension GL_ARB_shader_image_load_store : require\n"
10053 "precision highp float;\n"
10055 "layout(r32f) uniform image2D u_image;\n"
10059 " vec4 color = vec4(1.0, 0, 0, 0);\n"
10061 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10066 static const char* const fragment_shader_with_enabled_early_tests =
10067 "#version 400 core\n"
10068 "#extension GL_ARB_shader_image_load_store : require\n"
10070 "precision highp float;\n"
10072 "layout(early_fragment_tests) in;\n"
10074 "layout(r32f) uniform image2D u_image;\n"
10078 " vec4 color = vec4(1.0, 0, 0, 0);\n"
10080 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10085 static const char* const geometry_shader_code = "#version 400 core\n"
10086 "#extension GL_ARB_shader_image_load_store : require\n"
10088 "precision highp float;\n"
10090 "layout(points) in;\n"
10091 "layout(triangle_strip, max_vertices = 4) out;\n"
10093 "uniform float u_depth;\n"
10097 " // Left-bottom\n"
10098 " gl_Position = vec4(-1, -1, u_depth, 1);\n"
10102 " gl_Position = vec4(-1, 1, u_depth, 1);\n"
10105 " // Right-bottom\n"
10106 " gl_Position = vec4( 1, -1, u_depth, 1);\n"
10110 " gl_Position = vec4( 1, 1, u_depth, 1);\n"
10114 static const char* const vertex_shader_code = "#version 400 core\n"
10115 "#extension GL_ARB_shader_image_load_store : require\n"
10117 "precision highp float;\n"
10123 prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code,
10124 m_disabled_early_tests);
10126 prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code,
10127 m_enabled_early_tests);
10130 /** Fill texture with zeros
10133 void cleanTexture()
10135 glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge,
10136 GL_RED, GL_FLOAT, &m_clean_texture_data[0]);
10137 GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D");
10140 /** Create and bind (draw) framebuffer with color and depth-stencil attachments
10143 void createFramebuffer()
10145 /* Generate render buffers */
10146 glGenRenderbuffers(1, &m_color_renderbuffer_id);
10147 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10149 glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10150 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10152 /* Generate and bind framebuffer object */
10153 glGenFramebuffers(1, &m_framebuffer_id);
10154 GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers");
10156 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
10157 GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer");
10159 /* Prepare color render buffer */
10160 glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id);
10161 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10163 glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge);
10164 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10166 /* Set up color attachment */
10167 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id);
10168 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10170 /* Prepare depth-stencil render buffer */
10171 glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id);
10172 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10174 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge);
10175 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10177 /* Set up depth-stencil attachment */
10178 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10179 m_depth_stencil_renderbuffer_id);
10180 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10183 /** Create 2D R32F texture
10186 void createTexture()
10188 glGenTextures(1, &m_texture_id);
10189 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
10191 glBindTexture(GL_TEXTURE_2D, m_texture_id);
10192 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
10194 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge);
10195 GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D");
10198 /** Extracts red channel from texture and verify if all texels are set to specified value
10200 * @param value Expected value
10202 * @return true if all texel match expected value, false otherwise
10204 bool isTextureFilledWithValue(GLfloat value)
10206 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]);
10207 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
10209 for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i)
10211 if (value != m_extracted_texture_data[i])
10213 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i
10214 << " has invalid value: " << m_extracted_texture_data[i]
10215 << " expected: " << value << tcu::TestLog::EndMessage;
10224 /** Build program, extract location of uniforms and store results in programDetails instance
10226 * Throws tcu::InternalError if uniforms are inactive
10228 * @param fragment_shader_code Source of fragment shader
10229 * @param geometry_shader_code Source of geometry shader
10230 * @param vertex_shader_code Source of vertex shader
10231 * @param out_program_details Instance of programDetails
10233 void prepareProgramDetails(const char* fragment_shader_code, const char* geometry_shader_code,
10234 const char* vertex_shader_code, programDetails& out_program_details)
10236 static const char* const depth_uniform_name = "u_depth";
10237 static const char* const image_uniform_name = "u_image";
10238 bool is_program_built = true;
10240 GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code,
10241 fragment_shader_code, &is_program_built);
10243 if (false == is_program_built)
10245 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
10248 /* Get depth uniform location */
10249 GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name);
10250 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10252 if (m_invalid_uniform_location == depth_uniform_location)
10254 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10257 /* Get image uniform location */
10258 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name);
10259 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10261 if (m_invalid_uniform_location == image_uniform_location)
10263 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10266 /* Store results */
10267 out_program_details.m_depth_uniform_location = depth_uniform_location;
10268 out_program_details.m_image_uniform_location = image_uniform_location;
10269 out_program_details.m_program_id = program_id;
10272 /** Test if early fragment stencil test works as expected.
10274 * @return true if successful, false otherwise
10276 bool testEarlyStencil()
10278 bool result = true;
10280 glEnable(GL_STENCIL_TEST);
10281 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10283 glClearDepthf(1.0f);
10284 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10286 /* verify that early stencil test is applied when enabled */
10288 glUseProgram(m_enabled_early_tests.m_program_id);
10289 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10292 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10294 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10295 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10299 glStencilFunc(GL_LESS, 128, 0xffffffff);
10300 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10302 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10303 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10305 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10306 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10308 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10309 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10311 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10312 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10314 if (false == isTextureFilledWithValue(0.0f))
10316 m_context.getTestContext().getLog() << tcu::TestLog::Message
10317 << "Problem with early stencil test. It is not applied"
10318 << tcu::TestLog::EndMessage;
10324 /* verify that early stencil test does not discard all fragments */
10326 glClearStencil(128);
10327 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10329 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10330 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10334 glStencilFunc(GL_LESS, 0, 0xffffffff);
10335 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10337 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10338 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10340 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10341 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10343 if (false == isTextureFilledWithValue(1.0f))
10345 m_context.getTestContext().getLog()
10346 << tcu::TestLog::Message
10347 << "Problem with early stencil test. It discards fragments, that shall be drawn"
10348 << tcu::TestLog::EndMessage;
10354 /* verify that early stencil test is not applied when disabled */
10356 glUseProgram(m_disabled_early_tests.m_program_id);
10357 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10360 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10362 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10363 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10367 glStencilFunc(GL_LESS, 128, 0xffffffff);
10368 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10370 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10371 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10373 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10374 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10376 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10377 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10379 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10380 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10382 if (false == isTextureFilledWithValue(1.0f))
10384 m_context.getTestContext().getLog() << tcu::TestLog::Message
10385 << "Problem with early stencil test. It is applied when disabled"
10386 << tcu::TestLog::EndMessage;
10392 glDisable(GL_STENCIL_TEST);
10393 GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10399 /** Test if early fragment depth test works as expected.
10401 * @return true if successful, false otherwise
10405 bool result = true;
10407 glEnable(GL_DEPTH_TEST);
10408 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10410 glClearDepthf(0.5f);
10411 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10414 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10416 /* verify that early z test is applied when enabled */
10418 glUseProgram(m_enabled_early_tests.m_program_id);
10419 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10421 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10422 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10426 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10427 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10429 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10430 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10432 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10433 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10435 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10436 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10438 if (false == isTextureFilledWithValue(0.0f))
10440 m_context.getTestContext().getLog() << tcu::TestLog::Message
10441 << "Problem with early z test. It is not applied"
10442 << tcu::TestLog::EndMessage;
10448 /* verify that early z test does not discard all fragments */
10450 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10451 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10455 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10456 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10458 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */);
10459 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10461 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10462 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10464 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10465 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10467 if (false == isTextureFilledWithValue(1.0f))
10469 m_context.getTestContext().getLog()
10470 << tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn"
10471 << tcu::TestLog::EndMessage;
10477 /* verify that early z test is not applied when disabled */
10479 glUseProgram(m_disabled_early_tests.m_program_id);
10480 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10482 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10483 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10487 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10488 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10490 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10491 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10493 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10494 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10496 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10497 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10499 if (false == isTextureFilledWithValue(1.0f))
10501 m_context.getTestContext().getLog() << tcu::TestLog::Message
10502 << "Problem with early z test. It is applied when disabled"
10503 << tcu::TestLog::EndMessage;
10509 glDisable(GL_DEPTH_TEST);
10510 GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10517 //-----------------------------------------------------------------------------
10518 // 4.1 NegativeUniform
10519 //-----------------------------------------------------------------------------
10520 class NegativeUniform : public ShaderImageLoadStoreBase
10524 virtual long Setup()
10532 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
10533 " gl_Position = i_position;" NL "}";
10534 const char* glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
10535 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(0.0));" NL
10536 " discard;" NL "}";
10537 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
10539 GLint max_image_units;
10540 glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
10541 glUseProgram(m_program);
10543 glUniform1i(glGetUniformLocation(m_program, "g_image"), -1);
10544 if (glGetError() != GL_INVALID_VALUE)
10546 m_context.getTestContext().getLog()
10547 << tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero."
10548 << tcu::TestLog::EndMessage;
10551 glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units);
10552 if (glGetError() != GL_INVALID_VALUE)
10554 m_context.getTestContext().getLog()
10555 << tcu::TestLog::Message
10556 << "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of "
10557 << "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
10562 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10563 if (glGetError() != GL_INVALID_VALUE)
10565 m_context.getTestContext().getLog()
10566 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10567 << tcu::TestLog::EndMessage;
10570 i = max_image_units + 1;
10571 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10572 if (glGetError() != GL_INVALID_VALUE)
10574 m_context.getTestContext().getLog()
10575 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is greater "
10576 "than or equal to the value of MAX_IMAGE_UNITS."
10577 << tcu::TestLog::EndMessage;
10581 glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
10582 if (glGetError() != GL_INVALID_OPERATION)
10584 m_context.getTestContext().getLog()
10585 << tcu::TestLog::Message
10586 << "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable."
10587 << tcu::TestLog::EndMessage;
10590 glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
10591 if (glGetError() != GL_INVALID_OPERATION)
10593 m_context.getTestContext().getLog()
10594 << tcu::TestLog::Message
10595 << "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable."
10596 << tcu::TestLog::EndMessage;
10603 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1);
10604 if (glGetError() != GL_INVALID_VALUE)
10606 m_context.getTestContext().getLog()
10607 << tcu::TestLog::Message
10608 << "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero."
10609 << tcu::TestLog::EndMessage;
10612 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units);
10613 if (glGetError() != GL_INVALID_VALUE)
10615 m_context.getTestContext().getLog()
10616 << tcu::TestLog::Message
10617 << "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the "
10618 "value of MAX_IMAGE_UNITS."
10619 << tcu::TestLog::EndMessage;
10624 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10625 if (glGetError() != GL_INVALID_VALUE)
10627 m_context.getTestContext().getLog()
10628 << tcu::TestLog::Message
10629 << "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10630 << tcu::TestLog::EndMessage;
10633 ii = max_image_units + 1;
10634 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10635 if (glGetError() != GL_INVALID_VALUE)
10637 m_context.getTestContext().getLog()
10638 << tcu::TestLog::Message << "glProgramUniform1iv should generate INVALID_VALUE when <value> "
10639 "is greater than or equal to the value of MAX_IMAGE_UNITS."
10640 << tcu::TestLog::EndMessage;
10644 glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
10645 if (glGetError() != GL_INVALID_OPERATION)
10647 m_context.getTestContext().getLog()
10648 << tcu::TestLog::Message << "glProgramUniform1ui should generate INVALID_OPERATION if the "
10649 "location refers to an image variable."
10650 << tcu::TestLog::EndMessage;
10653 glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
10654 if (glGetError() != GL_INVALID_OPERATION)
10656 m_context.getTestContext().getLog()
10657 << tcu::TestLog::Message << "glProgramUniform2i should generate INVALID_OPERATION if the "
10658 "location refers to an image variable."
10659 << tcu::TestLog::EndMessage;
10667 virtual long Cleanup()
10670 glDeleteProgram(m_program);
10674 //-----------------------------------------------------------------------------
10675 // 4.2 NegativeBind
10676 //-----------------------------------------------------------------------------
10677 class NegativeBind : public ShaderImageLoadStoreBase
10679 virtual long Setup()
10686 glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10687 if (glGetError() != GL_INVALID_VALUE)
10689 m_context.getTestContext().getLog()
10690 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> is "
10691 "greater than or equal to the value of MAX_IMAGE_UNITS."
10692 << tcu::TestLog::EndMessage;
10696 glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10697 if (glGetError() != GL_INVALID_VALUE)
10699 m_context.getTestContext().getLog()
10700 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> is not "
10701 "the name of an existing texture object."
10702 << tcu::TestLog::EndMessage;
10706 glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234);
10707 if (glGetError() != GL_INVALID_VALUE)
10709 m_context.getTestContext().getLog()
10710 << tcu::TestLog::Message
10711 << "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format."
10712 << tcu::TestLog::EndMessage;
10718 virtual long Cleanup()
10723 //-----------------------------------------------------------------------------
10724 // 4.3 NegativeCompileErrors
10725 //-----------------------------------------------------------------------------
10726 class NegativeCompileErrors : public ShaderImageLoadStoreBase
10730 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10731 "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
10732 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10735 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10736 "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
10737 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10740 if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL
10741 "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
10742 " imageStore(g_image, ivec2(0), i_color);" NL " o_color = i_color;" NL "}"))
10745 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL
10746 "void main() {" NL " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10749 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10750 "readonly uniform image2D g_image;" NL "void main() {" NL
10751 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10754 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10755 "layout(rg16i) uniform image1D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}"))
10758 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10759 "layout(rg16) uniform iimage2D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}"))
10762 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10763 "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL
10764 " imageAtomicAdd(g_image, ivec2(1), 10);" NL " o_color = vec4(1.0);" NL "}"))
10767 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10768 "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL
10769 " imageAtomicAdd(g_image, ivec2(1), 1u);" NL " o_color = vec4(1.0);" NL "}"))
10772 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10773 "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL
10774 " imageStore(g_image, ivec3(1), ivec4(1));" NL " o_color = vec4(1.0);" NL "}"))
10777 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10778 "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL
10779 " imageStore(g_image, ivec3(0), uvec4(1));" NL " o_color = vec4(1.0);" NL "}"))
10782 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10783 "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL
10784 " return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL " o_color = Load(g_image);" NL
10791 bool Compile(const std::string& source)
10793 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
10795 const char* const src = source.c_str();
10796 glShaderSource(sh, 1, &src, NULL);
10797 glCompileShader(sh);
10800 glGetShaderInfoLog(sh, sizeof(log), NULL, log);
10801 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
10802 << log << tcu::TestLog::EndMessage;
10805 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
10806 glDeleteShader(sh);
10808 if (status == GL_TRUE)
10810 m_context.getTestContext().getLog()
10811 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
10818 //-----------------------------------------------------------------------------
10819 // 4.4 NegativeLinkErrors
10820 //-----------------------------------------------------------------------------
10821 class NegativeLinkErrors : public ShaderImageLoadStoreBase
10825 if (!SupportedInVS(1))
10826 return NOT_SUPPORTED;
10828 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10829 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10830 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}",
10831 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10832 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL
10833 " imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}"))
10836 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10837 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10838 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}",
10839 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10840 "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL
10841 " imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}"))
10847 bool Link(const std::string& vs, const std::string& fs)
10849 const GLuint p = glCreateProgram();
10851 const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
10852 glAttachShader(p, vsh);
10853 glDeleteShader(vsh);
10854 const char* const vssrc = vs.c_str();
10855 glShaderSource(vsh, 1, &vssrc, NULL);
10856 glCompileShader(vsh);
10858 const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
10859 glAttachShader(p, fsh);
10860 glDeleteShader(fsh);
10861 const char* const fssrc = fs.c_str();
10862 glShaderSource(fsh, 1, &fssrc, NULL);
10863 glCompileShader(fsh);
10866 glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
10867 if (status == GL_FALSE)
10869 glDeleteProgram(p);
10870 m_context.getTestContext().getLog()
10871 << tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
10874 glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
10875 if (status == GL_FALSE)
10877 glDeleteProgram(p);
10878 m_context.getTestContext().getLog()
10879 << tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
10886 glGetProgramInfoLog(p, sizeof(log), NULL, log);
10887 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
10888 << log << tcu::TestLog::EndMessage;
10890 glGetProgramiv(p, GL_LINK_STATUS, &status);
10891 glDeleteProgram(p);
10893 if (status == GL_TRUE)
10895 m_context.getTestContext().getLog()
10896 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
10904 /** Negative Test "Active image uniform limits", description follows.
10906 * Program that exceeds resource limits should not compile and/or link.
10909 * - try to compile and link a program that uses too many image uniforms in
10910 * fragment shader stage,
10911 * - try to compile and link a program that uses too many image uniforms in
10912 * vertex shader stage,
10913 * - try to compile and link a program that uses too many image uniforms in
10914 * tessellation control shader stage,
10915 * - try to compile and link a program that uses too many image uniforms in
10916 * tessellation evaluation shader stage,
10917 * - try to compile and link a program that uses too many image uniforms in
10918 * geometry shader stage,
10919 * - try to compile and link a program that uses too many image uniforms in all
10920 * shader stages combined, any single stage should not exceed its limits, this
10921 * step might be impossible to fulfill.
10923 * Test should use the following declaration of image uniforms:
10924 * layout(r32i) uniform iimage2D u_image[N_UNIFORMS];
10926 * For cases where limit for single stage is tested, N_UNIFORMS should be
10927 * defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant
10928 * corresponding to tested shader stage.
10930 * For case where limit for combined stages is tested:
10931 * - u_image name should be appended with the name of shader stage, like
10933 * - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where
10934 * gl_Max*ImageUniforms is constant corresponding to tested shader stage,
10935 * - compilation and linking shall succeed, when sum of all
10936 * gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to
10937 * gl_MaxCombinedImageUniforms.
10939 * All defined image uniforms have to be active. Each shader stage that declare
10940 * image uniforms should include following code snippet:
10942 * for (int i = 0; i < N_UNIFORMS; ++i)
10944 * value = imageAtomicAdd(u_image[i], coord, value);
10947 class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase
10952 bool m_result_for_combined;
10953 bool m_result_for_fragment_shader;
10954 bool m_result_for_geometry_shader;
10955 bool m_result_for_tesselation_control_shader;
10956 bool m_result_for_tesselatioon_evaluation_shader;
10957 bool m_result_for_vertex_shader;
10961 ImageLoadStoreUniformLimitsTest()
10962 : m_result_for_combined(false)
10963 , m_result_for_fragment_shader(false)
10964 , m_result_for_geometry_shader(false)
10965 , m_result_for_tesselation_control_shader(false)
10966 , m_result_for_tesselatioon_evaluation_shader(false)
10967 , m_result_for_vertex_shader(false)
10969 /* Nothing to be done */
10972 /* Methods inherited from SubcaseBase */
10973 virtual long Cleanup()
10981 m_context.getTestContext().getLog() << tcu::TestLog::Message
10982 << "This test tries to build invalid programs, expect error messages about "
10983 "exceeded number of active image uniforms"
10984 << tcu::TestLog::EndMessage;
10986 testFragmentShaderStage();
10987 testGeometryShaderStage();
10988 testTesselationControlShaderStage();
10989 testTesselationEvaluationShaderStage();
10990 testVertexShaderStage();
10991 testCombinedShaderStages();
10993 /* Return error if any stage failed */
10994 if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) ||
10995 (false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) ||
10996 (false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader))
11005 virtual long Setup()
11012 /** Test fragment shader stage
11015 void testFragmentShaderStage()
11017 static const char* const fragment_shader_code =
11018 "#version 400 core\n"
11019 "#extension GL_ARB_shader_image_load_store : require\n"
11021 "precision highp float;\n"
11023 "#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n"
11025 "flat in ivec2 vs_fs_coord;\n"
11027 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11031 " int value = 1;\n"
11033 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11035 " value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n"
11041 static const char* const vertex_shader_code = "#version 400 core\n"
11042 "#extension GL_ARB_shader_image_load_store : require\n"
11044 "precision highp float;\n"
11046 " in ivec2 vs_in_coord;\n"
11047 "flat out ivec2 vs_fs_coord;\n"
11051 " vs_fs_coord = vs_in_coord;\n"
11054 m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11055 0 /* tesselation_control_shader_code */,
11056 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11058 if (false == m_result_for_fragment_shader)
11060 m_context.getTestContext().getLog()
11061 << tcu::TestLog::Message
11062 << "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully."
11063 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11064 << fragment_shader_code << tcu::TestLog::EndMessage;
11068 /** Test geometry shader stage
11071 void testGeometryShaderStage()
11073 static const char* const fragment_shader_code = "#version 400 core\n"
11074 "#extension GL_ARB_shader_image_load_store : require\n"
11076 "precision highp float;\n"
11083 static const char* const geometry_shader_code =
11084 "#version 400 core\n"
11085 "#extension GL_ARB_shader_image_load_store : require\n"
11087 "precision highp float;\n"
11089 "layout(points) in;\n"
11090 "layout(points, max_vertices = 1) out;\n"
11092 "#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n"
11094 "in ivec2 vs_gs_coord[];\n"
11096 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11100 " int value = 1;\n"
11102 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11104 " value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\n"
11108 static const char* const vertex_shader_code = "#version 400 core\n"
11109 "#extension GL_ARB_shader_image_load_store : require\n"
11111 "precision highp float;\n"
11113 "in ivec2 vs_in_coord;\n"
11114 "out ivec2 vs_gs_coord;\n"
11118 " vs_gs_coord = vs_in_coord;\n"
11121 m_result_for_geometry_shader =
11122 !doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */,
11123 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11125 if (false == m_result_for_geometry_shader)
11127 m_context.getTestContext().getLog()
11128 << tcu::TestLog::Message
11129 << "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully."
11130 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11131 << geometry_shader_code << tcu::TestLog::EndMessage;
11135 /** Test tesselation control shader stage
11138 void testTesselationControlShaderStage()
11140 static const char* const fragment_shader_code = "#version 400 core\n"
11141 "#extension GL_ARB_shader_image_load_store : require\n"
11143 "precision highp float;\n"
11150 static const char* const tesselation_control_shader_code =
11151 "#version 400 core\n"
11152 "#extension GL_ARB_shader_image_load_store : require\n"
11154 "precision highp float;\n"
11156 "layout(vertices = 4) out;\n"
11158 "#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n"
11160 "in ivec2 vs_tcs_coord[];\n"
11162 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11166 " int value = 1;\n"
11168 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11170 " value = imageAtomicAdd(u_image[i], vs_tcs_coord[0], value);\n"
11174 static const char* const tesselation_evaluation_shader_code =
11175 "#version 400 core\n"
11176 "#extension GL_ARB_shader_image_load_store : require\n"
11178 "precision highp float;\n"
11180 "layout(quads, equal_spacing, ccw) in;\n"
11186 static const char* const vertex_shader_code = "#version 400 core\n"
11187 "#extension GL_ARB_shader_image_load_store : require\n"
11189 "precision highp float;\n"
11191 "in ivec2 vs_in_coord;\n"
11192 "out ivec2 vs_tcs_coord;\n"
11196 " vs_tcs_coord = vs_in_coord;\n"
11199 m_result_for_tesselation_control_shader =
11200 !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code,
11201 tesselation_evaluation_shader_code, vertex_shader_code);
11203 if (false == m_result_for_tesselation_control_shader)
11205 m_context.getTestContext().getLog()
11206 << tcu::TestLog::Message
11207 << "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully."
11208 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11209 << tesselation_control_shader_code << tcu::TestLog::EndMessage;
11213 /** Test teselation evaluation shader stage
11216 void testTesselationEvaluationShaderStage()
11218 static const char* const fragment_shader_code = "#version 400 core\n"
11219 "#extension GL_ARB_shader_image_load_store : require\n"
11221 "precision highp float;\n"
11228 static const char* const tesselation_evaluation_shader_code =
11229 "#version 400 core\n"
11230 "#extension GL_ARB_shader_image_load_store : require\n"
11232 "precision highp float;\n"
11234 "layout(quads, equal_spacing, ccw) in;\n"
11236 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n"
11238 "in ivec2 vs_tes_coord[];\n"
11240 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11244 " int value = 1;\n"
11246 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11248 " value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n"
11252 static const char* const vertex_shader_code = "#version 400 core\n"
11253 "#extension GL_ARB_shader_image_load_store : require\n"
11255 "precision highp float;\n"
11257 "in ivec2 vs_in_coord;\n"
11258 "out ivec2 vs_tes_coord;\n"
11262 " vs_tes_coord = vs_in_coord;\n"
11265 m_result_for_tesselatioon_evaluation_shader = !doesProgramLink(
11266 fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */,
11267 tesselation_evaluation_shader_code, vertex_shader_code);
11269 if (false == m_result_for_tesselatioon_evaluation_shader)
11271 m_context.getTestContext().getLog()
11272 << tcu::TestLog::Message
11273 << "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully."
11274 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11275 << tesselation_evaluation_shader_code << tcu::TestLog::EndMessage;
11279 /** Test vertex shader stage
11282 void testVertexShaderStage()
11284 static const char* const fragment_shader_code = "#version 400 core\n"
11285 "#extension GL_ARB_shader_image_load_store : require\n"
11287 "precision highp float;\n"
11294 static const char* const vertex_shader_code =
11295 "#version 400 core\n"
11296 "#extension GL_ARB_shader_image_load_store : require\n"
11298 "precision highp float;\n"
11300 "in ivec2 vs_in_coord;\n"
11302 "#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n"
11304 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11308 " int value = 1;\n"
11310 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11312 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11316 m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11317 0 /* tesselation_control_shader_code */,
11318 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11320 if (false == m_result_for_vertex_shader)
11322 m_context.getTestContext().getLog()
11323 << tcu::TestLog::Message
11324 << "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully."
11325 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11326 << vertex_shader_code << tcu::TestLog::EndMessage;
11330 /** Test combined shader stages
11333 void testCombinedShaderStages()
11335 std::string fragment_shader_code =
11336 "#version 400 core\n"
11337 "#extension GL_ARB_shader_image_load_store : require\n"
11339 "precision highp float;\n"
11341 "#define N_UNIFORMS gl_MaxFragmentImageUniforms\n"
11343 "flat in ivec2 gs_fs_coord;\n"
11345 "layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n"
11349 " int value = 1;\n"
11351 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11353 " value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n"
11359 std::string geometry_shader_code =
11360 "#version 400 core\n"
11361 "#extension GL_ARB_shader_image_load_store : require\n"
11363 "precision highp float;\n"
11365 "layout(points) in;\n"
11366 "layout(points, max_vertices = 1) out;\n"
11368 "#define N_UNIFORMS gl_MaxGeometryImageUniforms\n"
11370 "flat in ivec2 tes_gs_coord[];\n"
11371 "flat out ivec2 gs_fs_coord;\n"
11374 "layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n"
11380 " int value = 1;\n"
11382 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11384 " value = imageAtomicAdd(u_image_geometry[i], tes_gs_coord[0], value);\n"
11388 " gs_fs_coord = tes_gs_coord[0];\n"
11392 std::string tesselation_control_shader_code =
11393 "#version 400 core\n"
11394 "#extension GL_ARB_shader_image_load_store : require\n"
11396 "precision highp float;\n"
11398 "layout(vertices = 4) out;\n"
11400 "#define N_UNIFORMS gl_MaxTessControlImageUniforms\n"
11402 "flat in ivec2 vs_tcs_coord[];\n"
11403 "flat out ivec2 tcs_tes_coord[];\n"
11406 "layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n"
11412 " int value = 1;\n"
11414 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11416 " value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n"
11420 " tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n"
11423 std::string tesselation_evaluation_shader_code =
11424 "#version 400 core\n"
11425 "#extension GL_ARB_shader_image_load_store : require\n"
11427 "precision highp float;\n"
11429 "layout(quads, equal_spacing, ccw) in;\n"
11431 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n"
11433 "flat in ivec2 tcs_tes_coord[];\n"
11434 "flat out ivec2 tes_gs_coord;\n"
11437 "layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n"
11443 " int value = 1;\n"
11445 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11447 " value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n"
11451 " tes_gs_coord = tcs_tes_coord[0];\n"
11454 std::string vertex_shader_code =
11455 "#version 400 core\n"
11456 "#extension GL_ARB_shader_image_load_store : require\n"
11458 "precision highp float;\n"
11460 " in ivec2 vs_in_coord;\n"
11461 "flat out ivec2 vs_tcs_coord;\n"
11463 "#define N_UNIFORMS gl_MaxVertexImageUniforms\n"
11466 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11472 " int value = 1;\n"
11474 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11476 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11480 " vs_tcs_coord = vs_tcs_coord;\n"
11483 /* Active image uniform limits */
11484 GLint max_combined_image_uniforms = 0;
11485 GLint max_fragment_image_uniforms = 0;
11486 GLint max_geometry_image_uniforms = 0;
11487 GLint max_tesselation_control_image_uniforms = 0;
11488 GLint max_tesselation_evaluation_image_uniforms = 0;
11489 GLint max_vertex_image_uniforms = 0;
11491 /* Get limit values */
11492 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms);
11493 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms);
11494 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms);
11495 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms);
11496 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms);
11497 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms);
11498 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
11500 if (max_vertex_image_uniforms)
11501 vertex_shader_code.insert(18, "#define IMAGES\n");
11502 if (max_geometry_image_uniforms)
11503 geometry_shader_code.insert(18, "#define IMAGES\n");
11504 if (max_tesselation_control_image_uniforms)
11505 tesselation_control_shader_code.insert(18, "#define IMAGES\n");
11506 if (max_tesselation_evaluation_image_uniforms)
11507 tesselation_evaluation_shader_code.insert(18, "#define IMAGES\n");
11509 /* Check if program builds */
11510 m_result_for_combined =
11511 !doesProgramLink(fragment_shader_code.c_str(),
11512 geometry_shader_code.c_str(),
11513 tesselation_control_shader_code.c_str(),
11514 tesselation_evaluation_shader_code.c_str(),
11515 vertex_shader_code.c_str());
11517 /* Result depends on the limit values */
11518 if (max_combined_image_uniforms >=
11519 (max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms +
11520 max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms))
11522 /* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */
11523 m_result_for_combined = !m_result_for_combined;
11525 if (false == m_result_for_combined)
11527 m_context.getTestContext().getLog()
11528 << tcu::TestLog::Message << "There was an error while building a program."
11529 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11530 << vertex_shader_code << "\nTesselation control shader code:\n"
11531 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11532 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11533 << geometry_shader_code << "\nFragment shader code:\n"
11534 << fragment_shader_code << tcu::TestLog::EndMessage;
11539 /* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */
11540 if (false == m_result_for_combined)
11542 m_context.getTestContext().getLog()
11543 << tcu::TestLog::Message
11544 << "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully."
11545 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11546 << vertex_shader_code << "\nTesselation control shader code:\n"
11547 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11548 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11549 << geometry_shader_code << "\nFragment shader code:\n"
11550 << fragment_shader_code << tcu::TestLog::EndMessage;
11555 /** Check if program builds successfully
11557 * @param fragment_shader_code Source code for fragment shader stage
11558 * @param geometry_shader_code Source code for geometry shader stage
11559 * @param tesselation_control_shader_code Source code for tesselation control shader stage
11560 * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage
11561 * @param vertex_shader_code Source code for vertex shader stage
11563 * @return true if program was built without errors, false otherwise
11565 bool doesProgramLink(const char* fragment_shader_code, const char* geometry_shader_code,
11566 const char* tesselation_control_shader_code, const char* tesselation_evaluation_shader_code,
11567 const char* vertex_shader_code)
11569 bool is_program_built = true;
11570 GLuint program_id = 0;
11573 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
11574 geometry_shader_code, fragment_shader_code, &is_program_built);
11576 if (0 != program_id)
11578 glDeleteProgram(program_id);
11581 return is_program_built;
11586 ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context& context)
11587 : TestCaseGroup(context, "shader_image_load_store", "")
11591 ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
11595 void ShaderImageLoadStoreTests::init()
11597 using namespace deqp;
11598 addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
11599 addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
11600 addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
11601 addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
11602 addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>));
11603 addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>));
11604 addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages",
11605 TestSubcase::Create<BasicAllFormatsStoreGeometryStages>));
11606 addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages",
11607 TestSubcase::Create<BasicAllFormatsLoadGeometryStages>));
11608 addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
11609 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
11610 addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>));
11611 addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>));
11612 addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>));
11613 addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>));
11615 new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
11617 new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>));
11619 new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>));
11621 new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>));
11623 new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
11624 addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
11625 addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>));
11626 addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>));
11627 addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
11628 addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>));
11629 addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
11630 addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
11631 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
11632 addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
11633 addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>));
11634 addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>));
11635 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
11636 addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>));
11637 addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
11638 addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation",
11639 TestSubcase::Create<AdvancedMemoryDependentInvocation>));
11640 addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>));
11641 addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
11642 addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>));
11643 addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>));
11644 addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>));
11645 addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>));
11646 addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>));
11647 addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>));
11649 new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>));
11651 new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>));
11653 new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>));
11654 addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>));
11656 new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>));
11657 addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
11658 addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
11659 addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
11660 addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
11661 addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>));