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 "tcuPlatform.hpp"
29 #include "tcuRenderTarget.hpp"
30 #include "tcuVectorUtil.hpp"
31 #include "vkPlatform.hpp"
40 #include <tcuFloat.hpp>
48 typedef tcu::Vec2 vec2;
49 typedef tcu::Vec4 vec4;
50 typedef tcu::IVec4 ivec4;
51 typedef tcu::UVec4 uvec4;
52 typedef tcu::Mat4 mat4;
54 class ShaderImageLoadStoreBase : public deqp::SubcaseBase
56 virtual std::string Title()
61 virtual std::string Purpose()
66 virtual std::string Method()
71 virtual std::string PassCriteria()
77 bool SupportedInVS(int requiredVS)
80 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
81 if (imagesVS >= requiredVS)
85 std::ostringstream reason;
86 reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
88 OutputNotSupported(reason.str());
93 bool SupportedInTCS(int requiredTCS)
96 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
97 if (imagesTCS >= requiredTCS)
101 std::ostringstream reason;
102 reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
104 OutputNotSupported(reason.str());
109 bool SupportedInTES(int requiredTES)
112 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
113 if (imagesTES >= requiredTES)
117 std::ostringstream reason;
118 reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
120 OutputNotSupported(reason.str());
125 bool SupportedInGS(int requiredGS)
128 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
129 if (imagesGS >= requiredGS)
133 std::ostringstream reason;
134 reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
136 OutputNotSupported(reason.str());
141 bool SupportedInGeomStages(int required)
143 return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) &&
144 SupportedInGS(required);
147 bool SupportedInStage(int stage, int required)
152 return SupportedInVS(required);
154 return SupportedInTCS(required);
156 return SupportedInTES(required);
158 return SupportedInGS(required);
164 bool SupportedSamples(int required)
167 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
172 std::ostringstream reason;
173 reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
174 OutputNotSupported(reason.str());
181 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
182 return renderTarget.getWidth();
185 int getWindowHeight()
187 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
188 return renderTarget.getHeight();
191 void scaleDimensionsToMemory(int& width, int& height, int devLayers, int sysLayers, int devBPP, int sysBPP)
193 vk::PlatformMemoryLimits memoryLimits;
194 m_context.getTestContext().getPlatform().getVulkanPlatform().getMemoryLimits(memoryLimits);
195 GLsizeiptr sysSpace = memoryLimits.totalSystemMemory;
196 GLsizeiptr devSpace = memoryLimits.totalDeviceLocalMemory;
197 int devInSysLayers = 0;
201 devInSysLayers = devLayers;
205 // Check if available memory is enough
206 GLsizeiptr pixelsPerLayer = width * height;
207 GLsizeiptr sysRequired = pixelsPerLayer * ((sysBPP * sysLayers) + (devBPP * devInSysLayers));
208 GLsizeiptr devRequired = pixelsPerLayer * devBPP * devLayers;
209 if ((sysRequired <= sysSpace) && (devRequired <= devSpace))
214 // Scales the width and height such that the overall texture fits into
215 // the available space for both system and device.
216 GLdouble scale = sqrt(sysSpace / GLdouble(sysRequired));
219 GLdouble devScale = sqrt(devSpace / GLdouble(devRequired));
220 scale = de::min(devScale, scale);
222 int newWidth = int(width * scale);
223 int newHeight = int(height * scale);
225 m_context.getTestContext().getLog()
226 << tcu::TestLog::Message << "Reducing surface dimensions to fit in memory, from " << width << "x" << height
227 << " to " << newWidth << "x" << newHeight << "." << tcu::TestLog::EndMessage;
233 inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon)
235 if (fabs(c0[0] - c1[0]) > epsilon[0])
237 if (fabs(c0[1] - c1[1]) > epsilon[1])
239 if (fabs(c0[2] - c1[2]) > epsilon[2])
241 if (fabs(c0[3] - c1[3]) > epsilon[3])
246 bool IsEqual(vec4 a, vec4 b)
248 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
251 bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat)
253 if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM)
255 return ColorEqual(v0, v1, vec4(0.0001f));
257 else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM)
259 return ColorEqual(v0, v1, vec4(0.01f));
261 return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
264 bool Equal(const ivec4& a, const ivec4& b, GLenum)
266 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
269 bool Equal(const uvec4& a, const uvec4& b, GLenum)
271 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
275 std::string ToString(T v)
277 std::ostringstream s;
279 for (int i = 0; i < 4; ++i)
280 s << v[i] << (i == 3 ? "" : ",");
285 bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected)
288 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
289 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat();
290 vec4 g_color_eps = vec4(
291 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
292 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
294 std::vector<vec4> fb(w * h);
295 glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
297 for (int yy = 0; yy < h; ++yy)
299 for (int xx = 0; xx < w; ++xx)
301 const int idx = yy * w + xx;
302 if (!ColorEqual(fb[idx], expected, g_color_eps))
304 m_context.getTestContext().getLog()
305 << tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
306 << tcu::TestLog::EndMessage;
315 bool CompileShader(GLuint shader)
317 glCompileShader(shader);
320 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
321 if (status == GL_FALSE)
325 glGetShaderInfoLog(shader, sizeof(log), &length, log);
328 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
329 << log << tcu::TestLog::EndMessage;
336 bool LinkProgram(GLuint program)
338 glLinkProgram(program);
341 glGetProgramiv(program, GL_LINK_STATUS, &status);
342 if (status == GL_FALSE)
346 glGetProgramInfoLog(program, sizeof(log), &length, log);
349 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
350 << log << tcu::TestLog::EndMessage;
357 GLuint BuildProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs,
358 const char* src_fs, bool* result = NULL)
360 const GLuint p = glCreateProgram();
364 GLuint sh = glCreateShader(GL_VERTEX_SHADER);
365 glAttachShader(p, sh);
367 glShaderSource(sh, 1, &src_vs, NULL);
368 if (!CompileShader(sh))
370 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
378 GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
379 glAttachShader(p, sh);
381 glShaderSource(sh, 1, &src_tcs, NULL);
382 if (!CompileShader(sh))
384 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
392 GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
393 glAttachShader(p, sh);
395 glShaderSource(sh, 1, &src_tes, NULL);
396 if (!CompileShader(sh))
398 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
406 GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
407 glAttachShader(p, sh);
409 glShaderSource(sh, 1, &src_gs, NULL);
410 if (!CompileShader(sh))
412 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
420 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
421 glAttachShader(p, sh);
423 glShaderSource(sh, 1, &src_fs, NULL);
424 if (!CompileShader(sh))
426 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
435 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
437 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
439 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
441 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
443 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
452 GLuint BuildShaderProgram(GLenum type, const char* src)
454 const GLuint p = glCreateShaderProgramv(type, 1, &src);
457 glGetProgramiv(p, GL_LINK_STATUS, &status);
458 if (status == GL_FALSE)
461 glGetProgramInfoLog(p, sizeof(log), NULL, log);
462 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
464 << src << tcu::TestLog::EndMessage;
470 void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo)
474 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
476 -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,
477 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,
478 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,
480 glGenBuffers(1, vbo);
481 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
482 glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
483 glBindBuffer(GL_ARRAY_BUFFER, 0);
487 std::vector<GLushort> index_data(4);
488 for (int i = 0; i < 4; ++i)
490 index_data[i] = static_cast<GLushort>(i);
492 glGenBuffers(1, ebo);
493 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
494 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
495 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
498 glGenVertexArrays(1, vao);
499 glBindVertexArray(*vao);
500 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
501 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
502 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2));
503 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5));
504 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8));
505 glBindBuffer(GL_ARRAY_BUFFER, 0);
506 glEnableVertexAttribArray(0);
507 glEnableVertexAttribArray(1);
508 glEnableVertexAttribArray(2);
509 glEnableVertexAttribArray(3);
512 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
514 glBindVertexArray(0);
517 std::string FormatEnumToString(GLenum e)
529 case GL_R11F_G11F_B10F:
530 return "r11f_g11f_b10f";
591 case GL_RGBA16_SNORM:
592 return "rgba16_snorm";
594 return "rgba8_snorm";
609 const char* StageName(int stage)
614 return "Vertex Shader";
616 return "Tessellation Control Shader";
618 return "Tessellation Evaluation Shader";
620 return "Geometry Shader";
622 return "Compute Shader";
628 template <typename T>
631 template <typename T>
634 template <typename T>
635 std::string TypePrefix();
637 template <typename T>
638 GLenum ImageType(GLenum target);
640 void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color)
642 glClearBufferfv(buffer, drawbuffer, &color[0]);
645 void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color)
647 glClearBufferiv(buffer, drawbuffer, &color[0]);
650 void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color)
652 glClearBufferuiv(buffer, drawbuffer, &color[0]);
655 bool CheckUniform(GLuint program, const std::string& name, const std::map<std::string, GLuint>& name_index_map,
656 GLint size, GLenum type)
658 std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name);
659 assert(iter != name_index_map.end());
666 glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl);
668 if (std::string(name_gl) != name)
670 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl
671 << " should be " << name << tcu::TestLog::EndMessage;
674 if (length_gl != static_cast<GLsizei>(name.length()))
676 m_context.getTestContext().getLog()
677 << tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl
678 << ")" << tcu::TestLog::EndMessage;
683 m_context.getTestContext().getLog()
684 << tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl
685 << ")" << tcu::TestLog::EndMessage;
690 m_context.getTestContext().getLog()
691 << tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl
692 << ")" << tcu::TestLog::EndMessage;
699 bool CheckMax(GLenum pname, GLint min_value)
707 glGetIntegerv(pname, &i);
711 glGetBooleanv(pname, &b);
712 if (b != (i ? GL_TRUE : GL_FALSE))
715 glGetFloatv(pname, &f);
716 if (static_cast<GLint>(f) < min_value)
719 glGetDoublev(pname, &d);
720 if (static_cast<GLint>(d) < min_value)
723 glGetInteger64v(pname, &i64);
724 if (static_cast<GLint>(i64) < min_value)
730 bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
736 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
737 if (static_cast<GLuint>(i) != texture)
739 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
740 << " should be " << texture << tcu::TestLog::EndMessage;
743 glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b);
744 if (b != (i ? GL_TRUE : GL_FALSE))
746 m_context.getTestContext().getLog()
747 << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be "
748 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
752 glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
755 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
756 << " should be " << level << tcu::TestLog::EndMessage;
759 glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b);
760 if (b != (i ? GL_TRUE : GL_FALSE))
762 m_context.getTestContext().getLog()
763 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be "
764 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
768 glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
771 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
772 << " should be " << layered << tcu::TestLog::EndMessage;
775 glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
776 if (b != (i ? GL_TRUE : GL_FALSE))
778 m_context.getTestContext().getLog()
779 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be "
780 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
784 glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
787 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
788 << " should be " << layer << tcu::TestLog::EndMessage;
791 glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b);
792 if (b != (i ? GL_TRUE : GL_FALSE))
794 m_context.getTestContext().getLog()
795 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be "
796 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
800 glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
801 if (static_cast<GLenum>(i) != access)
803 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
804 << " should be " << access << tcu::TestLog::EndMessage;
807 glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b);
808 if (b != (i ? GL_TRUE : GL_FALSE))
810 m_context.getTestContext().getLog()
811 << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be "
812 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
816 glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
817 if (static_cast<GLenum>(i) != format)
819 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
820 << " should be " << format << tcu::TestLog::EndMessage;
823 glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b);
824 if (b != (i ? GL_TRUE : GL_FALSE))
826 m_context.getTestContext().getLog()
827 << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be "
828 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
834 const char* EnumToString(GLenum e)
839 return "GL_TEXTURE_1D";
841 return "GL_TEXTURE_2D";
843 return "GL_TEXTURE_3D";
844 case GL_TEXTURE_RECTANGLE:
845 return "GL_TEXTURE_RECTANGLE";
846 case GL_TEXTURE_CUBE_MAP:
847 return "GL_TEXTURE_CUBE_MAP";
848 case GL_TEXTURE_1D_ARRAY:
849 return "GL_TEXTURE_1D_ARRAY";
850 case GL_TEXTURE_2D_ARRAY:
851 return "GL_TEXTURE_2D_ARRAY";
852 case GL_TEXTURE_CUBE_MAP_ARRAY:
853 return "GL_TEXTURE_CUBE_MAP_ARRAY";
864 GLenum ShaderImageLoadStoreBase::Format<vec4>()
870 GLenum ShaderImageLoadStoreBase::Format<ivec4>()
872 return GL_RGBA_INTEGER;
876 GLenum ShaderImageLoadStoreBase::Format<uvec4>()
878 return GL_RGBA_INTEGER;
882 GLenum ShaderImageLoadStoreBase::Format<GLint>()
884 return GL_RED_INTEGER;
888 GLenum ShaderImageLoadStoreBase::Format<GLuint>()
890 return GL_RED_INTEGER;
894 GLenum ShaderImageLoadStoreBase::Type<vec4>()
900 GLenum ShaderImageLoadStoreBase::Type<ivec4>()
906 GLenum ShaderImageLoadStoreBase::Type<uvec4>()
908 return GL_UNSIGNED_INT;
912 GLenum ShaderImageLoadStoreBase::Type<GLint>()
918 GLenum ShaderImageLoadStoreBase::Type<GLuint>()
920 return GL_UNSIGNED_INT;
924 std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
930 std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
936 std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
942 std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
948 std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
954 GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
964 case GL_TEXTURE_RECTANGLE:
965 return GL_IMAGE_2D_RECT;
966 case GL_TEXTURE_CUBE_MAP:
967 return GL_IMAGE_CUBE;
968 case GL_TEXTURE_BUFFER:
969 return GL_IMAGE_BUFFER;
970 case GL_TEXTURE_1D_ARRAY:
971 return GL_IMAGE_1D_ARRAY;
972 case GL_TEXTURE_2D_ARRAY:
973 return GL_IMAGE_2D_ARRAY;
974 case GL_TEXTURE_CUBE_MAP_ARRAY:
975 return GL_IMAGE_CUBE_MAP_ARRAY;
976 case GL_TEXTURE_2D_MULTISAMPLE:
977 return GL_IMAGE_2D_MULTISAMPLE;
978 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
979 return GL_IMAGE_2D_MULTISAMPLE_ARRAY;
986 GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
991 return GL_INT_IMAGE_1D;
993 return GL_INT_IMAGE_2D;
995 return GL_INT_IMAGE_3D;
996 case GL_TEXTURE_RECTANGLE:
997 return GL_INT_IMAGE_2D_RECT;
998 case GL_TEXTURE_CUBE_MAP:
999 return GL_INT_IMAGE_CUBE;
1000 case GL_TEXTURE_BUFFER:
1001 return GL_INT_IMAGE_BUFFER;
1002 case GL_TEXTURE_1D_ARRAY:
1003 return GL_INT_IMAGE_1D_ARRAY;
1004 case GL_TEXTURE_2D_ARRAY:
1005 return GL_INT_IMAGE_2D_ARRAY;
1006 case GL_TEXTURE_CUBE_MAP_ARRAY:
1007 return GL_INT_IMAGE_CUBE_MAP_ARRAY;
1008 case GL_TEXTURE_2D_MULTISAMPLE:
1009 return GL_INT_IMAGE_2D_MULTISAMPLE;
1010 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1011 return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1018 GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
1023 return GL_UNSIGNED_INT_IMAGE_1D;
1025 return GL_UNSIGNED_INT_IMAGE_2D;
1027 return GL_UNSIGNED_INT_IMAGE_3D;
1028 case GL_TEXTURE_RECTANGLE:
1029 return GL_UNSIGNED_INT_IMAGE_2D_RECT;
1030 case GL_TEXTURE_CUBE_MAP:
1031 return GL_UNSIGNED_INT_IMAGE_CUBE;
1032 case GL_TEXTURE_BUFFER:
1033 return GL_UNSIGNED_INT_IMAGE_BUFFER;
1034 case GL_TEXTURE_1D_ARRAY:
1035 return GL_UNSIGNED_INT_IMAGE_1D_ARRAY;
1036 case GL_TEXTURE_2D_ARRAY:
1037 return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
1038 case GL_TEXTURE_CUBE_MAP_ARRAY:
1039 return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
1040 case GL_TEXTURE_2D_MULTISAMPLE:
1041 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
1042 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1043 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1049 //-----------------------------------------------------------------------------
1050 // 1.1.1 BasicAPIGet
1051 //-----------------------------------------------------------------------------
1052 class BasicAPIGet : public ShaderImageLoadStoreBase
1056 if (!CheckMax(GL_MAX_IMAGE_UNITS, 8))
1058 m_context.getTestContext().getLog()
1059 << tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
1062 if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8))
1064 m_context.getTestContext().getLog()
1065 << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
1066 << tcu::TestLog::EndMessage;
1069 if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0))
1071 m_context.getTestContext().getLog()
1072 << tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage;
1075 if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
1077 m_context.getTestContext().getLog()
1078 << tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
1079 << tcu::TestLog::EndMessage;
1082 if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0))
1084 m_context.getTestContext().getLog()
1085 << tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid."
1086 << tcu::TestLog::EndMessage;
1089 if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0))
1091 m_context.getTestContext().getLog()
1092 << tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid."
1093 << tcu::TestLog::EndMessage;
1096 if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0))
1098 m_context.getTestContext().getLog()
1099 << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid."
1100 << tcu::TestLog::EndMessage;
1103 if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8))
1105 m_context.getTestContext().getLog()
1106 << tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
1107 << tcu::TestLog::EndMessage;
1110 if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8))
1112 m_context.getTestContext().getLog()
1113 << tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
1114 << tcu::TestLog::EndMessage;
1120 //-----------------------------------------------------------------------------
1121 // 1.1.2 BasicAPIBind
1122 //-----------------------------------------------------------------------------
1123 class BasicAPIBind : public ShaderImageLoadStoreBase
1127 virtual long Setup()
1135 for (GLuint index = 0; index < 8; ++index)
1137 if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8))
1139 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
1140 << " has invalid default state." << tcu::TestLog::EndMessage;
1145 glGenTextures(1, &m_texture);
1146 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
1147 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL);
1148 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL);
1149 glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL);
1150 glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL);
1151 glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL);
1152 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1154 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
1155 if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
1158 glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
1159 if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
1162 glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16);
1163 if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16))
1166 glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
1167 if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
1170 glDeleteTextures(1, &m_texture);
1173 for (GLuint index = 0; index < 8; ++index)
1176 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
1179 m_context.getTestContext().getLog()
1180 << tcu::TestLog::Message << "Binding point " << index
1181 << " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
1189 virtual long Cleanup()
1191 glDeleteTextures(1, &m_texture);
1195 //-----------------------------------------------------------------------------
1196 // 1.1.3 BasicAPIBarrier
1197 //-----------------------------------------------------------------------------
1198 class BasicAPIBarrier : public ShaderImageLoadStoreBase
1202 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
1203 glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
1204 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
1205 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1206 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1207 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1208 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1209 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1210 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1211 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1212 glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1213 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1215 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1216 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1217 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1218 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
1220 glMemoryBarrier(GL_ALL_BARRIER_BITS);
1225 //-----------------------------------------------------------------------------
1226 // 1.1.4 BasicAPITexParam
1227 //-----------------------------------------------------------------------------
1228 class BasicAPITexParam : public ShaderImageLoadStoreBase
1232 virtual long Setup()
1240 glGenTextures(1, &m_texture);
1241 glBindTexture(GL_TEXTURE_2D, m_texture);
1242 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL);
1248 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1249 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1251 m_context.getTestContext().getLog()
1252 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1253 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1254 << tcu::TestLog::EndMessage;
1257 glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1258 if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1260 m_context.getTestContext().getLog()
1261 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1262 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1263 << tcu::TestLog::EndMessage;
1266 glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1267 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1269 m_context.getTestContext().getLog()
1270 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1271 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1272 << tcu::TestLog::EndMessage;
1275 glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui);
1276 if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1278 m_context.getTestContext().getLog()
1279 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1280 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1281 << tcu::TestLog::EndMessage;
1288 virtual long Cleanup()
1290 glDeleteTextures(1, &m_texture);
1294 //-----------------------------------------------------------------------------
1295 // 1.2.1 BasicAllFormatsStore
1296 //-----------------------------------------------------------------------------
1297 class BasicAllFormatsStore : public ShaderImageLoadStoreBase
1302 virtual long Setup()
1311 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1313 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1315 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1317 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1320 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1322 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1324 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1327 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1329 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1331 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1334 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1337 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1339 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1341 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1344 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1346 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1348 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1351 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1353 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1355 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1357 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1360 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1362 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1364 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1367 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1369 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1371 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1374 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1376 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1378 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1380 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1383 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1385 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1387 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1390 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1392 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1394 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1397 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1399 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1401 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1407 template <typename T>
1408 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1410 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1411 " gl_Position = i_position;" NL "}";
1412 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
1413 const int kSize = 16;
1414 std::vector<T> data(kSize * kSize);
1416 glGenTextures(1, &texture);
1418 for (GLuint unit = 0; unit < 8; ++unit)
1420 glBindTexture(GL_TEXTURE_2D, texture);
1421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1423 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1424 glBindTexture(GL_TEXTURE_2D, 0);
1426 glViewport(0, 0, kSize, kSize);
1427 glUseProgram(program);
1428 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1429 glBindVertexArray(m_vao);
1430 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1432 glBindTexture(GL_TEXTURE_2D, texture);
1433 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1434 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
1436 for (int i = 0; i < kSize * kSize; ++i)
1438 if (!Equal(data[i], expected_value, internalformat))
1440 glDeleteTextures(1, &texture);
1442 glDeleteProgram(program);
1443 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i])
1444 << ". Value should be: " << ToString(expected_value)
1445 << ". Format is: " << FormatEnumToString(internalformat)
1446 << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1453 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1457 glDeleteTextures(1, &texture);
1459 glDeleteProgram(program);
1464 virtual long Cleanup()
1466 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1467 glDeleteVertexArrays(1, &m_vao);
1468 glDeleteBuffers(1, &m_vbo);
1472 template <typename T>
1473 std::string GenFS(GLenum internalformat, const T& value)
1475 std::ostringstream os;
1476 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1477 << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1478 " imageStore(g_image, coord, "
1479 << TypePrefix<T>() << "vec4" << value << ");" NL " discard;" NL "}";
1483 //-----------------------------------------------------------------------------
1484 // 1.2.2 BasicAllFormatsLoad
1485 //-----------------------------------------------------------------------------
1486 class BasicAllFormatsLoad : public ShaderImageLoadStoreBase
1491 virtual long Setup()
1500 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1502 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1504 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1506 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1509 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1511 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1513 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1516 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1518 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1520 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1523 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1526 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1528 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1530 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1533 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1535 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1537 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1540 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1542 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1544 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1546 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1549 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1551 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1553 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1556 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1558 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1560 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1563 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1565 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1567 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1569 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1572 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1574 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1576 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1579 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1581 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1583 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1586 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1588 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1590 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1596 template <typename T>
1597 bool Read(GLenum internalformat, const T& value, const T& expected_value)
1599 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1600 " gl_Position = i_position;" NL "}";
1601 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
1602 const int kSize = 16;
1603 std::vector<T> data(kSize * kSize, value);
1605 glGenTextures(1, &texture);
1607 for (GLuint unit = 0; unit < 8; ++unit)
1609 glBindTexture(GL_TEXTURE_2D, texture);
1610 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1611 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1612 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1613 glBindTexture(GL_TEXTURE_2D, 0);
1615 glViewport(0, 0, kSize, kSize);
1616 glClear(GL_COLOR_BUFFER_BIT);
1617 glUseProgram(program);
1618 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1619 glBindVertexArray(m_vao);
1620 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1622 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
1624 glDeleteTextures(1, &texture);
1626 glDeleteProgram(program);
1627 m_context.getTestContext().getLog()
1628 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
1629 << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1635 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1639 glDeleteTextures(1, &texture);
1641 glDeleteProgram(program);
1646 virtual long Cleanup()
1648 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1649 glDeleteVertexArrays(1, &m_vao);
1650 glDeleteBuffers(1, &m_vbo);
1654 template <typename T>
1655 std::string GenFS(GLenum internalformat, const T& expected_value)
1657 std::ostringstream os;
1658 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
1659 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
1660 << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
1661 << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
1663 << ") 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 "}";
1667 //-----------------------------------------------------------------------------
1668 // 1.2.3 BasicAllFormatsStoreGeometryStages
1669 //-----------------------------------------------------------------------------
1670 class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase
1674 virtual long Setup()
1676 glGenVertexArrays(1, &m_vao);
1682 if (!SupportedInGeomStages(1))
1683 return NOT_SUPPORTED;
1684 glEnable(GL_RASTERIZER_DISCARD);
1686 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1688 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1690 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1693 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1695 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1697 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1700 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1702 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1704 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1707 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1710 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1712 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1714 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1717 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1719 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1721 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1724 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1726 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1728 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1730 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1733 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1735 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1737 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1740 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1742 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1744 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1747 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1749 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1751 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1753 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1756 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1758 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1760 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1763 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1765 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1767 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1770 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1772 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1774 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1780 template <typename T>
1781 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1783 const GLuint program =
1784 BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(),
1785 GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL);
1786 const int kSize = 1;
1787 std::vector<T> data(kSize * kSize);
1789 glGenTextures(4, texture);
1791 for (int i = 0; i < 4; ++i)
1793 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1794 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1795 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1796 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1798 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1800 glUseProgram(program);
1801 glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1802 glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1803 glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1804 glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1805 for (GLuint i = 0; i < 4; ++i)
1807 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1809 glBindVertexArray(m_vao);
1810 glPatchParameteri(GL_PATCH_VERTICES, 1);
1811 glDrawArrays(GL_PATCHES, 0, 1);
1812 glPatchParameteri(GL_PATCH_VERTICES, 3);
1814 for (int i = 0; i < 4; ++i)
1816 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1817 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1818 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
1820 if (!Equal(data[0], expected_value, internalformat))
1822 glDeleteTextures(4, texture);
1824 glDeleteProgram(program);
1825 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0])
1826 << ". Value should be: " << ToString(expected_value)
1827 << ". Format is: " << FormatEnumToString(internalformat)
1828 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
1832 glDeleteTextures(4, texture);
1834 glDeleteProgram(program);
1838 virtual long Cleanup()
1840 glDisable(GL_RASTERIZER_DISCARD);
1841 glDeleteVertexArrays(1, &m_vao);
1845 template <typename T>
1846 std::string GenVS(GLenum internalformat, const T& value)
1848 std::ostringstream os;
1849 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1850 << TypePrefix<T>() << "image2DArray g_image0;" NL "void main() {" NL
1851 " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " imageStore(g_image0, coord, "
1852 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1856 template <typename T>
1857 std::string GenTCS(GLenum internalformat, const T& value)
1859 std::ostringstream os;
1860 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
1861 << ") writeonly uniform " << TypePrefix<T>()
1862 << "image2DArray g_image1;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
1863 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
1864 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
1865 " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " imageStore(g_image1, coord, "
1866 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1870 template <typename T>
1871 std::string GenTES(GLenum internalformat, const T& value)
1873 std::ostringstream os;
1874 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
1875 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1876 << "image2DArray g_image2;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL
1877 " imageStore(g_image2, coord, "
1878 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1882 template <typename T>
1883 std::string GenGS(GLenum internalformat, const T& value)
1885 std::ostringstream os;
1886 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
1887 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1888 << "image2DArray g_image3;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL
1889 " imageStore(g_image3, coord, "
1890 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1894 //-----------------------------------------------------------------------------
1895 // 1.2.4 BasicAllFormatsLoadGeometryStages
1896 //-----------------------------------------------------------------------------
1897 class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase
1901 virtual long Setup()
1903 glGenVertexArrays(1, &m_vao);
1909 if (!SupportedInGeomStages(2))
1910 return NOT_SUPPORTED;
1911 glEnable(GL_RASTERIZER_DISCARD);
1913 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1915 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1917 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1920 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1922 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1924 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1927 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1929 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1931 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1934 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1937 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1939 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1941 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1944 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1946 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1948 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1951 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1953 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1955 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1957 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1960 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1962 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1964 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1967 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1969 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1971 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1974 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1976 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1978 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1980 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1983 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1985 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1987 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1990 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1992 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1994 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1997 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1999 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2001 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2007 template <typename T>
2008 bool Read(GLenum internalformat, const T& value, const T& expected_value)
2010 const GLuint program = BuildProgram(
2011 GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(),
2012 GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL);
2013 const int kSize = 1;
2014 std::vector<T> data(kSize * kSize, value);
2016 glGenTextures(8, texture);
2018 for (int i = 0; i < 4; ++i)
2020 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
2021 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2022 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2023 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
2025 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2027 for (int i = 4; i < 8; ++i)
2029 glBindTexture(GL_TEXTURE_2D, texture[i]);
2030 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2031 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2032 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero);
2034 glBindTexture(GL_TEXTURE_2D, 0);
2036 glUseProgram(program);
2037 glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
2038 glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
2039 glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
2040 glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
2041 glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4);
2042 glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5);
2043 glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6);
2044 glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7);
2046 for (GLuint i = 0; i < 4; ++i)
2048 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2050 for (GLuint i = 4; i < 8; ++i)
2052 glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
2054 glBindVertexArray(m_vao);
2055 glPatchParameteri(GL_PATCH_VERTICES, 1);
2056 glDrawArrays(GL_PATCHES, 0, 1);
2057 glPatchParameteri(GL_PATCH_VERTICES, 3);
2059 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
2060 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat();
2061 vec4 g_color_eps = vec4(
2062 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
2063 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
2065 for (int i = 0; i < 4; ++i)
2067 glBindTexture(GL_TEXTURE_2D, texture[i + 4]);
2068 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2070 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]);
2071 if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps))
2073 glDeleteTextures(8, texture);
2075 glDeleteProgram(program);
2076 m_context.getTestContext().getLog()
2077 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
2078 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
2082 glDeleteTextures(8, texture);
2084 glDeleteProgram(program);
2088 virtual long Cleanup()
2090 glDisable(GL_RASTERIZER_DISCARD);
2091 glDeleteVertexArrays(1, &m_vao);
2095 template <typename T>
2096 std::string GenVS(GLenum internalformat, const T& expected_value)
2098 std::ostringstream os;
2099 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
2101 << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL
2102 "void main() {" NL " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " "
2103 << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2104 << expected_value << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2105 " else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2109 template <typename T>
2110 std::string GenTCS(GLenum internalformat, const T& expected_value)
2112 std::ostringstream os;
2113 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
2114 << ") readonly uniform " << TypePrefix<T>()
2115 << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL
2116 "void main() {" NL " gl_TessLevelInner[0] = 1;" NL " gl_TessLevelInner[1] = 1;" NL
2117 " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL " gl_TessLevelOuter[2] = 1;" NL
2118 " gl_TessLevelOuter[3] = 1;" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " "
2119 << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2120 << expected_value << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2121 " else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2125 template <typename T>
2126 std::string GenTES(GLenum internalformat, const T& expected_value)
2128 std::ostringstream os;
2129 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
2130 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2131 << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL
2132 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " "
2133 << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2134 << expected_value << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2135 " else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2139 template <typename T>
2140 std::string GenGS(GLenum internalformat, const T& expected_value)
2142 std::ostringstream os;
2143 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
2144 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2145 << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL
2146 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL " "
2147 << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2148 << expected_value << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2149 " else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2153 //-----------------------------------------------------------------------------
2154 // 1.2.5 BasicAllFormatsLoadStoreComputeStage
2155 //-----------------------------------------------------------------------------
2156 class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
2160 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
2162 m_context.getTestContext().getLog()
2163 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
2164 << tcu::TestLog::EndMessage;
2165 return NOT_SUPPORTED;
2168 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2170 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2172 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2175 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2177 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2179 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2182 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2184 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2186 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2189 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
2192 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2194 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2196 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2199 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2201 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2203 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2206 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2208 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2210 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2212 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2215 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2217 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2219 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2222 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2224 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2226 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2229 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
2231 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
2233 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2235 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2238 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
2240 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2242 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2245 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2247 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2249 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2252 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2254 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2256 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2262 template <typename T>
2263 bool Read(GLenum internalformat, const T& value, const T& expected_value)
2266 std::string source = GenCS<T>(internalformat);
2267 const char* const src = source.c_str();
2268 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
2269 glShaderSource(sh, 1, &src, NULL);
2270 glCompileShader(sh);
2271 program = glCreateProgram();
2272 glAttachShader(program, sh);
2273 glLinkProgram(program);
2276 const int kSize = 1;
2277 std::vector<T> data(kSize * kSize, value);
2279 glGenTextures(2, texture);
2281 glBindTexture(GL_TEXTURE_2D, texture[0]);
2282 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2283 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2284 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2285 glBindTexture(GL_TEXTURE_2D, texture[1]);
2286 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2287 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2289 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero);
2291 glBindTexture(GL_TEXTURE_2D, 0);
2293 glUseProgram(program);
2294 glUniform1i(glGetUniformLocation(program, "g_image_read"), 0);
2295 glUniform1i(glGetUniformLocation(program, "g_image_write"), 1);
2297 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2298 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2300 glDispatchCompute(1, 1, 1);
2302 for (int i = 0; i < 2; ++i)
2304 glBindTexture(GL_TEXTURE_2D, texture[i]);
2305 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2306 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2308 if (!Equal(data[0], expected_value, internalformat))
2310 glDeleteTextures(4, texture);
2312 glDeleteProgram(program);
2313 m_context.getTestContext().getLog()
2314 << tcu::TestLog::Message << "Value is: " << ToString(data[0])
2315 << ". Value should be: " << ToString(expected_value)
2316 << ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage;
2320 glDeleteTextures(2, texture);
2322 glDeleteProgram(program);
2326 template <typename T>
2327 std::string GenCS(GLenum internalformat)
2329 std::ostringstream os;
2330 os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL
2332 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2333 << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2334 << TypePrefix<T>() << "image2D g_image_write;" NL "void main() {" NL
2335 " ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL " "
2337 << "vec4 v = imageLoad(g_image_read, coord);" NL " imageStore(g_image_write, coord, v);" NL "}";
2341 //-----------------------------------------------------------------------------
2342 // 1.3.1 BasicAllTargetsStore
2343 //-----------------------------------------------------------------------------
2344 class BasicAllTargetsStore : public ShaderImageLoadStoreBase
2349 virtual long Setup()
2358 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2360 if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2362 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2364 if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2367 if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2369 if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2371 if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2374 if (SupportedSamples(4))
2376 if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2380 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
2383 if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2385 if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2392 virtual long Cleanup()
2394 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2395 glDeleteVertexArrays(1, &m_vao);
2396 glDeleteBuffers(1, &m_vbo);
2400 template <typename T>
2401 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
2403 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2404 " gl_Position = i_position;" NL "}";
2405 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
2408 glGenTextures(8, textures);
2409 glGenBuffers(1, &buffer);
2411 const int kSize = 16;
2412 std::vector<T> data(kSize * kSize * 2);
2414 glBindTexture(GL_TEXTURE_1D, textures[0]);
2415 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2416 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2417 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2418 glBindTexture(GL_TEXTURE_1D, 0);
2420 glBindTexture(GL_TEXTURE_2D, textures[1]);
2421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2423 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2424 glBindTexture(GL_TEXTURE_2D, 0);
2426 glBindTexture(GL_TEXTURE_3D, textures[2]);
2427 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2428 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2429 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2430 glBindTexture(GL_TEXTURE_3D, 0);
2432 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2433 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2434 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2435 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2436 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2438 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2439 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2440 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2441 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2443 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2445 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2447 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2449 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2451 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2453 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2455 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2456 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2457 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2458 glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2459 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2460 glBindTexture(GL_TEXTURE_BUFFER, 0);
2462 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2463 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2464 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2465 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2466 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2468 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2469 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2470 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2471 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2472 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2474 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2475 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2476 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2477 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2478 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2479 glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2480 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2481 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2483 glUseProgram(program);
2484 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2485 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2486 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2487 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2488 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
2489 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
2490 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
2491 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
2493 glBindVertexArray(m_vao);
2494 glViewport(0, 0, kSize, kSize);
2495 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2499 glBindTexture(GL_TEXTURE_1D, textures[0]);
2500 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2501 glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]);
2502 glBindTexture(GL_TEXTURE_1D, 0);
2503 for (int i = 0; i < kSize; ++i)
2505 if (!tcu::allEqual(data[i], expected_value))
2508 m_context.getTestContext().getLog()
2509 << tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i])
2510 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2514 std::fill(data.begin(), data.end(), T(0));
2516 glBindTexture(GL_TEXTURE_2D, textures[1]);
2517 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2518 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2519 glBindTexture(GL_TEXTURE_2D, 0);
2520 for (int i = 0; i < kSize * kSize; ++i)
2522 if (!tcu::allEqual(data[i], expected_value))
2525 m_context.getTestContext().getLog()
2526 << tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i])
2527 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2532 glBindTexture(GL_TEXTURE_3D, textures[2]);
2533 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2534 glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]);
2535 glBindTexture(GL_TEXTURE_3D, 0);
2536 for (int i = 0; i < kSize * kSize * 2; ++i)
2538 if (!tcu::allEqual(data[i], expected_value))
2541 m_context.getTestContext().getLog()
2542 << tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i])
2543 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2548 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2549 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2550 glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]);
2551 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2552 for (int i = 0; i < kSize * kSize; ++i)
2554 if (!tcu::allEqual(data[i], expected_value))
2557 m_context.getTestContext().getLog()
2558 << tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i])
2559 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2565 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2566 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2567 for (int face = 0; face < 6; ++face)
2569 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
2570 for (int i = 0; i < kSize * kSize; ++i)
2572 if (!tcu::allEqual(data[i], expected_value))
2575 m_context.getTestContext().getLog()
2576 << tcu::TestLog::Message
2577 << "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i])
2578 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2583 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2586 glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2587 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2588 glBindTexture(GL_TEXTURE_BUFFER, 0);
2589 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2590 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]);
2591 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2592 for (int i = 0; i < kSize; ++i)
2594 if (!tcu::allEqual(data[i], expected_value))
2597 m_context.getTestContext().getLog()
2598 << tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i])
2599 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2604 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2605 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2606 glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2607 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2608 for (int i = 0; i < kSize * 2; ++i)
2610 if (!tcu::allEqual(data[i], expected_value))
2613 m_context.getTestContext().getLog()
2614 << tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i])
2615 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2620 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2621 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2622 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2623 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2624 for (int i = 0; i < kSize * kSize * 2; ++i)
2626 if (!tcu::allEqual(data[i], expected_value))
2629 m_context.getTestContext().getLog()
2630 << tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i])
2631 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2637 glDeleteProgram(program);
2638 glDeleteTextures(8, textures);
2639 glDeleteBuffers(1, &buffer);
2644 template <typename T>
2645 bool WriteMS(GLenum internalformat, const T& write_value, const T& expected_value)
2648 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2649 " gl_Position = i_position;" NL "}";
2650 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str());
2651 const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str());
2653 glGenTextures(2, textures);
2655 const int kSize = 16;
2657 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2658 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
2659 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
2661 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2662 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
2663 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
2665 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2666 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2668 glClear(GL_COLOR_BUFFER_BIT);
2669 glUseProgram(program);
2670 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
2671 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
2673 glBindVertexArray(m_vao);
2674 glViewport(0, 0, kSize, kSize);
2675 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2679 glActiveTexture(GL_TEXTURE0);
2680 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2681 glActiveTexture(GL_TEXTURE1);
2682 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2684 glUseProgram(val_program);
2685 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0);
2686 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1);
2688 glBindVertexArray(m_vao);
2689 glViewport(0, 0, kSize, kSize);
2690 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2691 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2693 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2696 m_context.getTestContext().getLog()
2697 << tcu::TestLog::Message
2698 << "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed."
2699 << tcu::TestLog::EndMessage;
2702 glActiveTexture(GL_TEXTURE0);
2703 glDeleteTextures(2, textures);
2705 glDeleteProgram(program);
2706 glDeleteProgram(val_program);
2711 template <typename T>
2712 bool WriteCubeArray(GLenum internalformat, const T& write_value, const T& expected_value)
2714 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2715 " gl_Position = i_position;" NL "}";
2716 const GLuint program =
2717 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str());
2719 glGenTextures(1, textures);
2721 const int kSize = 16;
2723 std::vector<T> data(kSize * kSize * 12);
2724 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2725 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2726 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
2728 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2730 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2732 glUseProgram(program);
2733 glBindVertexArray(m_vao);
2734 glViewport(0, 0, kSize, kSize);
2735 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2739 std::fill(data.begin(), data.end(), T(0));
2740 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2741 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2742 glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2743 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2744 for (int i = 0; i < kSize * kSize * 12; ++i)
2746 if (!tcu::allEqual(data[i], expected_value))
2749 m_context.getTestContext().getLog()
2750 << tcu::TestLog::Message
2751 << "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i])
2752 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2757 glDeleteTextures(1, textures);
2759 glDeleteProgram(program);
2764 template <typename T>
2765 std::string GenFS(GLenum internalformat, const T& write_value)
2767 std::ostringstream os;
2768 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2769 << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat)
2770 << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2771 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2772 << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2773 << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat)
2774 << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2775 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2776 << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2777 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
2778 << ") writeonly uniform " << TypePrefix<T>()
2779 << "image2DArray g_image_2darray;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2780 " imageStore(g_image_1d, coord.x, "
2781 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2d, coord, " << TypePrefix<T>()
2782 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>()
2783 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>()
2784 << "vec4" << write_value << ");" NL " imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4"
2785 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2786 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2787 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4"
2788 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4"
2789 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4"
2790 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4"
2791 << write_value << ");" NL " imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4"
2792 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4"
2793 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4"
2794 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2795 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2796 << write_value << ");" NL " discard;" NL "}";
2800 template <typename T>
2801 std::string GenFSMS(GLenum internalformat, const T& write_value)
2803 std::ostringstream os;
2804 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2805 << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat)
2806 << ") writeonly uniform " << TypePrefix<T>()
2807 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2808 " imageStore(g_image_2dms, coord, 0, "
2809 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 1, "
2810 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 2, "
2811 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 3, "
2812 << TypePrefix<T>() << "vec4" << write_value
2813 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4"
2814 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>()
2815 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 2, "
2816 << TypePrefix<T>() << "vec4" << write_value
2817 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4"
2818 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>()
2819 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 1, "
2820 << TypePrefix<T>() << "vec4" << write_value
2821 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4"
2822 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>()
2823 << "vec4" << write_value << ");" NL " discard;" NL "}";
2827 template <typename T>
2828 std::string GenFSMSVal(const T& expected_value)
2830 std::ostringstream os;
2831 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>()
2832 << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>()
2833 << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
2834 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (texelFetch(g_sampler_2dms, coord, 0) != "
2835 << TypePrefix<T>() << "vec4" << expected_value
2836 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 1) != "
2837 << TypePrefix<T>() << "vec4" << expected_value
2838 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 2) != "
2839 << TypePrefix<T>() << "vec4" << expected_value
2840 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 3) != "
2841 << TypePrefix<T>() << "vec4" << expected_value
2842 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
2843 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != "
2844 << TypePrefix<T>() << "vec4" << expected_value
2845 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2846 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != "
2847 << TypePrefix<T>() << "vec4" << expected_value
2848 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2849 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != "
2850 << TypePrefix<T>() << "vec4" << expected_value
2851 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2852 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != "
2853 << TypePrefix<T>() << "vec4" << expected_value
2854 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2855 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != "
2856 << TypePrefix<T>() << "vec4" << expected_value
2857 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2858 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != "
2859 << TypePrefix<T>() << "vec4" << expected_value
2860 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2861 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != "
2862 << TypePrefix<T>() << "vec4" << expected_value
2863 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2864 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != "
2865 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
2869 template <typename T>
2870 std::string GenFSCubeArray(GLenum internalformat, const T& write_value)
2872 std::ostringstream os;
2873 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2875 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2876 " imageStore(g_image_cube_array, ivec3(coord, 0), "
2877 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 1), "
2878 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 2), "
2879 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 3), "
2880 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 4), "
2881 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 5), "
2882 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 6), "
2883 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 7), "
2884 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 8), "
2885 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 9), "
2886 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 10), "
2887 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 11), "
2888 << TypePrefix<T>() << "vec4" << write_value << ");" NL " discard;" NL "}";
2892 //-----------------------------------------------------------------------------
2893 // 1.3.2.1 BasicAllTargetsLoadNonMS
2894 //-----------------------------------------------------------------------------
2895 class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase
2900 virtual long Setup()
2909 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2911 if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2913 if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2915 if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2918 if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2920 if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2922 if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2928 virtual long Cleanup()
2930 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2931 glDeleteVertexArrays(1, &m_vao);
2932 glDeleteBuffers(1, &m_vbo);
2936 template <typename T>
2937 bool Read(GLenum internalformat, const T& value, const T& expected_value)
2939 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2940 " gl_Position = i_position;" NL "}";
2941 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
2944 glGenTextures(7, textures);
2945 glGenBuffers(1, &buffer);
2947 const int kSize = 16;
2948 std::vector<T> data(kSize * kSize * 2, value);
2950 glBindTexture(GL_TEXTURE_1D, textures[0]);
2951 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2952 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2953 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2954 glBindTexture(GL_TEXTURE_1D, 0);
2956 glBindTexture(GL_TEXTURE_2D, textures[1]);
2957 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2958 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2959 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2960 glBindTexture(GL_TEXTURE_2D, 0);
2962 glBindTexture(GL_TEXTURE_3D, textures[2]);
2963 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2964 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2965 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2966 glBindTexture(GL_TEXTURE_3D, 0);
2968 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2969 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2970 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2971 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2972 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2974 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2975 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2976 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2977 glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
2978 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2979 glBindTexture(GL_TEXTURE_BUFFER, 0);
2981 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
2982 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2983 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2984 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2985 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2987 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
2988 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2989 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2990 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2991 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2993 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2994 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2995 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2996 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2997 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2998 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2999 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3001 glClear(GL_COLOR_BUFFER_BIT);
3003 glUseProgram(program);
3004 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3005 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3006 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3007 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3008 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3009 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3010 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3012 glBindVertexArray(m_vao);
3013 glViewport(0, 0, kSize, kSize);
3014 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3018 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3023 std::map<std::string, GLuint> name_index_map;
3025 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3029 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3030 << " should be 7." << tcu::TestLog::EndMessage;
3032 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3035 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3036 name_index_map.insert(std::make_pair(std::string(name), index));
3039 if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D)))
3041 if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D)))
3043 if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D)))
3045 if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE)))
3047 if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER)))
3049 if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY)))
3051 if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY)))
3055 glDeleteProgram(program);
3056 glDeleteTextures(7, textures);
3057 glDeleteBuffers(1, &buffer);
3062 template <typename T>
3063 bool ReadCube(GLenum internalformat, const T& value, const T& expected_value)
3065 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3066 " gl_Position = i_position;" NL "}";
3067 const GLuint program =
3068 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str());
3070 glGenTextures(2, textures);
3072 const int kSize = 16;
3073 std::vector<T> data(kSize * kSize * 12, value);
3075 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3076 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3077 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3078 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3080 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3082 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3084 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3086 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3088 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3090 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3092 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3093 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3094 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3095 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3097 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3099 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3100 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3102 glClear(GL_COLOR_BUFFER_BIT);
3104 glUseProgram(program);
3105 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3106 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3108 glBindVertexArray(m_vao);
3109 glViewport(0, 0, kSize, kSize);
3110 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3114 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3119 std::map<std::string, GLuint> name_index_map;
3121 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3125 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3126 << " should be 2." << tcu::TestLog::EndMessage;
3128 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3131 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3132 name_index_map.insert(std::make_pair(std::string(name), index));
3135 if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP)))
3137 if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY)))
3141 glDeleteProgram(program);
3142 glDeleteTextures(2, textures);
3147 template <typename T>
3148 std::string GenFS(GLenum internalformat, const T& expected_value)
3150 std::ostringstream os;
3151 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3152 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3153 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3154 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3155 << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3156 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3157 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3158 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3159 << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3160 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3161 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3162 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
3164 << "vec4 v;" NL " v = imageLoad(g_image_1d, coord.x);" NL " if (v != " << TypePrefix<T>() << "vec4"
3166 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_2d, coord);" NL " if (v != "
3167 << TypePrefix<T>() << "vec4" << expected_value
3168 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL
3170 << TypePrefix<T>() << "vec4" << expected_value
3171 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
3173 << TypePrefix<T>() << "vec4" << expected_value
3174 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_2drect, coord);" NL " if (v != "
3175 << TypePrefix<T>() << "vec4" << expected_value
3176 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_buffer, coord.x);" NL " if (v != "
3177 << TypePrefix<T>() << "vec4" << expected_value
3178 << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL
3180 << TypePrefix<T>() << "vec4" << expected_value
3181 << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL
3183 << TypePrefix<T>() << "vec4" << expected_value
3184 << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL
3186 << TypePrefix<T>() << "vec4" << expected_value
3187 << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
3189 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}";
3193 template <typename T>
3194 std::string GenFSCube(GLenum internalformat, const T& expected_value)
3196 std::ostringstream os;
3197 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3198 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3199 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3201 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3202 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
3204 << "vec4 v;" NL " v = imageLoad(g_image_cube, ivec3(coord, 0));" NL " if (v != " << TypePrefix<T>()
3205 << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
3206 " v = imageLoad(g_image_cube, ivec3(coord, 1));" NL " if (v != "
3207 << TypePrefix<T>() << "vec4" << expected_value
3208 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
3210 << TypePrefix<T>() << "vec4" << expected_value
3211 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
3213 << TypePrefix<T>() << "vec4" << expected_value
3214 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
3216 << TypePrefix<T>() << "vec4" << expected_value
3217 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube, ivec3(coord, 5));" NL
3219 << TypePrefix<T>() << "vec4" << expected_value
3220 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL
3222 << TypePrefix<T>() << "vec4" << expected_value
3223 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL
3225 << TypePrefix<T>() << "vec4" << expected_value
3226 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL
3228 << TypePrefix<T>() << "vec4" << expected_value
3229 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL
3231 << TypePrefix<T>() << "vec4" << expected_value
3232 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL
3234 << TypePrefix<T>() << "vec4" << expected_value
3235 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL
3237 << TypePrefix<T>() << "vec4" << expected_value
3238 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL
3240 << TypePrefix<T>() << "vec4" << expected_value
3241 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL
3243 << TypePrefix<T>() << "vec4" << expected_value
3244 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL
3246 << TypePrefix<T>() << "vec4" << expected_value
3247 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL
3249 << TypePrefix<T>() << "vec4" << expected_value
3250 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL
3252 << TypePrefix<T>() << "vec4" << expected_value
3253 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL
3255 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}";
3259 //-----------------------------------------------------------------------------
3260 // 1.3.2.2 BasicAllTargetsLoadMS
3261 //-----------------------------------------------------------------------------
3262 class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase
3267 virtual long Setup()
3276 if (!SupportedSamples(4))
3277 return NOT_SUPPORTED;
3279 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3281 if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
3285 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3288 if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3290 if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
3297 virtual long Cleanup()
3299 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3300 glDeleteVertexArrays(1, &m_vao);
3301 glDeleteBuffers(1, &m_vbo);
3305 template <typename T>
3306 bool ReadMS(GLenum internalformat, const T& value, const T& expected_value)
3308 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3309 " gl_Position = i_position;" NL "}";
3310 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str());
3312 glGenTextures(2, textures);
3314 const int kSize = 16;
3316 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3317 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3318 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3320 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3321 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3322 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3325 glGenFramebuffers(1, &fbo);
3326 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3327 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3328 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3329 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3330 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3331 glDrawBuffers(3, draw_buffers);
3332 ClearBuffer(GL_COLOR, 0, value);
3333 ClearBuffer(GL_COLOR, 1, value);
3334 ClearBuffer(GL_COLOR, 2, value);
3335 glDeleteFramebuffers(1, &fbo);
3337 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3338 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3340 glUseProgram(program);
3341 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3342 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3344 glClear(GL_COLOR_BUFFER_BIT);
3345 glBindVertexArray(m_vao);
3346 glViewport(0, 0, kSize, kSize);
3347 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3351 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3356 std::map<std::string, GLuint> name_index_map;
3358 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3362 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3363 << " should be 2." << tcu::TestLog::EndMessage;
3365 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3368 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3369 name_index_map.insert(std::make_pair(std::string(name), index));
3372 if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE)))
3374 if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1,
3375 ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)))
3378 glDeleteTextures(2, textures);
3380 glDeleteProgram(program);
3385 template <typename T>
3386 std::string GenFSMS(GLenum internalformat, const T& expected_value)
3388 std::ostringstream os;
3389 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3390 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3391 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3393 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3394 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (imageLoad(g_image_2dms, coord, 0) != "
3395 << TypePrefix<T>() << "vec4" << expected_value
3396 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 1) != "
3397 << TypePrefix<T>() << "vec4" << expected_value
3398 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 2) != "
3399 << TypePrefix<T>() << "vec4" << expected_value
3400 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 3) != "
3401 << TypePrefix<T>() << "vec4" << expected_value
3402 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != "
3403 << TypePrefix<T>() << "vec4" << expected_value
3404 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != "
3405 << TypePrefix<T>() << "vec4" << expected_value
3406 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != "
3407 << TypePrefix<T>() << "vec4" << expected_value
3408 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != "
3409 << TypePrefix<T>() << "vec4" << expected_value
3410 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != "
3411 << TypePrefix<T>() << "vec4" << expected_value
3412 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != "
3413 << TypePrefix<T>() << "vec4" << expected_value
3414 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != "
3415 << TypePrefix<T>() << "vec4" << expected_value
3416 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != "
3417 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
3421 //-----------------------------------------------------------------------------
3422 // 1.3.3 BasicAllTargetsAtomic
3423 //-----------------------------------------------------------------------------
3424 class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase
3429 virtual long Setup()
3438 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3440 if (!Atomic<GLint>(GL_R32I))
3442 if (!Atomic<GLuint>(GL_R32UI))
3445 if (!AtomicCube<GLint>(GL_R32I))
3447 if (!AtomicCube<GLuint>(GL_R32UI))
3451 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3452 if (SupportedSamples(4) && isamples >= 4)
3454 if (!AtomicMS<GLint>(GL_R32I))
3456 if (!AtomicMS<GLuint>(GL_R32UI))
3463 virtual long Cleanup()
3465 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3466 glDeleteVertexArrays(1, &m_vao);
3467 glDeleteBuffers(1, &m_vbo);
3471 template <typename T>
3472 bool Atomic(GLenum internalformat)
3474 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3475 " gl_Position = i_position;" NL "}";
3476 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str());
3479 glGenTextures(7, textures);
3480 glGenBuffers(1, &buffer);
3482 const int kSize = 16;
3483 std::vector<T> data(kSize * kSize * 2);
3485 glBindTexture(GL_TEXTURE_1D, textures[0]);
3486 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3487 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3488 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3489 glBindTexture(GL_TEXTURE_1D, 0);
3491 glBindTexture(GL_TEXTURE_2D, textures[1]);
3492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3493 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3494 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3495 glBindTexture(GL_TEXTURE_2D, 0);
3497 glBindTexture(GL_TEXTURE_3D, textures[2]);
3498 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3499 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3500 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3501 glBindTexture(GL_TEXTURE_3D, 0);
3503 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
3504 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3505 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3506 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3507 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
3509 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
3510 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
3511 glBindBuffer(GL_TEXTURE_BUFFER, 0);
3512 glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
3513 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
3514 glBindTexture(GL_TEXTURE_BUFFER, 0);
3516 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
3517 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3518 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3519 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3520 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
3522 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
3523 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3524 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3525 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3526 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3528 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3529 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3530 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3531 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3532 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3533 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3534 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3536 glClear(GL_COLOR_BUFFER_BIT);
3538 glUseProgram(program);
3539 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3540 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3541 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3542 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3543 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3544 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3545 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3547 glBindVertexArray(m_vao);
3548 glViewport(0, 0, kSize, 1);
3549 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3553 if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1)))
3559 glDeleteProgram(program);
3560 glDeleteTextures(7, textures);
3561 glDeleteBuffers(1, &buffer);
3566 template <typename T>
3567 bool AtomicCube(GLenum internalformat)
3569 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3570 " gl_Position = i_position;" NL "}";
3571 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str());
3573 glGenTextures(2, textures);
3575 const int kSize = 16;
3576 std::vector<T> data(kSize * kSize * 12);
3578 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3579 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3580 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3581 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3583 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3585 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3587 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3589 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3591 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3593 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3595 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3596 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3597 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3598 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3600 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3602 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3603 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3605 glClear(GL_COLOR_BUFFER_BIT);
3607 glUseProgram(program);
3608 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3609 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3611 glBindVertexArray(m_vao);
3612 glViewport(0, 0, kSize, kSize);
3613 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3617 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3623 glDeleteProgram(program);
3624 glDeleteTextures(2, textures);
3629 template <typename T>
3630 bool AtomicMS(GLenum internalformat)
3632 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3633 " gl_Position = i_position;" NL "}";
3634 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str());
3636 glGenTextures(2, textures);
3638 const int kSize = 16;
3640 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3641 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3642 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3644 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3645 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3646 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3649 glGenFramebuffers(1, &fbo);
3650 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3651 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3652 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3653 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3654 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3655 glDrawBuffers(3, draw_buffers);
3656 if (internalformat == GL_R32I)
3658 const GLint value[4] = { 0, 0, 0, 0 };
3659 glClearBufferiv(GL_COLOR, 0, value);
3660 glClearBufferiv(GL_COLOR, 1, value);
3661 glClearBufferiv(GL_COLOR, 2, value);
3665 const GLuint value[4] = { 0, 0, 0, 0 };
3666 glClearBufferuiv(GL_COLOR, 0, value);
3667 glClearBufferuiv(GL_COLOR, 1, value);
3668 glClearBufferuiv(GL_COLOR, 2, value);
3670 glDeleteFramebuffers(1, &fbo);
3672 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3673 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3675 glUseProgram(program);
3676 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3677 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3679 glClear(GL_COLOR_BUFFER_BIT);
3680 glBindVertexArray(m_vao);
3681 glViewport(0, 0, kSize, kSize);
3682 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3686 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3691 glDeleteTextures(2, textures);
3693 glDeleteProgram(program);
3698 template <typename T>
3699 std::string GenFS(GLenum internalformat)
3701 std::ostringstream os;
3702 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3703 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3704 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3705 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3706 << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3707 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3708 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3709 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3710 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3711 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3712 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3713 " ivec2 coord = ivec2(gl_FragCoord.xy);"
3715 NL " if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3716 " if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3717 " if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3718 " if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3719 " if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3720 " if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3721 " if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3722 " if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3723 " if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3725 NL " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3726 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3727 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3728 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3729 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3730 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3731 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3732 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3733 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3735 NL " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3736 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3737 " if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3738 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3739 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3740 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3741 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3742 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3744 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3746 NL " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3747 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3748 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3749 " if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3750 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3751 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3752 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3753 " if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3754 " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3756 NL " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3757 " if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3758 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3759 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3760 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3761 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3762 " if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3763 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3764 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3767 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3768 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3769 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3770 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3771 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3772 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3773 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3774 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = "
3775 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), "
3776 "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3778 NL " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3779 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3780 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3781 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3782 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3783 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3784 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3785 "1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, "
3786 "0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) "
3787 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3791 template <typename T>
3792 std::string GenFSCube(GLenum internalformat)
3794 std::ostringstream os;
3795 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3796 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3797 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3799 << "imageCube g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3800 " ivec2 coord = ivec2(gl_FragCoord.xy);"
3802 NL " if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3803 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3804 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3805 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3806 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3807 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3808 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3809 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3811 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3813 NL " if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3814 "1.0);" NL " if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, "
3815 "0.0, 1.0);" NL " if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color "
3816 "= vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicAnd(g_image_cube_array, "
3817 "ivec3(coord, 0), 0) != 4) o_color = "
3818 "vec4(1.0, 0.0, 0.0, 1.0);" NL
3819 " if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3820 " if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, "
3821 "1.0);" NL " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, "
3822 "0.0, 0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != "
3823 "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3824 " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, "
3829 template <typename T>
3830 std::string GenFSMS(GLenum internalformat)
3832 std::ostringstream os;
3833 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3834 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3835 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3837 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3838 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3839 " if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3840 " if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3841 " if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3842 " if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3843 " if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3844 " if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3845 " if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3846 " if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3847 " if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL
3848 " if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3849 "1.0);" NL " if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, "
3850 "0.0, 0.0, 1.0);" NL " if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) "
3851 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3852 " if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, "
3853 "1.0);" NL " if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, "
3854 "0.0, 0.0, 1.0);" NL " if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) "
3855 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3856 " if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, "
3857 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = "
3858 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2dms_array, "
3859 "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, "
3860 "0.0, 1.0);" NL "}";
3864 //-----------------------------------------------------------------------------
3866 //-----------------------------------------------------------------------------
3867 class LoadStoreMachine : public ShaderImageLoadStoreBase
3872 virtual long Setup()
3874 glGenVertexArrays(1, &m_vao);
3878 virtual long Cleanup()
3880 glDisable(GL_RASTERIZER_DISCARD);
3881 glDeleteVertexArrays(1, &m_vao);
3885 template <typename T>
3886 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
3888 const GLenum targets[] = { GL_TEXTURE_1D, GL_TEXTURE_2D,
3889 GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE,
3890 GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY,
3891 GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY };
3892 const int kTargets = sizeof(targets) / sizeof(targets[0]);
3893 GLuint program_store = 0;
3894 GLuint program_load = 0;
3898 BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL);
3900 BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL);
3902 else if (m_stage == 1)
3904 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3905 const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
3906 program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(),
3907 glsl_tes, NULL, NULL);
3908 program_load = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(),
3909 glsl_tes, NULL, NULL);
3911 else if (m_stage == 2)
3913 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3915 BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL);
3917 BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL);
3919 else if (m_stage == 3)
3921 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3923 BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL);
3925 BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL);
3927 else if (m_stage == 4)
3930 std::string source = GenStoreShader(m_stage, internalformat, write_value);
3931 const char* const src = source.c_str();
3932 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
3933 glShaderSource(sh, 1, &src, NULL);
3934 glCompileShader(sh);
3935 program_store = glCreateProgram();
3936 glAttachShader(program_store, sh);
3937 glLinkProgram(program_store);
3941 std::string source = GenLoadShader(m_stage, internalformat, expected_value);
3942 const char* const src = source.c_str();
3943 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
3944 glShaderSource(sh, 1, &src, NULL);
3945 glCompileShader(sh);
3946 program_load = glCreateProgram();
3947 glAttachShader(program_load, sh);
3948 glLinkProgram(program_load);
3952 GLuint textures[kTargets], texture_result;
3953 glGenTextures(kTargets, textures);
3954 glGenTextures(1, &texture_result);
3956 glBindTexture(GL_TEXTURE_2D, texture_result);
3957 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3958 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3959 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3961 for (int i = 0; i < kTargets; ++i)
3963 glBindTexture(targets[i], textures[i]);
3964 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3965 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3967 if (targets[i] == GL_TEXTURE_1D)
3969 glTexStorage1D(targets[i], 1, internalformat, 1);
3971 else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
3973 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3975 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3977 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
3979 else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3981 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3983 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
3985 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12);
3987 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
3989 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
3992 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3993 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3994 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3995 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3996 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3997 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3998 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3999 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4001 glUseProgram(program_store);
4002 glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0);
4003 glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1);
4004 glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2);
4005 glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3);
4006 glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4);
4007 glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5);
4008 glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6);
4009 glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7);
4011 glBindVertexArray(m_vao);
4012 if (m_stage == 1 || m_stage == 2)
4014 glPatchParameteri(GL_PATCH_VERTICES, 1);
4015 glDrawArrays(GL_PATCHES, 0, 1);
4016 glPatchParameteri(GL_PATCH_VERTICES, 3);
4018 else if (m_stage == 4)
4020 glDispatchCompute(1, 1, 1);
4024 glDrawArrays(GL_POINTS, 0, 1);
4028 for (int i = 0; i < kTargets; ++i)
4030 glBindTexture(targets[i], textures[i]);
4031 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4033 if (targets[i] == GL_TEXTURE_CUBE_MAP)
4035 for (int face = 0; face < 6; ++face)
4038 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
4039 if (!Equal(data, expected_value, internalformat))
4042 m_context.getTestContext().getLog()
4043 << tcu::TestLog::Message << "Value is: " << ToString(data)
4044 << ". Value should be: " << ToString(expected_value)
4045 << ". Format is: " << FormatEnumToString(internalformat)
4046 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4047 << tcu::TestLog::EndMessage;
4054 memset(&data[0], 0, sizeof(data));
4055 glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]);
4058 if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4060 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
4062 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4065 for (int j = 0; j < count; ++j)
4067 if (!Equal(data[j], expected_value, internalformat))
4070 m_context.getTestContext().getLog()
4071 << tcu::TestLog::Message << "Value is: " << ToString(data[j])
4072 << ". Value should be: " << ToString(expected_value)
4073 << ". Format is: " << FormatEnumToString(internalformat)
4074 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4075 << tcu::TestLog::EndMessage;
4080 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4081 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4082 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4083 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4084 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4085 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4086 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4087 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4089 glUseProgram(program_load);
4090 glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0);
4091 glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1);
4092 glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2);
4093 glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3);
4094 glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4);
4095 glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5);
4096 glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6);
4097 glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7);
4099 if (m_stage == 1 || m_stage == 2)
4101 glPatchParameteri(GL_PATCH_VERTICES, 1);
4102 glDrawArrays(GL_PATCHES, 0, 1);
4103 glPatchParameteri(GL_PATCH_VERTICES, 3);
4105 else if (m_stage == 4)
4107 glDispatchCompute(1, 1, 1);
4111 glDrawArrays(GL_POINTS, 0, 1);
4115 glBindTexture(GL_TEXTURE_2D, texture_result);
4116 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4117 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4118 if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4121 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4122 << ". Format is: " << FormatEnumToString(internalformat)
4123 << ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage;
4127 glDeleteProgram(program_store);
4128 glDeleteProgram(program_load);
4129 glDeleteTextures(kTargets, textures);
4130 glDeleteTextures(1, &texture_result);
4134 template <typename T>
4135 std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value)
4137 std::ostringstream os;
4138 os << "#version 420 core";
4141 os << NL "#extension GL_ARB_compute_shader : require";
4143 os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4144 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4145 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
4146 << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
4147 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4148 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4149 << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
4150 << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4151 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4152 << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat)
4153 << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform "
4154 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value
4155 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4158 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4160 else if (stage == 1)
4162 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4163 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4164 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4165 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4167 else if (stage == 2)
4169 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4170 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4172 else if (stage == 3)
4174 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4175 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4177 else if (stage == 4)
4179 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4180 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4182 os << NL " imageStore(g_image_1d, coord.x, g_value);" NL " imageStore(g_image_2d, coord, g_value);" NL
4183 " imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
4184 " imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
4185 " imageStore(g_image_2drect, coord, g_value);" NL " for (int i = 0; i < 6; ++i) {" NL
4186 " imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL " }" NL
4187 " imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL
4188 " imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL
4189 " imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
4190 " imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL
4191 " for (int i = 0; i < 6; ++i) {" NL
4192 " imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL " }" NL
4193 " for (int i = 0; i < 6; ++i) {" NL
4194 " imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL " }" NL "}";
4198 template <typename T>
4199 std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value)
4201 std::ostringstream os;
4202 os << "#version 420 core";
4205 os << NL "#extension GL_ARB_compute_shader : require";
4207 os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4208 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4209 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4210 << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4211 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4212 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4213 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
4214 << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout("
4215 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4216 << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4218 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value
4219 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4222 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4224 else if (stage == 1)
4226 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4227 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4228 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4229 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4231 else if (stage == 2)
4233 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4234 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4236 else if (stage == 3)
4238 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4239 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4241 else if (stage == 4)
4243 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4244 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4246 os << NL " vec4 r = vec4(0, 1, 0, 1);" NL " " << TypePrefix<T>()
4247 << "vec4 v;" NL " v = imageLoad(g_image_2d, coord);" NL
4248 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4249 " v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
4250 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_2drect, coord);" NL
4251 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4252 " v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
4253 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_1darray, coord);" NL
4254 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4255 " v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
4256 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4257 " v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL
4258 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " imageStore(g_image_result, coord, r);" NL "}";
4263 long RunStage(int stage)
4265 if (!SupportedInStage(stage, 8))
4266 return NOT_SUPPORTED;
4268 glEnable(GL_RASTERIZER_DISCARD);
4271 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4273 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4275 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4278 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4280 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4282 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4285 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4287 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4289 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4292 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
4295 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4297 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4299 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4302 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4304 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4306 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4309 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4311 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4313 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4315 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4318 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4320 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4322 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4325 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4327 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4329 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4332 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
4334 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
4336 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4338 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4341 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
4343 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4345 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4350 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4352 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4354 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4357 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4359 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4361 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4367 //-----------------------------------------------------------------------------
4369 //-----------------------------------------------------------------------------
4370 class AtomicMachine : public ShaderImageLoadStoreBase
4374 virtual long Setup()
4376 glEnable(GL_RASTERIZER_DISCARD);
4377 glGenVertexArrays(1, &m_vao);
4381 virtual long Cleanup()
4383 glDisable(GL_RASTERIZER_DISCARD);
4384 glDeleteVertexArrays(1, &m_vao);
4388 template <typename T>
4389 bool Atomic(int stage, GLenum internalformat)
4394 program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL);
4396 else if (stage == 1)
4398 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4399 const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
4400 program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL);
4402 else if (stage == 2)
4404 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4405 program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL);
4407 else if (stage == 3)
4409 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4410 program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL);
4412 else if (stage == 4)
4414 std::string source = GenShader<T>(stage, internalformat);
4415 const char* const src = source.c_str();
4416 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
4417 glShaderSource(sh, 1, &src, NULL);
4418 glCompileShader(sh);
4419 program = glCreateProgram();
4420 glAttachShader(program, sh);
4421 glLinkProgram(program);
4424 GLuint texture_result;
4425 glGenTextures(1, &texture_result);
4426 glBindTexture(GL_TEXTURE_2D, texture_result);
4427 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4428 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4429 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
4431 const GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP,
4432 GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY };
4433 const int kTargets = sizeof(targets) / sizeof(targets[0]);
4435 GLuint textures[kTargets];
4437 glGenTextures(kTargets, textures);
4438 glGenBuffers(1, &buffer);
4440 for (int i = 0; i < kTargets; ++i)
4442 glBindTexture(targets[i], textures[i]);
4443 if (targets[i] != GL_TEXTURE_BUFFER)
4445 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4446 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4448 if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
4450 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4452 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4454 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
4456 else if (targets[i] == GL_TEXTURE_CUBE_MAP)
4458 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4460 else if (targets[i] == GL_TEXTURE_BUFFER)
4462 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
4463 glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
4464 glBindBuffer(GL_TEXTURE_BUFFER, 0);
4465 glTexBuffer(targets[i], internalformat, buffer);
4467 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4469 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
4472 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4473 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4474 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4475 glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4476 glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4477 glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4478 glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4479 glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4481 glUseProgram(program);
4482 glUniform1i(glGetUniformLocation(program, "g_image_result"), 0);
4483 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
4484 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
4485 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
4486 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
4487 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
4488 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
4489 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
4491 glBindVertexArray(m_vao);
4492 if (stage == 1 || stage == 2)
4494 glPatchParameteri(GL_PATCH_VERTICES, 1);
4495 glDrawArrays(GL_PATCHES, 0, 1);
4496 glPatchParameteri(GL_PATCH_VERTICES, 3);
4498 else if (stage == 4)
4500 glDispatchCompute(1, 1, 1);
4504 glDrawArrays(GL_POINTS, 0, 1);
4510 glBindTexture(GL_TEXTURE_2D, texture_result);
4511 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4512 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4513 if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4516 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4517 << ". Format is: " << FormatEnumToString(internalformat)
4518 << ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage;
4522 glDeleteProgram(program);
4523 glDeleteTextures(7, textures);
4524 glDeleteTextures(1, &texture_result);
4525 glDeleteBuffers(1, &buffer);
4529 template <typename T>
4530 std::string GenShader(int stage, GLenum internalformat)
4532 std::ostringstream os;
4533 os << "#version 420 core";
4536 os << NL "#extension GL_ARB_compute_shader : require";
4538 os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4539 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4540 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4541 << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4542 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4543 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4544 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
4545 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4546 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4547 << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4548 "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);";
4551 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
4553 else if (stage == 1)
4555 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4556 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4557 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4558 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4560 else if (stage == 2)
4562 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4563 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4565 else if (stage == 3)
4567 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4568 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);";
4570 else if (stage == 4)
4572 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4573 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
4576 " vec4 o_color = vec4(0, 1, 0, 1);" NL " imageAtomicExchange(g_image_2d, coord, 0);" NL
4577 " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4578 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4579 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4580 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4581 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4582 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4583 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4584 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4585 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4587 NL " imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL
4588 " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4589 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4590 " if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4591 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4592 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4593 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4594 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4595 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4596 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4598 NL " imageAtomicExchange(g_image_2drect, coord, 0);" NL
4599 " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4600 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4601 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4602 " if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4603 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4604 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4605 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4606 " if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
4607 "1.0);" NL " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4609 NL " imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL " if (imageAtomicAdd(g_image_cube, "
4610 "ivec3(coord, 0), g_value[2]) != 0) "
4611 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4612 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4613 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4614 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4615 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4616 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4617 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4618 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, "
4620 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4622 NL " imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL
4623 " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4624 " if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4625 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4626 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4627 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4628 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4629 " if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4631 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4632 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4634 NL " imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL
4635 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4636 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4637 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, "
4639 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4640 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4641 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4642 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4643 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, "
4644 "0.0, 0.0, 1.0);" NL
4645 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4647 NL " imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL
4648 " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4649 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4650 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4651 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4652 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4653 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, "
4654 "1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, "
4655 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) "
4656 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4657 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4659 NL " imageStore(g_image_result, coord, o_color);" NL "}";
4664 long RunStage(int stage)
4666 if (!SupportedInStage(stage, 8))
4667 return NOT_SUPPORTED;
4668 if (!Atomic<GLint>(stage, GL_R32I))
4670 if (!Atomic<GLuint>(stage, GL_R32UI))
4675 //-----------------------------------------------------------------------------
4676 // 1.3.4 BasicAllTargetsLoadStoreVS
4677 //-----------------------------------------------------------------------------
4678 class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
4685 //-----------------------------------------------------------------------------
4686 // 1.3.5 BasicAllTargetsLoadStoreTCS
4687 //-----------------------------------------------------------------------------
4688 class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine
4695 //-----------------------------------------------------------------------------
4696 // 1.3.6 BasicAllTargetsLoadStoreTES
4697 //-----------------------------------------------------------------------------
4698 class BasicAllTargetsLoadStoreTES : public LoadStoreMachine
4705 //-----------------------------------------------------------------------------
4706 // 1.3.7 BasicAllTargetsLoadStoreGS
4707 //-----------------------------------------------------------------------------
4708 class BasicAllTargetsLoadStoreGS : public LoadStoreMachine
4715 //-----------------------------------------------------------------------------
4716 // 1.3.8 BasicAllTargetsLoadStoreCS
4717 //-----------------------------------------------------------------------------
4718 class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
4722 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4724 m_context.getTestContext().getLog()
4725 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4726 << tcu::TestLog::EndMessage;
4733 //-----------------------------------------------------------------------------
4734 // 1.3.9 BasicAllTargetsAtomicVS
4735 //-----------------------------------------------------------------------------
4736 class BasicAllTargetsAtomicVS : public AtomicMachine
4743 //-----------------------------------------------------------------------------
4744 // 1.3.10 BasicAllTargetsAtomicTCS
4745 //-----------------------------------------------------------------------------
4746 class BasicAllTargetsAtomicTCS : public AtomicMachine
4753 //-----------------------------------------------------------------------------
4754 // 1.3.11 BasicAllTargetsAtomicTES
4755 //-----------------------------------------------------------------------------
4756 class BasicAllTargetsAtomicTES : public AtomicMachine
4763 //-----------------------------------------------------------------------------
4764 // 1.3.12 BasicAllTargetsAtomicGS
4765 //-----------------------------------------------------------------------------
4766 class BasicAllTargetsAtomicGS : public AtomicMachine
4773 //-----------------------------------------------------------------------------
4774 // 1.3.13 BasicAllTargetsAtomicCS
4775 //-----------------------------------------------------------------------------
4776 class BasicAllTargetsAtomicCS : public AtomicMachine
4780 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4782 m_context.getTestContext().getLog()
4783 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4784 << tcu::TestLog::EndMessage;
4791 //-----------------------------------------------------------------------------
4792 // 1.4.1 BasicGLSLMisc
4793 //-----------------------------------------------------------------------------
4794 class BasicGLSLMisc : public ShaderImageLoadStoreBase
4798 GLuint m_vao, m_vbo;
4800 virtual long Setup()
4810 const int kSize = 32;
4811 std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f));
4813 glGenTextures(1, &m_texture);
4814 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4815 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4816 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]);
4817 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
4819 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4820 " gl_Position = i_position;" NL "}";
4821 const char* src_fs =
4822 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4823 "layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL
4824 "layout(rgba32f) volatile uniform image2D g_image_layer1;" NL
4825 "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
4826 " imageStore(g_image_layer0, coord, vec4(1.0));" NL " memoryBarrier();" NL
4827 " imageStore(g_image_layer0, coord, vec4(2.0));" NL " memoryBarrier();" NL
4828 " imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL " memoryBarrier();" NL
4829 " o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}";
4830 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs);
4832 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4834 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4835 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F);
4837 glClear(GL_COLOR_BUFFER_BIT);
4838 glViewport(0, 0, kSize, kSize);
4840 glUseProgram(m_program);
4841 glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0);
4842 glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1);
4844 glBindVertexArray(m_vao);
4845 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4847 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
4854 virtual long Cleanup()
4856 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4857 glDeleteTextures(1, &m_texture);
4858 glDeleteVertexArrays(1, &m_vao);
4859 glDeleteBuffers(1, &m_vbo);
4861 glDeleteProgram(m_program);
4865 //-----------------------------------------------------------------------------
4866 // 1.4.2 BasicGLSLEarlyFragTests
4867 //-----------------------------------------------------------------------------
4868 class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
4870 GLuint m_texture[2];
4871 GLuint m_program[2];
4872 GLuint m_vao, m_vbo;
4874 virtual long Setup()
4876 m_texture[0] = m_texture[1] = 0;
4877 m_program[0] = m_program[1] = 0;
4884 int ds = m_context.getRenderContext().getRenderTarget().getDepthBits();
4886 const int kSize = 32;
4887 std::vector<vec4> data(kSize * kSize);
4889 glGenTextures(2, m_texture);
4890 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4891 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4892 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4893 glBindTexture(GL_TEXTURE_2D, 0);
4895 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4896 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4897 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4898 glBindTexture(GL_TEXTURE_2D, 0);
4900 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4901 " gl_Position = i_position;" NL "}";
4902 const char* glsl_early_frag_tests_fs =
4903 "#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
4904 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4905 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL
4906 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4907 const char* glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4908 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4909 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL
4910 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4911 m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs);
4912 m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
4914 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4916 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4917 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4919 glViewport(0, 0, kSize, kSize);
4920 glBindVertexArray(m_vao);
4922 glEnable(GL_DEPTH_TEST);
4923 glClearColor(0.0, 1.0f, 0.0, 1.0f);
4924 glClearDepthf(0.0f);
4926 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4927 glUseProgram(m_program[0]);
4928 glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0);
4930 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4932 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4933 glUseProgram(m_program[1]);
4934 glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1);
4935 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4937 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4938 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4939 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4940 for (int i = 0; i < kSize * kSize; ++i)
4942 if (IsEqual(data[i], vec4(1.0f)) && ds != 0)
4946 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4947 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4948 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4949 for (int i = 0; i < kSize * kSize; ++i)
4951 if (!IsEqual(data[i], vec4(1.0f)) && ds != 0)
4958 virtual long Cleanup()
4960 glDisable(GL_DEPTH_TEST);
4961 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4962 glClearDepthf(1.0f);
4963 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4964 glDeleteTextures(2, m_texture);
4965 glDeleteVertexArrays(1, &m_vao);
4966 glDeleteBuffers(1, &m_vbo);
4968 glDeleteProgram(m_program[0]);
4969 glDeleteProgram(m_program[1]);
4973 //-----------------------------------------------------------------------------
4974 // 1.4.3 BasicGLSLConst
4975 //-----------------------------------------------------------------------------
4976 class BasicGLSLConst : public ShaderImageLoadStoreBase
4979 GLuint m_vao, m_vbo;
4981 virtual long Setup()
4990 bool isAtLeast44Context =
4991 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4));
4993 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4994 " gl_Position = i_position;" NL "}";
4995 std::ostringstream src_fs;
4996 src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core";
4997 src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL
4998 "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL
4999 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL
5000 "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL
5001 "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL
5002 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5003 " if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);";
5004 if (isAtLeast44Context)
5005 src_fs << NL " if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = "
5006 "vec4(0.2, 0.0, 0.0, 0.2);";
5008 src_fs << NL " if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) "
5009 "o_color = vec4(0.2, 0.0, 0.0, 0.2);";
5011 " if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
5012 " if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL
5013 " if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, "
5014 "0.5);" NL " if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, "
5015 "0.0, 0.0, 0.6);" NL
5016 " if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL
5017 " if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL
5018 " if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}";
5020 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str());
5021 glUseProgram(m_program);
5024 glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
5025 glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
5027 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
5028 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
5030 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
5031 glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i);
5033 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
5034 glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
5036 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i);
5037 glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i);
5039 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i);
5040 glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i);
5042 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i);
5043 glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i);
5045 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
5046 glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
5048 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
5049 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
5051 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5053 glClear(GL_COLOR_BUFFER_BIT);
5054 glBindVertexArray(m_vao);
5055 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5057 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5064 virtual long Cleanup()
5066 glDeleteVertexArrays(1, &m_vao);
5067 glDeleteBuffers(1, &m_vbo);
5069 glDeleteProgram(m_program);
5073 //-----------------------------------------------------------------------------
5074 // 2.1.1 AdvancedSyncImageAccess
5075 //-----------------------------------------------------------------------------
5076 class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
5079 GLuint m_buffer_tex;
5080 GLuint m_store_program;
5081 GLuint m_draw_program;
5082 GLuint m_attribless_vao;
5084 virtual long Setup()
5088 m_store_program = 0;
5090 m_attribless_vao = 0;
5096 if (!SupportedInVS(1))
5097 return NOT_SUPPORTED;
5098 const char* const glsl_store_vs =
5099 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5100 " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5101 " imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}";
5102 const char* const glsl_draw_vs =
5103 "#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL
5104 "uniform samplerBuffer g_sampler;" NL "void main() {" NL " vec4 pi = imageLoad(g_image, gl_VertexID);" NL
5105 " vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL
5106 " 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
5107 " gl_Position = pi;" NL "}";
5108 const char* const glsl_draw_fs =
5109 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5110 " o_color = vs_color;" NL "}";
5111 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5112 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5114 glGenVertexArrays(1, &m_attribless_vao);
5115 glBindVertexArray(m_attribless_vao);
5117 glGenBuffers(1, &m_buffer);
5118 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5119 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5120 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5122 glGenTextures(1, &m_buffer_tex);
5123 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5124 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer);
5126 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
5128 glEnable(GL_RASTERIZER_DISCARD);
5129 glUseProgram(m_store_program);
5130 glDrawArrays(GL_POINTS, 0, 4);
5132 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
5134 glDisable(GL_RASTERIZER_DISCARD);
5135 glClear(GL_COLOR_BUFFER_BIT);
5136 glUseProgram(m_draw_program);
5137 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5139 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5146 virtual long Cleanup()
5149 glDeleteBuffers(1, &m_buffer);
5150 glDeleteTextures(1, &m_buffer_tex);
5151 glDeleteProgram(m_store_program);
5152 glDeleteProgram(m_draw_program);
5153 glDeleteVertexArrays(1, &m_attribless_vao);
5157 //-----------------------------------------------------------------------------
5158 // 2.1.2 AdvancedSyncVertexArray
5159 //-----------------------------------------------------------------------------
5160 class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
5162 GLuint m_position_buffer;
5163 GLuint m_color_buffer;
5164 GLuint m_element_buffer;
5165 GLuint m_position_buffer_tex;
5166 GLuint m_color_buffer_tex;
5167 GLuint m_element_buffer_tex;
5168 GLuint m_store_program;
5169 GLuint m_draw_program;
5170 GLuint m_attribless_vao;
5173 virtual long Setup()
5175 m_position_buffer = 0;
5177 m_element_buffer = 0;
5178 m_position_buffer_tex = 0;
5179 m_color_buffer_tex = 0;
5180 m_element_buffer_tex = 0;
5181 m_store_program = 0;
5183 m_attribless_vao = 0;
5190 if (!SupportedInVS(3))
5191 return NOT_SUPPORTED;
5192 const char* const glsl_store_vs =
5193 "#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL
5194 "layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL
5195 "layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL
5196 "void main() {" NL " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5197 " imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL
5198 " imageStore(g_color_buffer, gl_VertexID, g_color);" NL
5199 " imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}";
5200 const char* const glsl_draw_vs =
5201 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5202 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL
5203 " gl_Position = i_position;" NL " vs_color = i_color;" NL "}";
5204 const char* const glsl_draw_fs =
5205 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5206 " o_color = vs_color;" NL "}";
5207 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5208 glUseProgram(m_store_program);
5209 glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0);
5210 glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1);
5211 glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2);
5214 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5216 glGenBuffers(1, &m_position_buffer);
5217 glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer);
5218 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5219 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5221 glGenBuffers(1, &m_color_buffer);
5222 glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer);
5223 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW);
5224 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5226 glGenBuffers(1, &m_element_buffer);
5227 glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer);
5228 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW);
5229 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5231 glGenTextures(1, &m_position_buffer_tex);
5232 glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex);
5233 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer);
5234 glBindTexture(GL_TEXTURE_BUFFER, 0);
5236 glGenTextures(1, &m_color_buffer_tex);
5237 glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex);
5238 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer);
5239 glBindTexture(GL_TEXTURE_BUFFER, 0);
5241 glGenTextures(1, &m_element_buffer_tex);
5242 glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex);
5243 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer);
5244 glBindTexture(GL_TEXTURE_BUFFER, 0);
5246 glGenVertexArrays(1, &m_attribless_vao);
5248 glGenVertexArrays(1, &m_draw_vao);
5249 glBindVertexArray(m_draw_vao);
5250 glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
5251 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5252 glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
5253 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
5254 glBindBuffer(GL_ARRAY_BUFFER, 0);
5255 glEnableVertexAttribArray(0);
5256 glEnableVertexAttribArray(1);
5257 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
5258 glBindVertexArray(0);
5260 glEnable(GL_RASTERIZER_DISCARD);
5261 glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F);
5262 glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5263 glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
5264 glUseProgram(m_store_program);
5265 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5266 glBindVertexArray(m_attribless_vao);
5267 glDrawArrays(GL_POINTS, 0, 4);
5269 glDisable(GL_RASTERIZER_DISCARD);
5270 glClear(GL_COLOR_BUFFER_BIT);
5271 glUseProgram(m_draw_program);
5272 glBindVertexArray(m_draw_vao);
5273 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5274 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5276 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5281 glEnable(GL_RASTERIZER_DISCARD);
5282 glUseProgram(m_store_program);
5283 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
5284 glBindVertexArray(m_attribless_vao);
5285 glDrawArrays(GL_POINTS, 0, 4);
5287 glDisable(GL_RASTERIZER_DISCARD);
5288 glClear(GL_COLOR_BUFFER_BIT);
5289 glUseProgram(m_draw_program);
5290 glBindVertexArray(m_draw_vao);
5291 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5292 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5294 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1)))
5301 virtual long Cleanup()
5303 glDisable(GL_RASTERIZER_DISCARD);
5305 glDeleteBuffers(1, &m_position_buffer);
5306 glDeleteBuffers(1, &m_color_buffer);
5307 glDeleteBuffers(1, &m_element_buffer);
5308 glDeleteTextures(1, &m_position_buffer_tex);
5309 glDeleteTextures(1, &m_color_buffer_tex);
5310 glDeleteTextures(1, &m_element_buffer_tex);
5311 glDeleteProgram(m_store_program);
5312 glDeleteProgram(m_draw_program);
5313 glDeleteVertexArrays(1, &m_attribless_vao);
5314 glDeleteVertexArrays(1, &m_draw_vao);
5319 //-----------------------------------------------------------------------------
5320 // 2.1.4 AdvancedSyncDrawIndirect
5321 //-----------------------------------------------------------------------------
5322 class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase
5324 GLuint m_draw_command_buffer;
5325 GLuint m_draw_command_buffer_tex;
5326 GLuint m_store_program;
5327 GLuint m_draw_program;
5328 GLuint m_attribless_vao;
5332 virtual long Setup()
5334 m_draw_command_buffer = 0;
5335 m_draw_command_buffer_tex = 0;
5336 m_store_program = 0;
5338 m_attribless_vao = 0;
5346 if (!SupportedInVS(1))
5347 return NOT_SUPPORTED;
5348 const char* const glsl_store_vs =
5349 "#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL
5350 " imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}";
5351 const char* const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5352 "void main() {" NL " gl_Position = i_position;" NL "}";
5353 const char* const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5354 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5355 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5356 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5358 glGenBuffers(1, &m_draw_command_buffer);
5359 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5360 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW);
5361 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
5363 glGenTextures(1, &m_draw_command_buffer_tex);
5364 glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex);
5365 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer);
5366 glBindTexture(GL_TEXTURE_BUFFER, 0);
5368 glGenVertexArrays(1, &m_attribless_vao);
5369 CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL);
5371 glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
5373 glEnable(GL_RASTERIZER_DISCARD);
5374 glUseProgram(m_store_program);
5375 glBindVertexArray(m_attribless_vao);
5376 glDrawArrays(GL_POINTS, 0, 1);
5378 glDisable(GL_RASTERIZER_DISCARD);
5379 glClear(GL_COLOR_BUFFER_BIT);
5380 glUseProgram(m_draw_program);
5381 glBindVertexArray(m_draw_vao);
5382 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5383 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
5384 glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0);
5386 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5393 virtual long Cleanup()
5396 glDeleteBuffers(1, &m_draw_command_buffer);
5397 glDeleteTextures(1, &m_draw_command_buffer_tex);
5398 glDeleteProgram(m_store_program);
5399 glDeleteProgram(m_draw_program);
5400 glDeleteVertexArrays(1, &m_attribless_vao);
5401 glDeleteVertexArrays(1, &m_draw_vao);
5402 glDeleteBuffers(1, &m_draw_vbo);
5406 //-----------------------------------------------------------------------------
5407 // 2.1.5 AdvancedSyncTextureUpdate
5408 //-----------------------------------------------------------------------------
5409 class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase
5412 GLuint m_store_program;
5413 GLuint m_draw_program;
5418 virtual long Setup()
5421 m_store_program = 0;
5431 const char* const glsl_vs =
5432 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5433 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5434 const char* const glsl_store_fs =
5435 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
5436 " imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL " discard;" NL "}";
5437 const char* const glsl_draw_fs =
5438 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5439 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}";
5440 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5441 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5443 std::vector<vec4> data(16 * 16, vec4(1.0f));
5444 glGenBuffers(1, &m_pbo);
5445 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5446 glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ);
5447 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5449 glGenTextures(1, &m_texture);
5450 glBindTexture(GL_TEXTURE_2D, m_texture);
5451 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5452 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
5453 glBindTexture(GL_TEXTURE_2D, 0);
5455 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5457 glViewport(0, 0, 16, 16);
5458 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5459 glUseProgram(m_store_program);
5460 glBindVertexArray(m_vao);
5461 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5463 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5464 glBindTexture(GL_TEXTURE_2D, m_texture);
5465 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
5466 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0);
5467 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5469 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5470 glClear(GL_COLOR_BUFFER_BIT);
5471 glUseProgram(m_draw_program);
5472 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5474 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1)))
5481 virtual long Cleanup()
5484 glDeleteBuffers(1, &m_vbo);
5485 glDeleteBuffers(1, &m_pbo);
5486 glDeleteTextures(1, &m_texture);
5487 glDeleteProgram(m_store_program);
5488 glDeleteProgram(m_draw_program);
5489 glDeleteVertexArrays(1, &m_vao);
5493 //-----------------------------------------------------------------------------
5494 // 2.1.6 AdvancedSyncImageAccess2
5495 //-----------------------------------------------------------------------------
5496 class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
5499 GLuint m_store_program;
5500 GLuint m_draw_program;
5504 virtual long Setup()
5507 m_store_program = 0;
5516 const char* const glsl_vs =
5517 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5518 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5519 const char* const glsl_store_fs =
5520 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
5521 " imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL " discard;" NL "}";
5522 const char* const glsl_draw_fs =
5523 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5524 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}";
5525 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5526 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5528 int width = getWindowWidth();
5529 int height = getWindowHeight();
5530 scaleDimensionsToMemory(width, height, 1, 1, 16, 16);
5532 glGenTextures(1, &m_texture);
5533 glBindTexture(GL_TEXTURE_2D, m_texture);
5534 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5535 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
5536 glBindTexture(GL_TEXTURE_2D, 0);
5538 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5540 glViewport(0, 0, width, height);
5541 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5542 glUseProgram(m_store_program);
5543 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
5544 glBindVertexArray(m_vao);
5545 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5547 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5549 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5550 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5552 glClear(GL_COLOR_BUFFER_BIT);
5553 glBindTexture(GL_TEXTURE_2D, m_texture);
5554 glUseProgram(m_draw_program);
5555 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5557 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5564 virtual long Cleanup()
5566 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5568 glDeleteBuffers(1, &m_vbo);
5569 glDeleteTextures(1, &m_texture);
5570 glDeleteProgram(m_store_program);
5571 glDeleteProgram(m_draw_program);
5572 glDeleteVertexArrays(1, &m_vao);
5576 //-----------------------------------------------------------------------------
5577 // 2.1.7 AdvancedSyncBufferUpdate
5578 //-----------------------------------------------------------------------------
5579 class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase
5582 GLuint m_buffer_tex;
5583 GLuint m_store_program;
5584 GLuint m_attribless_vao;
5586 virtual long Setup()
5590 m_store_program = 0;
5591 m_attribless_vao = 0;
5597 if (!SupportedInVS(1))
5598 return NOT_SUPPORTED;
5599 const char* const glsl_store_vs =
5600 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5601 " imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}";
5602 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5604 glGenVertexArrays(1, &m_attribless_vao);
5605 glBindVertexArray(m_attribless_vao);
5607 glGenBuffers(1, &m_buffer);
5608 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5609 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW);
5610 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5612 glGenTextures(1, &m_buffer_tex);
5613 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5614 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5616 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5618 glEnable(GL_RASTERIZER_DISCARD);
5619 glUseProgram(m_store_program);
5620 glDrawArrays(GL_POINTS, 0, 1000);
5622 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5624 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5626 reinterpret_cast<vec4*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT));
5627 for (int i = 0; i < 1000; ++i)
5629 if (!IsEqual(ptr[i], vec4(static_cast<float>(i))))
5631 m_context.getTestContext().getLog()
5632 << tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage;
5639 virtual long Cleanup()
5641 glDisable(GL_RASTERIZER_DISCARD);
5643 glDeleteBuffers(1, &m_buffer);
5644 glDeleteTextures(1, &m_buffer_tex);
5645 glDeleteProgram(m_store_program);
5646 glDeleteVertexArrays(1, &m_attribless_vao);
5650 //-----------------------------------------------------------------------------
5651 // 2.2.1 AdvancedAllStagesOneImage
5652 //-----------------------------------------------------------------------------
5653 class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
5660 GLuint m_buffer_tex;
5663 virtual long Setup()
5677 if (!SupportedInGeomStages(2))
5678 return NOT_SUPPORTED;
5679 const char* const glsl_vs =
5680 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5681 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5682 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5683 " gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL " imageAtomicAdd(g_buffer, 0, 1);" NL
5684 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5685 const char* const glsl_tcs =
5686 "#version 420 core" NL "layout(vertices = 1) out;" NL
5687 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5688 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5689 " gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL " gl_TessLevelInner[0] = 1.0;" NL
5690 " gl_TessLevelInner[1] = 1.0;" NL " gl_TessLevelOuter[0] = 1.0;" NL " gl_TessLevelOuter[1] = 1.0;" NL
5691 " gl_TessLevelOuter[2] = 1.0;" NL " gl_TessLevelOuter[3] = 1.0;" NL " imageAtomicAdd(g_buffer, 0, 1);" NL
5692 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5693 const char* const glsl_tes =
5694 "#version 420 core" NL "layout(triangles, point_mode) in;" NL
5695 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5696 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5697 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5698 " gl_Position = gl_in[0].gl_Position;" NL "}";
5699 const char* const glsl_gs =
5700 "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
5701 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5702 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5703 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5704 " gl_Position = gl_in[0].gl_Position;" NL " EmitVertex();" NL "}";
5705 const char* const glsl_fs =
5706 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5707 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5708 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5709 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5710 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5711 m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs);
5712 glUseProgram(m_program);
5713 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5714 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5716 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
5719 glGenBuffers(1, &m_buffer);
5720 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5721 glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW);
5722 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5724 glGenTextures(1, &m_buffer_tex);
5725 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5726 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer);
5727 glBindTexture(GL_TEXTURE_BUFFER, 0);
5730 glGenTextures(1, &m_texture);
5731 glBindTexture(GL_TEXTURE_2D, m_texture);
5732 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5733 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5734 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5735 glBindTexture(GL_TEXTURE_2D, 0);
5737 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5738 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5740 glBindVertexArray(m_vao);
5741 glPatchParameteri(GL_PATCH_VERTICES, 1);
5743 glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0);
5744 glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1);
5746 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5747 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5748 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32);
5749 if (i32 < 20 || i32 > 50)
5751 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32
5752 << " should be in the range [20;50]" << tcu::TestLog::EndMessage;
5756 glBindTexture(GL_TEXTURE_2D, m_texture);
5757 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5758 if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32))
5760 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be "
5761 << (2 * i32) << tcu::TestLog::EndMessage;
5768 virtual long Cleanup()
5770 glPatchParameteri(GL_PATCH_VERTICES, 3);
5772 glDeleteBuffers(1, &m_buffer);
5773 glDeleteBuffers(1, &m_vbo);
5774 glDeleteBuffers(1, &m_ebo);
5775 glDeleteTextures(1, &m_buffer_tex);
5776 glDeleteTextures(1, &m_texture);
5777 glDeleteProgram(m_program);
5778 glDeleteVertexArrays(1, &m_vao);
5782 //-----------------------------------------------------------------------------
5783 // 2.3.1 AdvancedMemoryDependentInvocation
5784 //-----------------------------------------------------------------------------
5785 class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase
5788 GLuint m_buffer_tex;
5794 virtual long Setup()
5807 if (!SupportedInVS(2))
5808 return NOT_SUPPORTED;
5809 const char* const glsl_vs =
5810 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5811 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL
5812 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5813 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " gl_Position = i_position;" NL
5814 " vs_color = i_color;" NL " imageStore(g_buffer, 0, vec4(1.0));" NL
5815 " imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL " memoryBarrier();" NL "}";
5816 const char* const glsl_fs =
5817 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5818 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5819 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL
5820 " if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
5821 " if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}";
5822 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5823 glUseProgram(m_program);
5824 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5825 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5828 glGenBuffers(1, &m_buffer);
5829 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5830 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW);
5831 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5833 glGenTextures(1, &m_buffer_tex);
5834 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5835 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5836 glBindTexture(GL_TEXTURE_BUFFER, 0);
5838 glGenTextures(1, &m_texture);
5839 glBindTexture(GL_TEXTURE_2D, m_texture);
5840 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5841 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero);
5842 glBindTexture(GL_TEXTURE_2D, 0);
5844 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5845 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5847 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5849 glClear(GL_COLOR_BUFFER_BIT);
5850 glBindVertexArray(m_vao);
5851 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5853 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5860 virtual long Cleanup()
5863 glDeleteBuffers(1, &m_vbo);
5864 glDeleteBuffers(1, &m_buffer);
5865 glDeleteTextures(1, &m_texture);
5866 glDeleteTextures(1, &m_buffer_tex);
5867 glDeleteProgram(m_program);
5868 glDeleteVertexArrays(1, &m_vao);
5872 //-----------------------------------------------------------------------------
5873 // 2.3.2 AdvancedMemoryOrder
5874 //-----------------------------------------------------------------------------
5875 class AdvancedMemoryOrder : public ShaderImageLoadStoreBase
5878 GLuint m_buffer_tex;
5884 virtual long Setup()
5897 if (!SupportedInVS(1))
5898 return NOT_SUPPORTED;
5899 const char* const glsl_vs =
5900 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
5901 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL
5902 " gl_Position = i_position;" NL " vs_color = vec4(0, 1, 0, 1);" NL
5903 " imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL " imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL
5904 " imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL
5905 " if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}";
5906 const char* const glsl_fs =
5907 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5908 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL
5909 " ivec2 coord = ivec2(gl_FragCoord);" NL " for (int i = 0; i < 3; ++i) {" NL
5910 " imageStore(g_image, coord, vec4(i));" NL " vec4 v = imageLoad(g_image, coord);" NL
5911 " if (v != vec4(i)) {" NL " o_color = vec4(v.xyz, 0.0);" NL " break;" NL " }" NL " }" NL
5913 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5914 glUseProgram(m_program);
5915 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5916 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5918 glGenBuffers(1, &m_buffer);
5919 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5920 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
5921 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5923 glGenTextures(1, &m_buffer_tex);
5924 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5925 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5926 glBindTexture(GL_TEXTURE_BUFFER, 0);
5928 int width = getWindowWidth();
5929 int height = getWindowHeight();
5930 scaleDimensionsToMemory(width, height, 1, 2, 16, 16);
5932 std::vector<vec4> data(width * height);
5933 glGenTextures(1, &m_texture);
5934 glBindTexture(GL_TEXTURE_2D, m_texture);
5935 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5936 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
5937 glBindTexture(GL_TEXTURE_2D, 0);
5939 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5940 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5942 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5944 glClear(GL_COLOR_BUFFER_BIT);
5945 glViewport(0, 0, width, height);
5946 glBindVertexArray(m_vao);
5947 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5949 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5956 virtual long Cleanup()
5958 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5960 glDeleteBuffers(1, &m_vbo);
5961 glDeleteBuffers(1, &m_buffer);
5962 glDeleteTextures(1, &m_texture);
5963 glDeleteTextures(1, &m_buffer_tex);
5964 glDeleteProgram(m_program);
5965 glDeleteVertexArrays(1, &m_vao);
5969 //-----------------------------------------------------------------------------
5970 // 2.4.1 AdvancedSSOSimple
5971 //-----------------------------------------------------------------------------
5972 class AdvancedSSOSimple : public ShaderImageLoadStoreBase
5975 GLuint m_pipeline[2];
5976 GLuint m_vsp, m_fsp0, m_fsp1;
5977 GLuint m_vao, m_vbo;
5979 virtual long Setup()
5981 glGenTextures(1, &m_texture);
5982 glGenProgramPipelines(2, m_pipeline);
5983 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5985 const char* const glsl_vs =
5986 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
5987 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}";
5988 const char* const glsl_fs0 =
5989 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL
5990 " for (int i = 0; i < g_image.length(); ++i) {" NL
5991 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL " }" NL " discard;" NL "}";
5992 const char* const glsl_fs1 =
5993 "#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL
5994 " for (int i = 0; i < g_image.length(); ++i) {" NL
5995 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL " }" NL " discard;" NL "}";
5996 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
5997 m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
5998 m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
6005 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0);
6006 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2);
6007 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4);
6008 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6);
6010 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1);
6011 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3);
6012 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5);
6013 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7);
6015 glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
6016 glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
6018 glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
6019 glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
6021 int width = getWindowWidth();
6022 int height = getWindowHeight();
6023 scaleDimensionsToMemory(width, height, 8, 8, 16, 16);
6025 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6026 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6027 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6029 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6030 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
6031 glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F);
6032 glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
6033 glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
6034 glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F);
6035 glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
6036 glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F);
6038 glBindVertexArray(m_vao);
6040 glViewport(0, 0, width, height);
6041 glBindProgramPipeline(m_pipeline[0]);
6042 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6044 glBindProgramPipeline(m_pipeline[1]);
6045 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6047 std::vector<vec4> data(width * height * 8);
6048 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6050 for (int layer = 0; layer < 8; ++layer)
6052 for (int h = 0; h < height; ++h)
6054 for (int w = 0; w < width; ++w)
6056 const vec4 c = data[layer * width * height + h * width + w];
6059 if (!IsEqual(c, vec4(2.0f)))
6066 if (!IsEqual(c, vec4(1.0f)))
6077 virtual long Cleanup()
6079 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6080 glDeleteBuffers(1, &m_vbo);
6081 glDeleteTextures(1, &m_texture);
6082 glDeleteProgram(m_vsp);
6083 glDeleteProgram(m_fsp0);
6084 glDeleteProgram(m_fsp1);
6085 glDeleteVertexArrays(1, &m_vao);
6086 glDeleteProgramPipelines(2, m_pipeline);
6090 //-----------------------------------------------------------------------------
6091 // 2.4.2 AdvancedSSOAtomicCounters
6092 //-----------------------------------------------------------------------------
6093 class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase
6095 GLuint m_buffer, m_buffer_tex;
6096 GLuint m_counter_buffer;
6097 GLuint m_transform_buffer;
6099 GLuint m_vao, m_vbo;
6100 GLuint m_vsp, m_fsp;
6102 virtual long Setup()
6108 glGenBuffers(1, &m_buffer);
6109 glGenTextures(1, &m_buffer_tex);
6110 glGenBuffers(1, &m_counter_buffer);
6111 glGenBuffers(1, &m_transform_buffer);
6112 glGenProgramPipelines(1, &m_pipeline);
6118 if (!SupportedInVS(1))
6119 return NOT_SUPPORTED;
6121 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
6122 const char* const glsl_vs =
6123 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6124 "layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL
6125 "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL
6126 " mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL
6127 "layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL
6128 " gl_Position = g_transform.mvp * i_position;" NL " o_color = i_color;" NL
6129 " const uint index = atomicCounterIncrement(g_counter);" NL
6130 " imageStore(g_buffer, int(index), gl_Position);" NL "}";
6131 const char* const glsl_fs =
6132 "#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL
6133 "layout(location = 0) out vec4 o_color;" NL "void main() {" NL " o_color = i_color;" NL "}";
6134 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6135 m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
6137 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6138 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
6140 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6141 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
6143 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
6144 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
6146 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer);
6148 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW);
6150 glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer);
6152 glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW);
6154 glClear(GL_COLOR_BUFFER_BIT);
6155 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
6156 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer);
6157 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6158 glBindVertexArray(m_vao);
6159 glBindProgramPipeline(m_pipeline);
6160 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6162 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6167 std::vector<vec4> data(4);
6168 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6169 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]);
6171 for (int i = 0; i < 4; ++i)
6173 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)) &&
6174 !IsEqual(data[i], vec4(-1.0f, 1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, 1.0f, 0.0f, 1.0f)))
6183 virtual long Cleanup()
6185 glDeleteBuffers(1, &m_buffer);
6186 glDeleteBuffers(1, &m_vbo);
6187 glDeleteBuffers(1, &m_counter_buffer);
6188 glDeleteBuffers(1, &m_transform_buffer);
6189 glDeleteTextures(1, &m_buffer_tex);
6190 glDeleteProgram(m_vsp);
6191 glDeleteProgram(m_fsp);
6192 glDeleteVertexArrays(1, &m_vao);
6193 glDeleteProgramPipelines(1, &m_pipeline);
6197 //-----------------------------------------------------------------------------
6198 // 2.4.3 AdvancedSSOSubroutine
6199 //-----------------------------------------------------------------------------
6200 class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase
6203 GLuint m_attribless_vao;
6205 GLint m_draw_buffer;
6207 virtual long Setup()
6209 glGenTextures(1, &m_texture);
6210 glGenVertexArrays(1, &m_attribless_vao);
6212 const char* const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL
6213 "const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL
6214 "void main() {" NL " gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}";
6215 const char* const glsl_fs =
6216 "#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL
6217 "writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL
6218 "subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL
6219 " imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL
6220 " imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL
6221 " imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL
6222 "subroutine(Brush) void Brush1(ivec2 coord) {" NL
6223 " imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL
6224 " imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL
6225 " imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL
6226 " g_brush(ivec2(gl_FragCoord));" NL "}";
6227 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6234 int width = getWindowWidth();
6235 int height = getWindowHeight();
6236 scaleDimensionsToMemory(width, height, 3, 3, 16, 16);
6238 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1);
6239 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1);
6241 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6242 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6243 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 3, 0, GL_RGBA, GL_FLOAT, NULL);
6245 glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer);
6247 glDrawBuffer(GL_NONE);
6248 glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);
6249 glUseProgram(m_program);
6250 glBindVertexArray(m_attribless_vao);
6252 const GLuint indices[2] = { glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"),
6253 glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1") };
6255 glViewport(0, 0, width, height);
6256 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]);
6257 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6259 std::vector<vec4> data(width * height * 3);
6260 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6261 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6263 for (int layer = 0; layer < 3; ++layer)
6265 for (int h = 0; h < height; ++h)
6267 for (int w = 0; w < width; ++w)
6269 const vec4 c = data[layer * width * height + h * width + w];
6270 if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6272 m_context.getTestContext().getLog()
6273 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6274 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6277 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6279 m_context.getTestContext().getLog()
6280 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6281 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6284 else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6286 m_context.getTestContext().getLog()
6287 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6288 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6295 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]);
6296 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6298 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6299 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6301 for (int layer = 0; layer < 3; ++layer)
6303 for (int h = 0; h < height; ++h)
6305 for (int w = 0; w < width; ++w)
6307 const vec4 c = data[layer * width * height + h * width + w];
6308 if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6310 m_context.getTestContext().getLog()
6311 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6312 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6315 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6317 m_context.getTestContext().getLog()
6318 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6319 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6322 else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6324 m_context.getTestContext().getLog()
6325 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6326 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6335 virtual long Cleanup()
6337 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6338 glDrawBuffer(m_draw_buffer);
6339 glDeleteTextures(1, &m_texture);
6341 glDeleteProgram(m_program);
6342 glDeleteVertexArrays(1, &m_attribless_vao);
6346 //-----------------------------------------------------------------------------
6347 // 2.4.4 AdvancedSSOPerSample
6348 //-----------------------------------------------------------------------------
6349 class AdvancedSSOPerSample : public ShaderImageLoadStoreBase
6353 GLuint m_vao, m_vbo, m_ebo;
6354 GLuint m_vsp, m_store_fsp, m_load_fsp;
6356 virtual long Setup()
6364 glGenTextures(1, &m_texture);
6365 glGenProgramPipelines(1, &m_pipeline);
6372 if (!SupportedSamples(4))
6373 return NOT_SUPPORTED;
6375 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6377 const char* const glsl_vs =
6378 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6379 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}";
6380 const char* const glsl_store_fs =
6381 "#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL
6382 " imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}";
6383 const char* const glsl_load_fs =
6384 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6385 "layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL
6386 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != "
6387 "vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6388 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6389 m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs);
6390 m_load_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs);
6392 int width = getWindowWidth();
6393 int height = getWindowHeight();
6394 scaleDimensionsToMemory(width, height, 1, 1, /* bpp*samples */ 16 * 4, 16);
6396 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture);
6397 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, width, height, GL_FALSE);
6398 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
6400 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6401 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp);
6403 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6405 glClear(GL_COLOR_BUFFER_BIT);
6406 glViewport(0, 0, width, height);
6407 glBindVertexArray(m_vao);
6408 glBindProgramPipeline(m_pipeline);
6409 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6411 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6413 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp);
6414 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6416 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
6423 virtual long Cleanup()
6425 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6426 glDeleteBuffers(1, &m_vbo);
6427 glDeleteBuffers(1, &m_ebo);
6428 glDeleteTextures(1, &m_texture);
6429 glDeleteProgram(m_vsp);
6430 glDeleteProgram(m_store_fsp);
6431 glDeleteProgram(m_load_fsp);
6432 glDeleteVertexArrays(1, &m_vao);
6433 glDeleteProgramPipelines(1, &m_pipeline);
6438 //-----------------------------------------------------------------------------
6439 // 2.5 AdvancedCopyImage
6440 //-----------------------------------------------------------------------------
6441 class AdvancedCopyImage : public ShaderImageLoadStoreBase
6443 GLuint m_texture[2];
6445 GLuint m_vao, m_vbo, m_ebo;
6447 virtual long Setup()
6449 glGenTextures(2, m_texture);
6450 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6452 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6453 "void main() {" NL " gl_Position = i_position;" NL "}";
6454 const char* const glsl_fs =
6455 "#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL
6456 "layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL
6457 " ivec2 coord = ivec2(gl_FragCoord);" NL
6458 " imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL " discard;" NL "}";
6459 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6466 int width = getWindowWidth();
6467 int height = getWindowHeight();
6468 scaleDimensionsToMemory(width, height, 2, 2, 16, 16);
6470 glUseProgram(m_program);
6471 glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0);
6472 glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1);
6474 std::vector<vec4> data(width * height, vec4(7.0f));
6475 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6476 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6477 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
6479 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6480 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6481 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
6483 glBindTexture(GL_TEXTURE_2D, 0);
6485 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6486 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
6488 glClear(GL_COLOR_BUFFER_BIT);
6489 glViewport(0, 0, width, height);
6490 glBindVertexArray(m_vao);
6491 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6493 std::vector<vec4> rdata(width * height);
6494 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6495 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]);
6497 for (int h = 0; h < height; ++h)
6499 for (int w = 0; w < width; ++w)
6501 if (!IsEqual(rdata[h * width + w], vec4(7.0f)))
6510 virtual long Cleanup()
6512 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6514 glDeleteBuffers(1, &m_vbo);
6515 glDeleteBuffers(1, &m_ebo);
6516 glDeleteTextures(2, m_texture);
6517 glDeleteProgram(m_program);
6518 glDeleteVertexArrays(1, &m_vao);
6522 //-----------------------------------------------------------------------------
6523 // 2.6 AdvancedAllMips
6524 //-----------------------------------------------------------------------------
6525 class AdvancedAllMips : public ShaderImageLoadStoreBase
6528 GLuint m_store_program, m_load_program;
6529 GLuint m_vao, m_vbo, m_ebo;
6531 virtual long Setup()
6533 glGenTextures(1, &m_texture);
6534 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6536 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6537 "void main() {" NL " gl_Position = i_position;" NL "}";
6538 const char* const glsl_store_fs =
6539 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6540 " for (int i = 0; i < 6; ++i) {" NL " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL " }" NL
6542 const char* const glsl_load_fs =
6543 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6544 "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6545 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " for (int i = 0; i < 6; ++i) {" NL
6546 " const ivec2 coord = ivec2(gl_FragCoord);" NL " const vec4 c = imageLoad(g_image[i], coord);" NL
6547 " if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " }" NL "}";
6548 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
6549 m_load_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs);
6556 glUseProgram(m_store_program);
6557 glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0);
6558 glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1);
6559 glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2);
6560 glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3);
6561 glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4);
6562 glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5);
6565 glUseProgram(m_load_program);
6566 glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0);
6567 glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1);
6568 glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2);
6569 glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3);
6570 glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4);
6571 glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5);
6574 glBindTexture(GL_TEXTURE_2D, m_texture);
6575 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
6576 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
6577 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6578 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
6579 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
6580 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
6581 glBindTexture(GL_TEXTURE_2D, 0);
6583 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6584 glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6585 glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6586 glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6587 glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6588 glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6590 glViewport(0, 0, 32, 32);
6591 glBindVertexArray(m_vao);
6593 glClear(GL_COLOR_BUFFER_BIT);
6594 glUseProgram(m_store_program);
6595 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6597 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6599 glUseProgram(m_load_program);
6600 glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6602 if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1)))
6609 virtual long Cleanup()
6611 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6613 glDeleteBuffers(1, &m_vbo);
6614 glDeleteBuffers(1, &m_ebo);
6615 glDeleteTextures(1, &m_texture);
6616 glDeleteProgram(m_store_program);
6617 glDeleteProgram(m_load_program);
6618 glDeleteVertexArrays(1, &m_vao);
6622 //-----------------------------------------------------------------------------
6624 //-----------------------------------------------------------------------------
6625 class AdvancedCast : public ShaderImageLoadStoreBase
6627 GLuint m_texture[2];
6629 GLuint m_vao, m_vbo, m_ebo;
6631 virtual long Setup()
6633 glGenTextures(2, m_texture);
6634 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6636 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6637 "void main() {" NL " gl_Position = i_position;" NL "}";
6638 const char* const glsl_fs =
6639 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6640 "layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL
6641 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " ivec2 coord = ivec2(gl_FragCoord);" NL
6642 " if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6643 " if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6644 " if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6645 " if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6646 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6653 glUseProgram(m_program);
6654 glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0);
6655 glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1);
6658 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6659 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6660 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6661 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6664 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6665 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6666 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6669 glBindTexture(GL_TEXTURE_2D, 0);
6672 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
6673 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
6675 glClear(GL_COLOR_BUFFER_BIT);
6676 glBindVertexArray(m_vao);
6677 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6679 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6680 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6681 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6682 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6684 for (int h = 0; h < getWindowHeight(); ++h)
6686 for (int w = 0; w < getWindowWidth(); ++w)
6688 const GLubyte c[4] = {
6689 data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6690 data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6692 if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6694 m_context.getTestContext().getLog()
6695 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6696 << ") should be (1 0 0 0)" << tcu::TestLog::EndMessage;
6702 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6703 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6705 for (int h = 0; h < getWindowHeight(); ++h)
6707 for (int w = 0; w < getWindowWidth(); ++w)
6709 const GLubyte c[4] = {
6710 data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6711 data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6713 if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6715 m_context.getTestContext().getLog()
6716 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6717 << ") should be (3 0 0 0)" << tcu::TestLog::EndMessage;
6723 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6730 virtual long Cleanup()
6733 glDeleteBuffers(1, &m_vbo);
6734 glDeleteBuffers(1, &m_ebo);
6735 glDeleteTextures(2, m_texture);
6736 glDeleteProgram(m_program);
6737 glDeleteVertexArrays(1, &m_vao);
6742 /** Test "imageLoad() and imageStore() for single-byte data alignment" description follows.
6745 * - create two textures: "source" and "destination". Fill "source"
6746 * texture with unique values. Fill "destination" texture with zeros,
6747 * - prepare a program object that will read texel from "source" image at given
6748 * coordinates and write its value to "destination" image at same
6750 * - bind "source" and "destination" textures as "source" and "destination"
6752 * - render "full screen" quad (left bottom corner at -1,-1 and right top
6754 * - verify that texel values in "destination" texture match those in
6755 * "source" texture (use glGetTexImage).
6757 * Test with 2D R8UI textures with following dimensions:
6769 * Note that default data alignment should cause problems with packing/
6770 * /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters
6771 * of pixel storage mode have to be changed to one byte alignment.
6773 * Program should consist of vertex and fragment shader. Vertex shader should
6774 * pass vertex position through. Fragment shader should do imageLoad() and
6775 * imageStore() operations at coordinates gl_FragCoord.
6777 class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase
6781 struct TextureDimensions
6786 TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height)
6792 typedef std::deque<TextureDimensions> TextureDimensionsList;
6795 GLuint m_destination_texture_id;
6796 GLuint m_program_id;
6797 TextureDimensionsList m_texture_dimensions;
6798 GLuint m_source_texture_id;
6799 GLuint m_vertex_array_object_id;
6800 GLuint m_vertex_buffer_id;
6804 ImageLoadStoreDataAlignmentTest()
6805 : m_destination_texture_id(0)
6807 , m_source_texture_id(0)
6808 , m_vertex_array_object_id(0)
6809 , m_vertex_buffer_id(0)
6811 /* Nothing to be done here */
6814 /* Methods inherited from SubcaseBase */
6815 virtual long Setup()
6818 const char* const vertex_shader_code = "#version 400 core\n"
6819 "#extension GL_ARB_shader_image_load_store : require\n"
6821 "precision highp float;\n"
6823 "in vec4 vs_in_position;\n"
6827 " gl_Position = vs_in_position;\n"
6830 const char* const fragment_shader_code =
6831 "#version 400 core\n"
6832 "#extension GL_ARB_shader_image_load_store : require\n"
6834 "precision highp float;\n"
6836 "layout(r8ui) writeonly uniform uimage2D u_destination_image;\n"
6837 "layout(r8ui) readonly uniform uimage2D u_source_image;\n"
6841 " uvec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n"
6842 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
6847 /* Vertex postions for "full screen" quad, made with triangle strip */
6848 static const GLfloat m_vertex_buffer_data[] = {
6849 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
6850 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
6851 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
6852 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
6855 /* Result of BuildProgram operation */
6856 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
6858 /* Add all tested texture dimensions */
6859 m_texture_dimensions.push_back(TextureDimensions(16, 16));
6860 m_texture_dimensions.push_back(TextureDimensions(16, 17));
6861 m_texture_dimensions.push_back(TextureDimensions(17, 16));
6862 m_texture_dimensions.push_back(TextureDimensions(17, 17));
6863 m_texture_dimensions.push_back(TextureDimensions(16, 18));
6864 m_texture_dimensions.push_back(TextureDimensions(18, 16));
6865 m_texture_dimensions.push_back(TextureDimensions(18, 18));
6866 m_texture_dimensions.push_back(TextureDimensions(16, 19));
6867 m_texture_dimensions.push_back(TextureDimensions(19, 16));
6868 m_texture_dimensions.push_back(TextureDimensions(19, 19));
6870 /* Clean previous error */
6873 /* Set single-byte data alignment */
6874 glPixelStorei(GL_PACK_ALIGNMENT, 1);
6875 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6876 GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei");
6878 /* Prepare buffer with vertex positions of "full screen" quad" */
6879 glGenBuffers(1, &m_vertex_buffer_id);
6880 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
6882 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
6883 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
6885 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
6886 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
6888 /* Generate vertex array object */
6889 glGenVertexArrays(1, &m_vertex_array_object_id);
6890 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
6892 /* Prepare program object */
6893 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
6894 fragment_shader_code, &is_program_correct);
6895 if (false == is_program_correct)
6904 virtual long Cleanup()
6906 /* Reset OpenGL state */
6907 glBindBuffer(GL_ARRAY_BUFFER, 0);
6908 glBindTexture(GL_TEXTURE_2D, 0);
6909 glBindVertexArray(0);
6912 /* Delete program */
6913 if (0 != m_program_id)
6915 glDeleteProgram(m_program_id);
6919 /* Delete textures */
6920 if (0 != m_destination_texture_id)
6922 glDeleteTextures(1, &m_destination_texture_id);
6923 m_destination_texture_id = 0;
6926 if (0 != m_source_texture_id)
6928 glDeleteTextures(1, &m_source_texture_id);
6929 m_source_texture_id = 0;
6932 /* Delete vertex array object */
6933 if (0 != m_vertex_array_object_id)
6935 glDeleteVertexArrays(1, &m_vertex_array_object_id);
6936 m_vertex_array_object_id = 0;
6940 if (0 != m_vertex_buffer_id)
6942 glDeleteBuffers(1, &m_vertex_buffer_id);
6943 m_vertex_buffer_id = 0;
6954 /* For each dimension */
6955 for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it;
6958 /* Prepare "source" and "destination" textures */
6959 GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id),
6960 "Create2DR8UIDestinationTexture");
6961 GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id),
6962 "Create2DR8UISourceTexture");
6964 /* Copy texture data with imageLoad() and imageStore() operations */
6965 Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id);
6967 /* Compare "source" and "destination" textures */
6969 Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height))
6971 m_context.getTestContext().getLog()
6972 << tcu::TestLog::Message
6973 << "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height
6974 << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
6979 /* Destroy "source" and "destination" textures */
6980 glDeleteTextures(1, &m_destination_texture_id);
6981 glDeleteTextures(1, &m_source_texture_id);
6983 m_destination_texture_id = 0;
6984 m_source_texture_id = 0;
6987 if (false == result)
6997 /* Private methods */
6999 /** Binds a texture to user-specified image unit and updates relevant sampler uniform
7001 * @param program_id Program object id
7002 * @param texture_id Texture id
7003 * @param image_unit Index of image unit
7004 * @param uniform_name Name of image uniform
7006 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char* uniform_name)
7008 /* Uniform location and invalid value */
7009 static const GLint invalid_uniform_location = -1;
7010 GLint image_uniform_location = 0;
7012 /* Get uniform location */
7013 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7014 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7015 if (invalid_uniform_location == image_uniform_location)
7017 throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__);
7020 /* Bind texture to image unit */
7021 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI);
7022 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7024 /* Set uniform to image unit */
7025 glUniform1i(image_uniform_location, image_unit);
7026 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7029 /** Compare two 2D R8UI textures
7031 * @param left_texture_id Id of "left" texture object
7032 * @param right_texture_id Id of "right" texture object
7033 * @param width Width of the textures
7034 * @param height Height of the textures
7036 * @return true when texture data is identical, false otherwise
7038 bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height)
7040 /* Size of textures */
7041 const GLuint texture_data_size = width * height;
7043 /* Storage for texture data */
7044 std::vector<GLubyte> left_texture_data;
7045 std::vector<GLubyte> right_texture_data;
7047 /* Alocate memory for texture data */
7048 left_texture_data.resize(texture_data_size);
7049 right_texture_data.resize(texture_data_size);
7051 /* Get "left" texture data */
7052 glBindTexture(GL_TEXTURE_2D, left_texture_id);
7053 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7055 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]);
7056 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7058 /* Get "right" texture data */
7059 glBindTexture(GL_TEXTURE_2D, right_texture_id);
7060 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7062 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]);
7063 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7065 /* Compare texels */
7066 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7069 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7071 * @param destination_texture_id Id of "destination" texture object
7072 * @param source_texture_id Id of "source" texture object
7074 void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id)
7077 static const char* const destination_image_uniform_name = "u_destination_image";
7078 static const char* const source_image_uniform_name = "u_source_image";
7080 /* Attribute name */
7081 static const char* const position_attribute_name = "vs_in_position";
7083 /* Attribute location and invalid value */
7084 static const GLint invalid_attribute_location = -1;
7085 GLint position_attribute_location = 0;
7087 /* Set current program */
7088 glUseProgram(m_program_id);
7089 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7091 /* Bind vertex array object */
7092 glBindVertexArray(m_vertex_array_object_id);
7093 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7095 /* Bind buffer with quad vertex positions */
7096 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7097 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7099 /* Set up position attribute */
7100 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7101 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7102 if (invalid_attribute_location == position_attribute_location)
7104 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7108 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7110 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7112 glEnableVertexAttribArray(position_attribute_location);
7113 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7115 /* Set up textures as source and destination images */
7116 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name);
7117 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name);
7120 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7121 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7124 /** Create 2D R8UI texture and fills it with zeros
7126 * @param width Width of created texture
7127 * @param height Height of created texture
7128 * @param out_texture_id Id of created texture, not modified if operation fails
7130 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7132 GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7135 const GLuint texture_size = width * height;
7137 /* Prepare storage for texture data */
7138 std::vector<GLubyte> texture_data;
7139 texture_data.resize(texture_size);
7141 /* Set all texels */
7142 for (GLuint i = 0; i < texture_size; ++i)
7144 texture_data[i] = 0;
7147 /* Create texture */
7148 return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7151 /** Create 2D R8UI texture and fills it with increasing values, starting from 0
7153 * @param width Width of created texture
7154 * @param height Height of created texture
7155 * @param out_texture_id Id of created texture, not modified if operation fails
7157 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7159 GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7162 const GLuint texture_size = width * height;
7164 /* Value of texel */
7165 GLubyte texel_value = 0;
7167 /* Prepare storage for texture data */
7168 std::vector<GLubyte> texture_data;
7169 texture_data.resize(texture_size);
7171 /* Set all texels */
7172 for (GLuint i = 0; i < texture_size; ++i)
7174 texture_data[i] = texel_value++;
7177 /* Create texture */
7178 return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7181 /** Create 2D R8UI texture and fills it with user-provided data
7183 * @param width Width of created texture
7184 * @param height Height of created texture
7185 * @param texture_data Texture data
7186 * @param out_texture_id Id of created texture, not modified if operation fails
7188 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7190 GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte>& texture_data,
7191 GLuint& out_texture_id)
7194 GLuint texture_id = 0;
7196 /* Generate texture */
7197 glGenTextures(1, &texture_id);
7199 if (GL_NO_ERROR != err)
7205 glBindTexture(GL_TEXTURE_2D, texture_id);
7207 if (GL_NO_ERROR != err)
7209 glDeleteTextures(1, &texture_id);
7213 /* Allocate storage and fill texture */
7214 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER,
7215 GL_UNSIGNED_BYTE, &texture_data[0]);
7217 if (GL_NO_ERROR != err)
7219 glDeleteTextures(1, &texture_id);
7223 /* Make texture complete */
7224 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7225 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7228 if (GL_NO_ERROR != err)
7230 glDeleteTextures(1, &texture_id);
7234 /* Set out_texture_id */
7235 out_texture_id = texture_id;
7242 /** Test "imageLoad() and imageStore() for non-layered image bindings" description follows.
7244 * Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest).
7246 * Test non-layered image bindings (BindImageTexture <layered>: false) with:
7247 * | Type | Dimensions |
7248 * | 2D_ARRAY | 64x64x6 |
7251 * | CUBE_MAP_ARRAY | 64x3 |
7253 * Use RGBA8 format. All layers shall be tested.
7255 * Program should consist of vertex and fragment shader. Vertex shader should
7256 * pass vertex position through. Fragment shader should do imageLoad() and
7257 * imageStore() operations at coordinates gl_FragCoord. Fragment shader should
7258 * use image2D as image type.
7260 class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase
7264 struct TextureShapeDefinition
7267 GLuint m_n_elements;
7270 TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type)
7271 : m_edge(edge), m_n_elements(n_elements), m_type(type)
7277 typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList;
7280 GLuint m_destination_texture_id;
7281 GLuint m_program_id;
7282 TextureShapeDefinitionList m_texture_shape_definitions;
7283 GLuint m_source_texture_id;
7284 GLuint m_vertex_array_object_id;
7285 GLuint m_vertex_buffer_id;
7289 ImageLoadStoreNonLayeredBindingTest()
7290 : m_destination_texture_id(0)
7292 , m_source_texture_id(0)
7293 , m_vertex_array_object_id(0)
7294 , m_vertex_buffer_id(0)
7296 /* Nothing to be done here */
7299 /* Methods inherited from SubcaseBase */
7300 virtual long Setup()
7303 const char* const vertex_shader_code = "#version 400 core\n"
7304 "#extension GL_ARB_shader_image_load_store : require\n"
7306 "precision highp float;\n"
7308 "in vec4 vs_in_position;\n"
7312 " gl_Position = vs_in_position;\n"
7315 const char* const fragment_shader_code =
7316 "#version 400 core\n"
7317 "#extension GL_ARB_shader_image_load_store : require\n"
7319 "precision highp float;\n"
7321 "layout(rgba8) writeonly uniform image2D u_destination_image;\n"
7322 "layout(rgba8) readonly uniform image2D u_source_image;\n"
7326 " vec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n"
7327 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
7332 /* Vertex postions for "full screen" quad, defined as a triangle strip */
7333 static const GLfloat m_vertex_buffer_data[] = {
7334 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7335 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
7336 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
7337 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
7340 /* Result of BuildProgram operation */
7341 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7343 /* Add all tested texture shapes */
7344 int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7345 m_texture_shape_definitions.push_back(
7346 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY));
7347 m_texture_shape_definitions.push_back(
7348 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D));
7349 m_texture_shape_definitions.push_back(
7350 TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP));
7351 m_texture_shape_definitions.push_back(
7352 TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY));
7354 /* Prepare buffer with vertex positions of "full screen" quad" */
7355 glGenBuffers(1, &m_vertex_buffer_id);
7356 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7358 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7359 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7361 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7362 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7364 /* Generate vertex array object */
7365 glGenVertexArrays(1, &m_vertex_array_object_id);
7366 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7368 /* Prepare program object */
7369 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */,
7370 fragment_shader_code, &is_program_correct);
7371 if (false == is_program_correct)
7380 virtual long Cleanup()
7382 /* Reset OpenGL state */
7383 glBindBuffer(GL_ARRAY_BUFFER, 0);
7384 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
7385 glBindTexture(GL_TEXTURE_3D, 0);
7386 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
7387 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
7388 glBindVertexArray(0);
7391 /* Delete program */
7392 if (0 != m_program_id)
7394 glDeleteProgram(m_program_id);
7398 /* Delete textures */
7399 if (0 != m_destination_texture_id)
7401 glDeleteTextures(1, &m_destination_texture_id);
7402 m_destination_texture_id = 0;
7405 if (0 != m_source_texture_id)
7407 glDeleteTextures(1, &m_source_texture_id);
7408 m_source_texture_id = 0;
7411 /* Delete vertex array object */
7412 if (0 != m_vertex_array_object_id)
7414 glDeleteVertexArrays(1, &m_vertex_array_object_id);
7415 m_vertex_array_object_id = 0;
7419 if (0 != m_vertex_buffer_id)
7421 glDeleteBuffers(1, &m_vertex_buffer_id);
7422 m_vertex_buffer_id = 0;
7433 /* For each shape */
7434 for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin();
7435 m_texture_shape_definitions.end() != it; ++it)
7437 const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type);
7439 /* Prepare "source" and "destination" textures */
7440 GLU_EXPECT_NO_ERROR(
7441 CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id),
7442 "Create2DR8UIDestinationTexture");
7443 GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id),
7444 "Create2DR8UISourceTexture");
7446 /* Copy texture data with imageLoad() and imageStore() operations */
7447 CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers);
7449 /* Compare "source" and "destination" textures */
7451 CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type))
7453 const char* texture_type = "";
7456 case GL_TEXTURE_2D_ARRAY:
7457 texture_type = "2d array";
7460 texture_type = "3d";
7462 case GL_TEXTURE_CUBE_MAP:
7463 texture_type = "Cube map";
7465 case GL_TEXTURE_CUBE_MAP_ARRAY:
7466 texture_type = "Cube map array";
7470 m_context.getTestContext().getLog()
7471 << tcu::TestLog::Message
7472 << "Copy with imageLoad and imageStore failed for texture type: " << texture_type
7473 << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
7478 /* Destroy "source" and "destination" textures */
7479 glDeleteTextures(1, &m_destination_texture_id);
7480 glDeleteTextures(1, &m_source_texture_id);
7482 m_destination_texture_id = 0;
7483 m_source_texture_id = 0;
7486 if (false == result)
7496 /* Private methods */
7498 /** Binds a texture to user-specified image unit and update relevant sampler uniform
7500 * @param program_id Program object id
7501 * @param texture_id Texture id
7502 * @param image_unit Index of image unit
7503 * @param layer Index of layer bound to unit
7504 * @param uniform_name Name of image uniform
7506 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer,
7507 const char* uniform_name)
7509 static const GLint invalid_uniform_location = -1;
7510 GLint image_uniform_location = 0;
7512 /* Get uniform location */
7513 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7514 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7515 if (invalid_uniform_location == image_uniform_location)
7517 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
7520 /* Bind texture to image unit */
7521 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE,
7523 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7525 /* Set uniform to image unit */
7526 glUniform1i(image_uniform_location, image_unit);
7527 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7530 /** Compare two 2D R8UI textures
7532 * @param left_texture_id Id of "left" texture object
7533 * @param right_texture_id Id of "right" texture object
7534 * @param edge Length of texture edge
7535 * @param n_layers Number of layers to compare
7536 * @param type Type of texture
7538 * @return true when texture data is found identical, false otherwise
7540 bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers,
7543 static const GLuint n_components = 4; /* RGBA */
7544 const GLuint texture_data_size = edge * edge * n_layers * n_components;
7546 /* Storage for texture data */
7547 std::vector<GLubyte> left_texture_data;
7548 std::vector<GLubyte> right_texture_data;
7550 ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data);
7551 ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data);
7553 /* Compare texels */
7554 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7557 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7559 * @param destination_texture_id Id of "destination" texture object
7560 * @param source_texture_id Id of "source" texture object
7561 * @param n_layers Number of layers
7563 void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers)
7565 for (GLuint layer = 0; layer < n_layers; ++layer)
7567 CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer);
7571 /** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations
7573 * @param destination_texture_id Id of "destination" texture object
7574 * @param source_texture_id Id of "source" texture object
7575 * @param layer Index of layer
7577 void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer)
7580 static const char* const destination_image_uniform_name = "u_destination_image";
7581 static const char* const source_image_uniform_name = "u_source_image";
7583 /* Attribute name */
7584 static const char* const position_attribute_name = "vs_in_position";
7586 /* Attribute location and invalid value */
7587 static const GLint invalid_attribute_location = -1;
7588 GLint position_attribute_location = 0;
7590 /* Set current program */
7591 glUseProgram(m_program_id);
7592 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7594 /* Bind vertex array object */
7595 glBindVertexArray(m_vertex_array_object_id);
7596 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7598 /* Bind buffer with quad vertex positions */
7599 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7600 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7602 /* Set up vertex attribute array for position attribute */
7603 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7604 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7605 if (invalid_attribute_location == position_attribute_location)
7607 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7611 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7612 0 /* stride */, 0 /* pointer */);
7613 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7615 glEnableVertexAttribArray(position_attribute_location);
7616 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7618 /* Set up textures as source and destination image samplers */
7619 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer,
7620 destination_image_uniform_name);
7621 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name);
7624 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7625 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7628 /** Creates RGBA8 texture of given type and fills it with zeros
7630 * @param edge Edge of created texture
7631 * @param n_elements Number of elements in texture array
7632 * @param target Target of created texture
7633 * @param out_texture_id Id of created texture, not modified if operation fails
7635 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7637 GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7639 /* Constasts to calculate texture size */
7640 static const GLuint n_components = 4; /* RGBA */
7641 const GLuint layer_size = edge * edge * n_components;
7642 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target);
7643 const GLuint texture_size = layer_size * n_layers;
7645 /* Prepare storage for texture data */
7646 std::vector<GLubyte> texture_data;
7647 texture_data.resize(texture_size);
7649 /* Set all texels */
7650 for (GLuint i = 0; i < texture_size; ++i)
7652 texture_data[i] = 0;
7655 /* Create texture */
7656 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7659 /** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa]
7661 * @param edge Edge of created texture
7662 * @param n_elements Number of elements in texture array
7663 * @param target Target of created texture
7664 * @param out_texture_id Id of created texture, not modified if operation fails
7666 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7668 GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7670 /* Constants to calculate texture size */
7671 static const GLuint n_components = 4; /* RGBA */
7672 const GLuint layer_size = edge * edge * n_components;
7673 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target);
7674 const GLuint texture_size = layer_size * n_layers;
7676 /* Value of texel */
7677 GLubyte texel[4] = { 0, 0, 0, 0xaa };
7679 /* Prepare storage for texture data */
7680 std::vector<GLubyte> texture_data;
7681 texture_data.resize(texture_size);
7683 /* Set all texels */
7684 for (GLuint layer = 0; layer < n_layers; ++layer)
7686 const GLuint layer_offset = layer_size * layer;
7688 texel[2] = static_cast<GLubyte>(layer);
7690 for (GLuint y = 0; y < edge; ++y)
7692 const GLuint line_offset = y * edge * n_components + layer_offset;
7694 texel[1] = static_cast<GLubyte>(y);
7696 for (GLuint x = 0; x < edge; ++x)
7698 const GLuint texel_offset = x * n_components + line_offset;
7699 texel[0] = static_cast<GLubyte>(x);
7701 for (GLuint component = 0; component < n_components; ++component)
7703 texture_data[texel_offset + component] = texel[component];
7709 /* Create texture */
7710 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7713 /** Creates RGBA8 texture of given type and fills it provided data
7715 * @param edge Edge of created texture
7716 * @param n_elements Number of elements in texture array
7717 * @param target Target of created texture
7718 * @param texture_data Texture data
7719 * @param out_texture_id Id of created texture, not modified if operation fails
7721 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7723 GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte>& texture_data,
7724 GLuint& out_texture_id)
7727 GLuint texture_id = 0;
7729 /* Generate texture */
7730 glGenTextures(1, &texture_id);
7732 if (GL_NO_ERROR != err)
7738 glBindTexture(target, texture_id);
7740 if (GL_NO_ERROR != err)
7742 glDeleteTextures(1, &texture_id);
7746 /* Allocate storage and fill texture */
7747 if (GL_TEXTURE_CUBE_MAP != target)
7749 glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA,
7750 GL_UNSIGNED_BYTE, &texture_data[0]);
7754 const GLuint n_components = 4;
7755 const GLuint layer_size = edge * edge * n_components;
7757 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7758 GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7759 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7760 GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7761 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7762 GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7763 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7764 GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7765 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7766 GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7767 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7768 GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7771 if (GL_NO_ERROR != err)
7773 glDeleteTextures(1, &texture_id);
7777 /* Make texture complete */
7778 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
7779 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
7780 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7782 if (GL_NO_ERROR != err)
7784 glDeleteTextures(1, &texture_id);
7788 /* Set out_texture_id */
7789 out_texture_id = texture_id;
7795 /** Extracts texture data
7797 * @param texture_id Id of texture object
7798 * @param edge Length of texture edge
7799 * @param n_layers Number of layers
7800 * @param target Target of texture
7801 * @param texture_data Extracted texture data
7803 void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target,
7804 std::vector<GLubyte>& texture_data)
7806 static const GLuint n_components = 4; /* RGBA */
7807 const GLuint texture_data_size = edge * edge * n_layers * n_components;
7809 /* Alocate memory for texture data */
7810 texture_data.resize(texture_data_size);
7813 glBindTexture(target, texture_id);
7814 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7817 if (GL_TEXTURE_CUBE_MAP != target)
7819 glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
7823 const GLuint layer_size = edge * edge * n_components;
7825 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7826 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7827 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7828 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7829 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7830 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7833 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7836 /** Get number of layers per single element for given type of texture
7838 * @param target Target of texture
7840 * @return Number of layers
7842 GLuint GetLayersPerElement(GLenum target)
7846 case GL_TEXTURE_2D_ARRAY:
7850 case GL_TEXTURE_CUBE_MAP:
7851 case GL_TEXTURE_CUBE_MAP_ARRAY:
7855 throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__);
7860 /** Get total number of layers in texture of given type and number of array elements
7862 * @param n_elements Number of elements in texture array
7863 * @param target Target of texture
7865 * @return Number of layers
7867 GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target)
7869 return GetLayersPerElement(target) * n_elements;
7873 /** Test "imageLoad() and imageStore() for incomplete textures" description follows.
7875 * Load from incomplete textures should return 0.
7876 * Store to incomplete textures should be ignored.
7879 * - create two incomplete textures: "incomplete_source" and
7880 * "incomplete_destination",
7881 * - create two complete textures: "complete_source" and
7882 * "complete_destination",
7883 * - fill all textures with unique values,
7884 * - prepare program that will:
7885 * * load texel from "incomplete_source" and store its value to
7886 * "complete_destination",
7887 * * load texel from "complete_source" and store its value to
7888 * "incomplete_destination".
7889 * - bind textures to corresponding image uniforms
7890 * - execute program for all texels,
7891 * - verify that "incomplete_destination" was not modified and
7892 * "complete_destination" is filled with zeros.
7894 * Texture is considered incomplete when it has enabled mipmaping (see below)
7895 * and does not have all mipmap levels defined. But for the case of Image
7896 * accessing, it is considered invalid if it is mipmap-incomplete and the
7897 * level is different to the base level (base-incomplete).
7899 * Creation of incomplete texture:
7900 * - generate and bind texture object id,
7901 * - call TexImage2D with <level>: 0,
7902 * - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make
7903 * sure, it should be initial value),
7904 * - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7905 * - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width,
7908 * Creation of complete texture:
7909 * - generate and bind texture object id,
7910 * - call TexImage2D with <level>: 0,
7911 * - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7912 * - set GL_TEXTURE_MAX_LEVEL parameter to 0.
7915 * - Set level == base_level for complete destinations.
7916 * - Set level != base_level for incomplete destinations that are using
7917 * mipmap-incomplete textures.
7919 * Test with 2D 64x64 RGBA8 textures.
7921 * Program should consist of vertex and fragment shader. Vertex shader should
7922 * pass vertex position through. Fragment shader should do imageLoad() and
7923 * imageStore() operations at coordinates gl_FragCoord.
7925 class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase
7929 /* Magic numbers that will identify textures, which will be used as their
7932 static const GLubyte m_complete_destination_magic_number = 0x11;
7933 static const GLubyte m_complete_source_magic_number = 0x22;
7934 static const GLubyte m_incomplete_destination_magic_number = 0x33;
7935 static const GLubyte m_incomplete_source_magic_number = 0x44;
7938 GLuint m_texture_edge;
7941 GLuint m_complete_destination_texture_id;
7942 GLuint m_complete_source_texture_id;
7943 GLuint m_incomplete_destination_texture_id;
7944 GLuint m_incomplete_source_texture_id;
7945 GLuint m_program_id;
7946 GLuint m_vertex_array_object_id;
7947 GLuint m_vertex_buffer_id;
7951 ImageLoadStoreIncompleteTexturesTest()
7953 , m_complete_destination_texture_id(0)
7954 , m_complete_source_texture_id(0)
7955 , m_incomplete_destination_texture_id(0)
7956 , m_incomplete_source_texture_id(0)
7958 , m_vertex_array_object_id(0)
7959 , m_vertex_buffer_id(0)
7961 /* Nothing to be done here */
7964 /* Methods inherited from SubcaseBase */
7965 virtual long Setup()
7968 const char* const vertex_shader_code = "#version 400 core\n"
7969 "#extension GL_ARB_shader_image_load_store : require\n"
7971 "precision highp float;\n"
7973 "in vec4 vs_in_position;\n"
7977 " gl_Position = vs_in_position;\n"
7980 const char* const fragment_shader_code =
7981 "#version 400 core\n"
7982 "#extension GL_ARB_shader_image_load_store : require\n"
7984 "precision highp float;\n"
7986 "layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n"
7987 "layout(rgba8) readonly uniform image2D u_complete_source_image;\n"
7988 "layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n"
7989 "layout(rgba8) readonly uniform image2D u_incomplete_source_image;\n"
7993 " vec4 complete_loaded_color = imageLoad (u_complete_source_image, ivec2(gl_FragCoord));\n"
7994 " vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n"
7996 " imageStore(u_complete_destination_image,\n"
7997 " ivec2(gl_FragCoord),\n"
7998 " incomplete_loaded_color);\n"
7999 " imageStore(u_incomplete_destination_image,\n"
8000 " ivec2(gl_FragCoord),\n"
8001 " complete_loaded_color);\n"
8006 /* Vertex postions for "full screen" quad, made with triangle strip */
8007 static const GLfloat m_vertex_buffer_data[] = {
8008 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
8009 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
8010 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
8011 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
8014 /* Result of BuildProgram operation */
8015 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
8017 /* Clean previous error */
8020 m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
8022 /* Prepare textures */
8023 GLU_EXPECT_NO_ERROR(
8024 Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id),
8025 "Create2DRGBA8CompleteTexture");
8026 GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id),
8027 "Create2DRGBA8CompleteTexture");
8028 GLU_EXPECT_NO_ERROR(
8029 Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id),
8030 "Create2DRGBA8IncompleteTexture");
8031 GLU_EXPECT_NO_ERROR(
8032 Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id),
8033 "Create2DRGBA8IncompleteTexture");
8035 /* Prepare buffer with vertex positions of "full screen" quad" */
8036 glGenBuffers(1, &m_vertex_buffer_id);
8037 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
8039 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8040 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8042 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
8043 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
8045 /* Generate vertex array object */
8046 glGenVertexArrays(1, &m_vertex_array_object_id);
8047 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8049 /* Prepare program object */
8050 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
8051 fragment_shader_code, &is_program_correct);
8053 if (false == is_program_correct)
8062 virtual long Cleanup()
8064 /* Reset OpenGL state */
8065 glBindBuffer(GL_ARRAY_BUFFER, 0);
8066 glBindTexture(GL_TEXTURE_2D, 0);
8067 glBindVertexArray(0);
8070 /* Delete program */
8071 if (0 != m_program_id)
8073 glDeleteProgram(m_program_id);
8077 /* Delete textures */
8078 if (0 != m_complete_destination_texture_id)
8080 glDeleteTextures(1, &m_complete_destination_texture_id);
8081 m_complete_destination_texture_id = 0;
8084 if (0 != m_complete_source_texture_id)
8086 glDeleteTextures(1, &m_complete_source_texture_id);
8087 m_complete_source_texture_id = 0;
8090 if (0 != m_incomplete_destination_texture_id)
8092 glDeleteTextures(1, &m_incomplete_destination_texture_id);
8093 m_incomplete_destination_texture_id = 0;
8096 if (0 != m_incomplete_source_texture_id)
8098 glDeleteTextures(1, &m_incomplete_source_texture_id);
8099 m_incomplete_source_texture_id = 0;
8102 /* Delete vertex array object */
8103 if (0 != m_vertex_array_object_id)
8105 glDeleteVertexArrays(1, &m_vertex_array_object_id);
8106 m_vertex_array_object_id = 0;
8110 if (0 != m_vertex_buffer_id)
8112 glDeleteBuffers(1, &m_vertex_buffer_id);
8113 m_vertex_buffer_id = 0;
8124 /* Copy textures data with imageLoad() and imageStore() operations */
8125 Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id,
8126 m_complete_source_texture_id, m_incomplete_source_texture_id);
8128 glMemoryBarrier(GL_ALL_BARRIER_BITS);
8130 /* Verify that store to "incomplete destination" was ignored */
8132 CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number))
8134 m_context.getTestContext().getLog()
8135 << tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture"
8136 << tcu::TestLog::EndMessage;
8141 /* Verify that load from "incomplete source" returned 0 */
8142 if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id))
8144 m_context.getTestContext().getLog()
8145 << tcu::TestLog::Message
8146 << "Problem with imageLoad, operation returned non 0 result for incomplete texture"
8147 << tcu::TestLog::EndMessage;
8152 if (false == result)
8162 /* Private methods */
8164 /** Bind texture to image unit and sets image uniform to that unit
8166 * @param program_id Program object id
8167 * @param texture_id Texture id
8168 * @param level Texture level
8169 * @param image_unit Index of image unit
8170 * @param uniform_name Name of image uniform
8172 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit, const char* uniform_name)
8174 /* Uniform location and invalid value */
8175 static const GLint invalid_uniform_location = -1;
8176 GLint image_uniform_location = 0;
8178 /* Get uniform location */
8179 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
8180 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
8181 if (invalid_uniform_location == image_uniform_location)
8183 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
8186 /* Bind texture to image unit */
8187 glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8);
8188 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
8190 /* Set uniform to image unit */
8191 glUniform1i(image_uniform_location, image_unit);
8192 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
8195 /** Check if texture is filled with black color, zeros
8197 * @param texture_id Id of texture object
8199 * @return true when texture is fully black, false otherwise
8201 bool CheckIfTextureIsBlack(GLuint texture_id)
8203 /* Constants to calculate size of texture */
8204 static const GLuint n_components = 4; /* RGBA */
8205 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8207 /* Storage for texture data */
8208 std::vector<GLubyte> black_texture_data;
8209 std::vector<GLubyte> texture_data;
8211 /* Allocate memory */
8212 black_texture_data.resize(texture_data_size);
8213 texture_data.resize(texture_data_size);
8215 /* Set all texels to black */
8216 for (GLuint i = 0; i < texture_data_size; ++i)
8218 black_texture_data[i] = 0;
8222 glBindTexture(GL_TEXTURE_2D, texture_id);
8223 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8225 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8226 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8228 /* Compare texels */
8229 return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size));
8232 /** Check if texture was modified
8234 * @param texture_id Id of texture object
8235 * @param nagic_number Magic number that was to create texture
8237 * @return true if texture contents match expected values, false otherwise
8239 bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number)
8241 /* Constants to calculate size of texture */
8242 static const GLuint n_components = 4; /* RGBA */
8243 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8245 /* Storage for texture data */
8246 std::vector<GLubyte> expected_texture_data;
8247 std::vector<GLubyte> texture_data;
8249 /* Allocate memory */
8250 expected_texture_data.resize(texture_data_size);
8251 texture_data.resize(texture_data_size);
8253 /* Prepare expected texels */
8254 for (GLuint y = 0; y < m_texture_edge; ++y)
8256 const GLuint line_offset = y * m_texture_edge * n_components;
8258 for (GLuint x = 0; x < m_texture_edge; ++x)
8260 const GLuint texel_offset = x * n_components + line_offset;
8262 SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y),
8268 glBindTexture(GL_TEXTURE_2D, texture_id);
8269 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8271 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8272 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8274 /* Compare texels, true when textures are different */
8275 return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size));
8278 /** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations
8280 * @param complete_destination_texture_id Id of "complete destination" texture object
8281 * @param incomplete_destination_texture_id Id of "incomplete destination" texture object
8282 * @param complete_source_texture_id Id of "complete source" texture object
8283 * @param incomplete_source_texture_id Id of "incomplete source" texture object
8285 void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id,
8286 GLuint complete_source_texture_id, GLuint incomplete_source_texture_id)
8289 static const char* const complete_destination_image_uniform_name = "u_complete_destination_image";
8290 static const char* const complete_source_image_uniform_name = "u_complete_source_image";
8291 static const char* const incomplete_destination_image_uniform_name = "u_incomplete_destination_image";
8292 static const char* const incomplete_source_image_uniform_name = "u_incomplete_source_image";
8294 /* Attribute name */
8295 static const char* const position_attribute_name = "vs_in_position";
8297 /* Attribute location and invalid value */
8298 static const GLint invalid_attribute_location = -1;
8299 GLint position_attribute_location = 0;
8301 /* Set current program */
8302 glUseProgram(m_program_id);
8303 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
8305 /* Bind vertex array object */
8306 glBindVertexArray(m_vertex_array_object_id);
8307 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8309 /* Bind buffer with quad vertex positions */
8310 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8311 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8313 /* Setup position attribute */
8314 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
8315 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
8316 if (invalid_attribute_location == position_attribute_location)
8318 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
8322 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0);
8323 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
8325 glEnableVertexAttribArray(position_attribute_location);
8326 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
8328 /* Setup textures as source and destination images */
8329 BindTextureToImage(m_program_id, complete_destination_texture_id,
8330 0 /* texture level */, 0 /* image_unit */,
8331 complete_destination_image_uniform_name);
8332 BindTextureToImage(m_program_id, complete_source_texture_id,
8333 0 /* texture level */, 1 /* image_unit */,
8334 complete_source_image_uniform_name);
8335 BindTextureToImage(m_program_id, incomplete_destination_texture_id,
8336 2 /* texture level */, 2 /* image_unit */,
8337 incomplete_destination_image_uniform_name);
8338 BindTextureToImage(m_program_id, incomplete_source_texture_id,
8339 2 /* texture level */, 3 /* image_unit */,
8340 incomplete_source_image_uniform_name);
8343 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
8344 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
8347 /** Create complete 2D RGBA8 texture.
8349 * @param magic_number Magic number of texture
8350 * @param out_texture_id Id of created texture, not modified if operation fails
8352 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8354 GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8356 /* Constants to calculate size of texture */
8357 static const GLuint n_components = 4; /* RGBA */
8358 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8364 GLuint texture_id = 0;
8366 /* Prepare storage for texture data */
8367 std::vector<GLubyte> texture_data;
8368 texture_data.resize(texture_data_size);
8370 /* Prepare texture data */
8371 for (GLuint y = 0; y < m_texture_edge; ++y)
8373 const GLuint line_offset = y * m_texture_edge * n_components;
8375 for (GLuint x = 0; x < m_texture_edge; ++x)
8377 const GLuint texel_offset = x * n_components + line_offset;
8379 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8383 /* Generate texture */
8384 glGenTextures(1, &texture_id);
8386 if (GL_NO_ERROR != err)
8392 glBindTexture(GL_TEXTURE_2D, texture_id);
8394 if (GL_NO_ERROR != err)
8396 glDeleteTextures(1, &texture_id);
8400 /* Allocate storage and fill texture */
8401 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8402 GL_UNSIGNED_BYTE, &texture_data[0]);
8404 if (GL_NO_ERROR != err)
8406 glDeleteTextures(1, &texture_id);
8410 /* Make texture complete */
8411 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8412 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8413 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8415 if (GL_NO_ERROR != err)
8417 glDeleteTextures(1, &texture_id);
8421 /* Set out_texture_id */
8422 out_texture_id = texture_id;
8428 /** Create incomplete 2D RGBA8 texture
8430 * @param magic_number Magic number of texture
8431 * @param out_texture_id Id of created texture, not modified if operation fails
8433 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8435 GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8437 /* Constants to calculate size of texture */
8438 static const GLuint n_components = 4; /* RGBA */
8439 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8445 GLuint texture_id = 0;
8447 /* Prepare storage for texture data */
8448 std::vector<GLubyte> texture_data;
8449 texture_data.resize(texture_data_size);
8451 /* Prepare texture data */
8452 for (GLuint y = 0; y < m_texture_edge; ++y)
8454 const GLuint line_offset = y * m_texture_edge * n_components;
8456 for (GLuint x = 0; x < m_texture_edge; ++x)
8458 const GLuint texel_offset = x * n_components + line_offset;
8460 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8464 /* Generate texture */
8465 glGenTextures(1, &texture_id);
8467 if (GL_NO_ERROR != err)
8473 glBindTexture(GL_TEXTURE_2D, texture_id);
8475 if (GL_NO_ERROR != err)
8477 glDeleteTextures(1, &texture_id);
8481 /* Allocate storage and fill texture */
8482 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8483 GL_UNSIGNED_BYTE, &texture_data[0]);
8485 if (GL_NO_ERROR != err)
8487 glDeleteTextures(1, &texture_id);
8491 /* Make texture incomplete */
8492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8493 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7);
8494 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
8496 if (GL_NO_ERROR != err)
8498 glDeleteTextures(1, &texture_id);
8502 /* Set out_texture_id */
8503 out_texture_id = texture_id;
8509 /** Prepare "unique" texels.
8510 * Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc].
8512 * @param texel Storage of texel
8513 * @param x_coordinate X coordiante of texel
8514 * @param y_coordinate Y coordinate of texel
8515 * @param magic_number Magic number of texture
8517 void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number)
8519 texel[0] = x_coordinate;
8520 texel[1] = y_coordinate;
8521 texel[2] = magic_number;
8526 /** Test "Refer to the same image unit using multiple uniforms", description follows.
8529 * - prepare program object, see details below,
8530 * - prepare 2D R32I texture, width should be equal to the number of image
8531 * uniforms used by program object, height should be 2, fill first row with
8532 * unique values, fill second row with zeros,
8533 * - bind texture to first image unit,
8534 * - set all image uniforms to first image unit,
8535 * - execute program for a single vertex,
8537 * - values in first row were negated,
8538 * - values from first row were copied to second row,
8540 * Repeat steps to test all shader stages that support at least 2 image
8543 * Program has to contain all necessary shader stages. Use boilerplate shaders
8544 * for shader stages that are not important for the test.
8546 * Tested shader stage should:
8547 * - Use as many different image formats as possible, image formats compatible
8564 * - Declare maximum allowed number of image uniforms,
8566 * layout(format) uniform gimage2D u_image;
8568 * where <format> is selected image format, <gimage2D> is type of 2D image
8569 * compatible with <format> and <u_image> is unique name of uniform.
8570 * Note that image uniforms cannot be declared as array, due to different image
8571 * formats. Therefore separate uniforms have to be used.
8572 * - Include following code snippet:
8573 * for (int i = 0; i < gl_Max*ImageUniforms; ++i)
8575 * vec row_1_coord(i,0);
8576 * vec row_2_coord(i,1);
8578 * row_1_value = imageLoad(u_image[i], row_1_coord);
8579 * imageStore(u_image[i], row_1_coord, -row_1_value);
8580 * imageStore(u_image[i], row_2_coord, row_1_value);
8582 * where gl_Max*ImageUniforms is the constant corresponding to tested shader
8585 class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase
8589 /** Details of image format
8592 struct imageFormatDetails
8594 typedef bool (*verificationRoutine)(GLint, GLint, GLint);
8596 const char* m_image_format;
8597 const char* m_image_type;
8598 const char* m_color_type;
8599 GLenum m_image_unit_format;
8600 verificationRoutine m_verification_routine;
8603 template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)>
8606 /** Get mask of bits used to store in bit-field
8610 static inline T RawMask()
8612 static const T mask = ValueMask() << OFFSET;
8617 /** Get mask of bits used to store value.
8621 static inline T ValueMask()
8623 static const T mask = (1 << SIZE) - 1;
8632 static inline T Offset()
8638 template <typename T, GLuint SIZE, GLuint OFFSET>
8639 struct Masks<T, SIZE, OFFSET, false>
8641 /** Get mask of bits used to store in bit-field
8645 static inline T RawMask()
8647 DE_ASSERT(DE_FALSE && "Shouldn't be called");
8651 /** Get mask of bits used to store value.
8655 static inline T ValueMask()
8657 DE_ASSERT(DE_FALSE && "Shouldn't be called");
8665 static inline T Offset()
8667 DE_ASSERT(DE_FALSE && "Shouldn't be called");
8672 /** Template class for accessing integer values stored in bit-fields
8675 template <typename T, GLuint SIZE, GLuint OFFSET>
8682 Integer(T raw) : m_raw(raw)
8686 /** Extract value from bit-field
8692 const T mask = Masks<T, SIZE, OFFSET>::RawMask();
8694 const T bits = m_raw & mask;
8695 const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset();
8700 /** Extract value from bit-field and negate it
8702 * @return Negated value
8704 T GetNegated() const
8706 const T mask = Masks<T, SIZE, OFFSET>::ValueMask();
8707 const T value = Get();
8709 return Clamp((~value) + 1) & mask;
8714 const bool isUnsigned = (T(0) < T(-1));
8715 const T min = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1)));
8716 const T max = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L);
8717 const T x = n > max ? max : n;
8718 return x < min ? min : x;
8726 /** Shader stage identification
8731 fragmentShaderStage = 2,
8732 geometryShaderStage = 4,
8733 tesselationControlShaderStage = 8,
8734 tesselationEvalutaionShaderStage = 16,
8735 vertexShaderStage = 32,
8744 testNotSupported = 1,
8749 static const GLint m_min_required_image_uniforms = 2;
8752 GLuint m_program_to_test_fs_stage_id;
8753 GLuint m_program_to_test_gs_stage_id;
8754 GLuint m_program_to_test_tcs_stage_id;
8755 GLuint m_program_to_test_tes_stage_id;
8756 GLuint m_program_to_test_vs_stage_id;
8757 GLuint m_texture_to_test_fs_stage_id;
8758 GLuint m_texture_to_test_gs_stage_id;
8759 GLuint m_texture_to_test_tcs_stage_id;
8760 GLuint m_texture_to_test_tes_stage_id;
8761 GLuint m_texture_to_test_vs_stage_id;
8762 GLuint m_vertex_array_object_id;
8766 ImageLoadStoreMultipleUniformsTest()
8767 : m_program_to_test_fs_stage_id(0)
8768 , m_program_to_test_gs_stage_id(0)
8769 , m_program_to_test_tcs_stage_id(0)
8770 , m_program_to_test_tes_stage_id(0)
8771 , m_program_to_test_vs_stage_id(0)
8772 , m_texture_to_test_fs_stage_id(0)
8773 , m_texture_to_test_gs_stage_id(0)
8774 , m_texture_to_test_tcs_stage_id(0)
8775 , m_texture_to_test_tes_stage_id(0)
8776 , m_texture_to_test_vs_stage_id(0)
8777 , m_vertex_array_object_id(0)
8779 /* Nothing to be done here */
8782 /* Methods inherited from SubcaseBase */
8783 virtual long Setup()
8785 /* Prepare programs */
8786 m_program_to_test_fs_stage_id = buildProgramToTestShaderStage(fragmentShaderStage);
8787 m_program_to_test_gs_stage_id = buildProgramToTestShaderStage(geometryShaderStage);
8788 m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage);
8789 m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage);
8790 m_program_to_test_vs_stage_id = buildProgramToTestShaderStage(vertexShaderStage);
8792 /* Prepare textures */
8793 m_texture_to_test_fs_stage_id = createTextureToTestShaderStage(fragmentShaderStage);
8794 m_texture_to_test_gs_stage_id = createTextureToTestShaderStage(geometryShaderStage);
8795 m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage);
8796 m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage);
8797 m_texture_to_test_vs_stage_id = createTextureToTestShaderStage(vertexShaderStage);
8799 /* Generate vertex array object */
8800 glGenVertexArrays(1, &m_vertex_array_object_id);
8801 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8803 /* Bind vertex array object */
8804 glBindVertexArray(m_vertex_array_object_id);
8805 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8807 /* Set vertices number for patches */
8808 glPatchParameteri(GL_PATCH_VERTICES, 1);
8814 virtual long Cleanup()
8818 /* Delete programs */
8819 if (0 != m_program_to_test_fs_stage_id)
8821 glDeleteProgram(m_program_to_test_fs_stage_id);
8822 m_program_to_test_fs_stage_id = 0;
8825 if (0 != m_program_to_test_gs_stage_id)
8827 glDeleteProgram(m_program_to_test_gs_stage_id);
8828 m_program_to_test_gs_stage_id = 0;
8831 if (0 != m_program_to_test_tcs_stage_id)
8833 glDeleteProgram(m_program_to_test_tcs_stage_id);
8834 m_program_to_test_tcs_stage_id = 0;
8837 if (0 != m_program_to_test_tes_stage_id)
8839 glDeleteProgram(m_program_to_test_tes_stage_id);
8840 m_program_to_test_tes_stage_id = 0;
8843 if (0 != m_program_to_test_vs_stage_id)
8845 glDeleteProgram(m_program_to_test_vs_stage_id);
8846 m_program_to_test_vs_stage_id = 0;
8849 /* Delete textures */
8850 if (0 != m_texture_to_test_fs_stage_id)
8852 glDeleteTextures(1, &m_texture_to_test_fs_stage_id);
8853 m_texture_to_test_fs_stage_id = 0;
8856 if (0 != m_texture_to_test_gs_stage_id)
8858 glDeleteTextures(1, &m_texture_to_test_gs_stage_id);
8859 m_texture_to_test_gs_stage_id = 0;
8862 if (0 != m_texture_to_test_tcs_stage_id)
8864 glDeleteTextures(1, &m_texture_to_test_tcs_stage_id);
8865 m_texture_to_test_tcs_stage_id = 0;
8868 if (0 != m_texture_to_test_tes_stage_id)
8870 glDeleteTextures(1, &m_texture_to_test_tes_stage_id);
8871 m_texture_to_test_tes_stage_id = 0;
8874 if (0 != m_texture_to_test_vs_stage_id)
8876 glDeleteTextures(1, &m_texture_to_test_vs_stage_id);
8877 m_texture_to_test_vs_stage_id = 0;
8880 /* Delete vertex array object id */
8881 if (0 != m_vertex_array_object_id)
8883 glDeleteVertexArrays(1, &m_vertex_array_object_id);
8884 m_vertex_array_object_id = 0;
8895 if (testFailed == testShaderStage(fragmentShaderStage))
8897 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with fragment shader stage!"
8898 << tcu::TestLog::EndMessage;
8903 if (testFailed == testShaderStage(geometryShaderStage))
8905 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with geometry shader stage!"
8906 << tcu::TestLog::EndMessage;
8911 if (testFailed == testShaderStage(tesselationControlShaderStage))
8913 m_context.getTestContext().getLog() << tcu::TestLog::Message
8914 << "Problems with tesselation control shader stage!"
8915 << tcu::TestLog::EndMessage;
8920 if (testFailed == testShaderStage(tesselationEvalutaionShaderStage))
8922 m_context.getTestContext().getLog() << tcu::TestLog::Message
8923 << "Problems with tesselation evaluation shader stage!"
8924 << tcu::TestLog::EndMessage;
8929 if (testFailed == testShaderStage(vertexShaderStage))
8931 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with vertex shader stage!"
8932 << tcu::TestLog::EndMessage;
8937 if (false == result)
8947 /* Static routines */
8948 /** Provide image format details for given index
8950 * @param index Index
8951 * @param out_details Image format detail instance
8953 static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails& out_details)
8955 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = {
8956 "r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger
8959 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = {
8960 { "rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort> },
8961 { "r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F,
8962 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8963 { "r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint> },
8964 { "rgb10_a2", "image2D", "vec4", GL_RGB10_A2,
8965 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8966 { "rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8967 { "rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8968 { "rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM,
8969 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte> },
8970 { "rg16_snorm", "image2D", "vec4", GL_RG16_SNORM,
8971 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort> },
8972 { "rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI,
8973 ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint> },
8974 { "rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI,
8975 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint> },
8976 { "rg16ui", "uimage2D", "uvec4", GL_RG16UI,
8977 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint> },
8978 { "r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger },
8979 { "rgba8i", "iimage2D", "ivec4", GL_RGBA8I,
8980 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint> },
8981 { "rg16i", "iimage2D", "ivec4", GL_RG16I,
8982 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint> }
8985 static const GLuint n_imageUniformFormatDetails =
8986 sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails);
8988 if (n_imageUniformFormatDetails <= index)
8990 out_details = default_format_details;
8994 out_details = format_details[index];
8998 /** Write name of image uniform at given index to output stream
9000 * @param stream Output stream
9001 * @param index Index
9003 static void writeImageUniformNameToStream(std::ostream& stream, GLuint index)
9006 stream << "u_image_" << index;
9009 /** Write name of variable used to store value loaded from image at given index to output stream
9011 * @param stream Output stream
9012 * @param index Index
9014 static void writeLoadedValueVariableNameToStream(std::ostream& stream, GLuint index)
9016 /* loaded_value_0 */
9017 stream << "loaded_value_" << index;
9020 /** Write name of variable used to store coordinate of texel at given row to output stream
9022 * @param stream Output stream
9023 * @param index Index of image uniform
9024 * @param row Row of image
9026 static void writeCoordinatesVariableNameToStream(std::ostream& stream, GLuint index, GLuint row)
9028 /* row_0_coordinates_0 */
9029 stream << "row_" << row << "_coordinates_" << index;
9032 struct imageUniformDeclaration
9034 imageUniformDeclaration(GLuint index) : m_index(index)
9041 /** Write declaration of image uniform at given index to output stream
9043 * @param stream Output stream
9044 * @param imageUniformDeclaration Declaration details
9048 friend std::ostream& operator<<(std::ostream& stream, const imageUniformDeclaration& declaration)
9050 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9051 getImageUniformDeclarationDetails(declaration.m_index, format_details);
9053 /* layout(r32f) uniform image2D u_image_0; */
9054 stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " ";
9056 ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index);
9063 struct imageLoadCall
9065 imageLoadCall(GLuint index) : m_index(index)
9072 /* Stream operators */
9073 /** Write code that execute imageLoad routine for image at given index to output stream
9075 * @param stream Output stream
9076 * @param load imageLoad call details
9080 friend std::ostream& operator<<(std::ostream& stream, const imageLoadCall& load)
9082 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9083 getImageUniformDeclarationDetails(load.m_index, format_details);
9085 /* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */
9086 stream << format_details.m_color_type << " ";
9088 writeLoadedValueVariableNameToStream(stream, load.m_index);
9090 stream << " = imageLoad(";
9092 writeImageUniformNameToStream(stream, load.m_index);
9096 writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */);
9103 struct imageStoreCall
9105 imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row)
9113 /** Write code that execute imageStore to image at given index to output stream
9115 * @param stream Output stream
9116 * @param store imageStore call details
9120 friend std::ostream& operator<<(std::ostream& stream, const imageStoreCall& store)
9122 /* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */
9123 stream << "imageStore(";
9125 writeImageUniformNameToStream(stream, store.m_index);
9129 writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row);
9131 if (0 == store.m_row)
9140 writeLoadedValueVariableNameToStream(stream, store.m_index);
9146 struct coordinatesVariableDeclaration
9148 coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row)
9155 /** Write declaration of variable for coordinate at given row to output stream
9157 * @param stream Output stream
9158 * @param declaration Declaration details
9162 friend std::ostream& operator<<(std::ostream& stream, const coordinatesVariableDeclaration& declaration)
9164 stream << "const ivec2 ";
9166 writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row);
9168 stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");";
9174 /** Build program to test specified shader stage
9176 * Throws exception in case of any failure
9178 * @param stage Stage id
9180 * @return Program id
9182 GLuint buildProgramToTestShaderStage(shaderStage stage)
9184 static const char* const boilerplate_fragment_shader_code =
9185 "#version 400 core\n"
9186 "#extension GL_ARB_shader_image_load_store : require\n"
9188 "precision highp float;\n"
9195 static const char* const boilerplate_tesselation_evaluation_shader_code =
9196 "#version 400 core\n"
9197 "#extension GL_ARB_shader_image_load_store : require\n"
9199 "precision highp float;\n"
9201 "layout(quads, equal_spacing, ccw) in;\n"
9208 static const char* const boilerplate_vertex_shader_code =
9209 "#version 400 core\n"
9210 "#extension GL_ARB_shader_image_load_store : require\n"
9212 "precision highp float;\n"
9214 "layout(location = 0) in vec4 i_position;\n"
9218 " gl_Position = i_position;\n"
9221 const char* fragment_shader_code = boilerplate_fragment_shader_code;
9222 const char* geometry_shader_code = 0;
9223 bool is_program_built = true;
9224 GLuint program_object_id = 0;
9225 const char* tesselation_control_shader_code = 0;
9226 const char* tesselation_evaluation_shader_code = 0;
9227 std::string tested_shader_stage_code;
9228 const char* vertex_shader_code = boilerplate_vertex_shader_code;
9230 /* Get source code for tested shader stage */
9231 prepareShaderForTestedShaderStage(stage, tested_shader_stage_code);
9233 if (true == tested_shader_stage_code.empty())
9238 /* Set up source code for all required stages */
9241 case fragmentShaderStage:
9242 fragment_shader_code = tested_shader_stage_code.c_str();
9245 case geometryShaderStage:
9246 geometry_shader_code = tested_shader_stage_code.c_str();
9249 case tesselationControlShaderStage:
9250 tesselation_control_shader_code = tested_shader_stage_code.c_str();
9251 tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code;
9254 case tesselationEvalutaionShaderStage:
9255 tesselation_evaluation_shader_code = tested_shader_stage_code.c_str();
9258 case vertexShaderStage:
9259 vertex_shader_code = tested_shader_stage_code.c_str();
9263 TCU_FAIL("Invalid shader stage");
9268 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
9269 geometry_shader_code, fragment_shader_code, &is_program_built);
9271 /* Check if program was built */
9272 if (false == is_program_built)
9274 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
9278 return program_object_id;
9281 /** Create texture to test given shader stage
9283 * Throws exception in case of any failure
9285 * @param stage Stage id
9287 * @return Texture id
9289 GLuint createTextureToTestShaderStage(shaderStage stage)
9291 GLenum error = glGetError();
9292 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9293 GLuint texture_id = 0;
9294 std::vector<GLint> texture_data;
9296 const GLsizei height = 2;
9297 const GLsizei width = max_image_uniforms;
9299 if (m_min_required_image_uniforms > max_image_uniforms)
9304 /* Generate texture id */
9305 glGenTextures(1, &texture_id);
9306 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
9309 glBindTexture(GL_TEXTURE_2D, texture_id);
9310 error = glGetError();
9311 if (GL_NO_ERROR != error)
9313 glDeleteTextures(1, &texture_id);
9314 GLU_EXPECT_NO_ERROR(error, "BindTexture");
9317 /* Prepare storage for texture data */
9318 texture_data.resize(width * height);
9319 for (GLint i = 0; i < max_image_uniforms; ++i)
9321 texture_data[i] = getExpectedValue(i);
9322 texture_data[i + width] = 0;
9325 /* Create first level of texture */
9326 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT,
9328 error = glGetError();
9329 if (GL_NO_ERROR != error)
9331 glDeleteTextures(1, &texture_id);
9332 GLU_EXPECT_NO_ERROR(error, "TexImage2D");
9335 /* Make texture complete */
9336 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
9337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
9338 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9339 error = glGetError();
9340 if (GL_NO_ERROR != error)
9342 glDeleteTextures(1, &texture_id);
9343 GLU_EXPECT_NO_ERROR(error, "TexParameteri");
9350 /** Get value of texel for image at given index
9352 * @param index Index of image uniform
9354 * @return Value of texel
9356 GLint getExpectedValue(GLint index)
9358 // To fix denorm issues with r32f, rg16f and r11f_g11f_b10f
9359 // we set one bit in the exponent of each component of those pixel format
9360 return 0x40104200 + index;
9363 /** Get name of uniform at given index
9365 * @param index Index of uniform
9366 * @param out_name Name of uniform
9368 void getImageUniformName(GLuint index, std::string& out_name)
9370 std::stringstream stream;
9372 writeImageUniformNameToStream(stream, index);
9374 out_name = stream.str();
9377 /** Get maximum number of image uniforms allowed for given shader stage
9379 * @param stage Stage id
9381 * @return Maximum allowed image uniforms
9383 GLint getMaximumImageUniformsForStage(shaderStage stage)
9385 GLint max_image_uniforms = 0;
9390 case fragmentShaderStage:
9391 pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS;
9394 case geometryShaderStage:
9395 pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
9398 case tesselationControlShaderStage:
9399 pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
9402 case tesselationEvalutaionShaderStage:
9403 pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
9406 case vertexShaderStage:
9407 pname = GL_MAX_VERTEX_IMAGE_UNIFORMS;
9411 TCU_FAIL("Invalid shader stage");
9414 glGetIntegerv(pname, &max_image_uniforms);
9415 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
9417 return max_image_uniforms;
9420 /** Prepare source for tested shader stage
9422 * @param stage Stage id
9423 * @param out_code Source code
9425 void prepareShaderForTestedShaderStage(shaderStage stage, std::string& out_code)
9427 GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9428 const char* stage_specific_layout = "";
9429 const char* stage_specific_predicate = "true";
9430 std::stringstream stream;
9432 if (m_min_required_image_uniforms > max_image_uniforms)
9437 /* Expected result follows
9440 * #extension GL_ARB_shader_image_load_store : require
9442 * precision highp float;
9444 * stage_specific_layout goes here
9446 * Uniform declarations go here
9450 * const ivec2 row_0_coordinates(0, 0);
9451 * const ivec2 row_1_coordinates(0, 1);
9453 * For each index <0, GL_MAX_*_IMAGE_UNIFORMS>
9455 * vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates);
9457 * imageStore(u_image_0, row_0_coordinates, -loaded_value_0);
9458 * imageStore(u_image_0, row_1_coordinates, loaded_value_0);
9462 /* Get piece of code specific for stage */
9465 case fragmentShaderStage:
9468 case geometryShaderStage:
9469 stage_specific_layout = "layout(points) in;\n"
9470 "layout(points, max_vertices = 1) out;\n"
9474 case tesselationControlShaderStage:
9475 stage_specific_layout = "layout(vertices = 4) out;\n"
9477 stage_specific_predicate = "gl_InvocationID == 0";
9480 case tesselationEvalutaionShaderStage:
9481 stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n"
9485 case vertexShaderStage:
9489 TCU_FAIL("Invalid shader stage");
9493 stream << "#version 400 core\n"
9494 "#extension GL_ARB_shader_image_load_store : require\n"
9496 "precision highp float;\n"
9498 << stage_specific_layout;
9500 /* Image uniforms declarations */
9501 for (GLint i = 0; i < max_image_uniforms; ++i)
9503 stream << imageUniformDeclaration(i) << "\n";
9511 stream << " if (" << stage_specific_predicate << ")\n";
9514 /* imageLoad and imageStores for each uniform */
9515 for (GLint i = 0; i < max_image_uniforms; ++i)
9517 stream << " " << coordinatesVariableDeclaration(i, 0) << "\n"
9518 << " " << coordinatesVariableDeclaration(i, 1) << "\n"
9520 << " " << imageLoadCall(i) << "\n"
9522 << " " << imageStoreCall(i, 0) << "\n"
9523 << " " << imageStoreCall(i, 1) << "\n";
9525 if (max_image_uniforms > i + 1)
9537 out_code = stream.str();
9540 /** Test given shader stage
9542 * @param stage Stage id
9544 * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms;
9545 * testFailed when test result is negative;
9546 * m_test_passed when test result is positive;
9548 testResult testShaderStage(shaderStage stage)
9550 std::string image_uniform_name;
9551 static const GLint invalid_uniform_location = -1;
9552 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9553 GLenum primitive_mode = GL_POINTS;
9554 GLuint program_id = 0;
9555 testResult result = testPassed;
9556 std::vector<GLint> texture_data;
9557 GLuint texture_id = 0;
9559 static const GLuint height = 2;
9560 const GLuint width = max_image_uniforms;
9562 const GLuint positive_value_index = width;
9563 static const GLuint negated_value_index = 0;
9565 if (m_min_required_image_uniforms > max_image_uniforms)
9567 return testNotSupported;
9570 /* Select program and texture ids for given stage */
9573 case fragmentShaderStage:
9574 program_id = m_program_to_test_fs_stage_id;
9575 texture_id = m_texture_to_test_fs_stage_id;
9578 case geometryShaderStage:
9579 program_id = m_program_to_test_gs_stage_id;
9580 texture_id = m_texture_to_test_gs_stage_id;
9583 case tesselationControlShaderStage:
9584 primitive_mode = GL_PATCHES;
9585 program_id = m_program_to_test_tcs_stage_id;
9586 texture_id = m_texture_to_test_tcs_stage_id;
9589 case tesselationEvalutaionShaderStage:
9590 primitive_mode = GL_PATCHES;
9591 program_id = m_program_to_test_tes_stage_id;
9592 texture_id = m_texture_to_test_tes_stage_id;
9595 case vertexShaderStage:
9596 program_id = m_program_to_test_vs_stage_id;
9597 texture_id = m_texture_to_test_vs_stage_id;
9601 TCU_FAIL("Invalid shader stage");
9605 glUseProgram(program_id);
9606 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
9608 /* Bind texture to image units */
9609 for (GLint i = 0; i < max_image_uniforms; ++i)
9611 imageFormatDetails format_details;
9612 getImageUniformDeclarationDetails(i, format_details);
9614 glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9615 GL_READ_WRITE, format_details.m_image_unit_format);
9616 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9619 /* Set all image uniforms to corresponding image units */
9620 for (GLint i = 0; i < max_image_uniforms; ++i)
9623 getImageUniformName(i, image_uniform_name);
9626 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str());
9627 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
9629 if (invalid_uniform_location == image_uniform_location)
9631 throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__,
9635 /* Set uniform value */
9636 glUniform1i(image_uniform_location, i /* image_unit */);
9637 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
9641 glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */);
9642 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
9644 glMemoryBarrier(GL_ALL_BARRIER_BITS);
9646 texture_data.resize(width * height);
9648 /* Get texture data */
9649 glBindTexture(GL_TEXTURE_2D, texture_id);
9650 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
9652 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]);
9653 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
9655 /* Verify each image uniform */
9656 for (GLint i = 0; i < max_image_uniforms; ++i)
9658 imageFormatDetails format_details;
9659 getImageUniformDeclarationDetails(i, format_details);
9662 format_details.m_verification_routine(getExpectedValue(i), texture_data[positive_value_index + i],
9663 texture_data[negated_value_index + i]))
9665 m_context.getTestContext().getLog()
9666 << tcu::TestLog::Message << "Invalid result!"
9667 << " Image format: " << format_details.m_image_format << " Original value: "
9668 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i)
9669 << " Copied value: "
9670 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9671 << texture_data[positive_value_index + i] << " Negated value: "
9672 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9673 << texture_data[negated_value_index + i] << tcu::TestLog::EndMessage;
9675 result = testFailed;
9683 /** Verifies if original_value, positive_value and negated_value match
9685 * @tparam T Type used during verification process, it should match float values by size
9687 * @param original_value Original value of texel, used when creating a texture
9688 * @param positive_value Value stored by shader as read
9689 * @param negated_value Value stored by shader after negation
9691 * @return true if values match, false otherwise
9693 template <typename T>
9694 static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value)
9696 if (original_value != positive_value)
9701 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9702 static const GLuint sign_bit_index = sizeof(T) * 8 - 1; /* 7, 15, 31 */
9703 static const T sign_bit_mask = 1 << sign_bit_index; /* 0x80.. */
9704 static const T sign_bit_inv_mask = (T)~sign_bit_mask; /* 0x7f.. */
9706 const T* positive_elements = (T*)&positive_value;
9707 const T* negated_elements = (T*)&negated_value;
9709 for (GLuint i = 0; i < n_elements; ++i)
9711 const T positive_element = positive_elements[i];
9712 const T negated_element = negated_elements[i];
9714 const T positive_sign_bit = positive_element & sign_bit_mask;
9715 const T negated_sign_bit = negated_element & sign_bit_mask;
9717 const T positive_data = positive_element & sign_bit_inv_mask;
9718 const T negated_data = negated_element & sign_bit_inv_mask;
9720 /* Compare data bits */
9721 if (positive_data != negated_data)
9726 /* Verify that sign bit is inverted */
9727 if (positive_sign_bit == negated_sign_bit)
9736 /** Verifies if original_value, positive_value and negated_value match
9738 * @tparam T Type used during verification process, it should match float values by size
9740 * @param original_value Original value of texel, used when creating a texture
9741 * @param positive_value Value stored by shader as read
9742 * @param negated_value Value stored by shader after negation
9744 * @return true if values match, false otherwise
9746 template <typename T>
9747 static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value)
9749 if (original_value != positive_value)
9754 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9756 const T* positive_elements = (T*)&positive_value;
9757 const T* negated_elements = (T*)&negated_value;
9759 for (GLuint i = 0; i < n_elements; ++i)
9761 const T positive_element = positive_elements[i];
9762 const T negated_element = negated_elements[i];
9764 /* Compare data bits */
9765 if (positive_element != -negated_element)
9774 /** Verifies if original_value, positive_value and negated_value match
9776 * @tparam R Number of bits for red channel
9777 * @tparam G Number of bits for green channel
9778 * @tparam B Number of bits for blue channel
9779 * @tparam A Number of bits for alpha channel
9781 * @param original_value Original value of texel, used when creating a texture
9782 * @param positive_value Value stored by shader as read
9783 * @param negated_value Value stored by shader after negation
9785 * @return true if values match, false otherwise
9787 template <GLuint R, GLuint G, GLuint B, GLuint A, typename T>
9788 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9790 if (original_value != positive_value)
9795 Integer<T, R, 0> positive_red(positive_value);
9796 Integer<T, R, 0> negated_red(negated_value);
9798 Integer<T, G, R> positive_green(positive_value);
9799 Integer<T, G, R> negated_green(negated_value);
9801 Integer<T, B, R + G> positive_blue(positive_value);
9802 Integer<T, B, R + G> negated_blue(negated_value);
9804 Integer<T, A, R + G + B> positive_alpha(positive_value);
9805 Integer<T, A, R + G + B> negated_alpha(negated_value);
9807 if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) ||
9808 ((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) ||
9809 ((0 != G) && (positive_green.GetNegated() != negated_green.Get())) ||
9810 ((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get())))
9818 /** Verifies if original_value, positive_value and negated_value match
9820 * @param original_value Original value of texel, used when creating a texture
9821 * @param positive_value Value stored by shader as read
9822 * @param negated_value Value stored by shader after negation
9824 * @return true if values match, false otherwise
9826 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9828 if (original_value != positive_value)
9833 if (positive_value != -negated_value)
9841 /** Verifies if original_value, positive_value and negated_value match
9843 * @param original_value Original value of texel, used when creating a texture
9844 * @param positive_value Value stored by shader as read
9845 * @param negated_value Value stored by shader after negation
9847 * @return true if values match, false otherwise
9849 template <typename T>
9850 static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value)
9852 if (original_value != positive_value)
9857 if (0 != negated_value)
9866 /** Test "Early fragment tests" description follows.
9868 * BasicGLSLEarlyFragTests verifies that:
9869 * - early z test is applied when enabled,
9870 * - early z test is not applied when disabled.
9872 * Proposed modifications:
9873 * - verify that early z test does not discard all fragments when enabled,
9874 * - verify that early stencil test is applied when enabled,
9875 * - verify that early stencil test does not discard all fragments when
9877 * - verify that early stencil test is not applied when disabled.
9880 * - prepare 2 programs that store 1.0 at red channel to image in fragment
9882 * a) one program should enable early fragment tests
9883 * ("layout(early_fragment_tests) in;"),
9884 * b) second program should disable early fragment tests,
9885 * - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL
9886 * depth-stencil attachments,
9887 * - prepare 2D texture 64x64 R32F,
9888 * - enable depth test,
9889 * - verify that early z test is applied when enabled:
9890 * - use program enabling early fragment tests,
9891 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9892 * - fill texture with zeros,
9893 * - bind texture to image uniform,
9894 * - draw "full screen" quad (left bottom corner at -1,-1 and right top
9895 * corner at 1,1) at z: 0.75
9896 * - verify that texture is still filled with zeros,
9897 * - verify that early z test does not discard all fragments:
9898 * - use program enabling early fragment tests,
9899 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9900 * - fill texture with zeros,
9901 * - bind texture to image uniform,
9902 * - draw "full screen" quad at z: 0.25
9903 * - verify that texture is now filled with 1.0,
9904 * -verify that early z test is not applied when disabled:
9905 * - use program disabling early fragment tests,
9906 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9907 * - fill texture with zeros,
9908 * - bind texture to image uniform,
9909 * - draw "full screen" quad at z: 0.75
9910 * - verify that texture is now filled with 1.0.
9911 * - disable depth test
9912 * - enable stencil test
9913 * - verify that early stencil test is applied when enabled:
9914 * - use program enabling early fragment tests,
9915 * - clean frame buffer with color: 0, stencil: 0 and depth 1,
9916 * - fill texture with zeros,
9917 * - set stencil test to:
9918 * - <func> to GL_LESS,
9920 * - <mask> 0xffffffff,
9921 * - bind texture to image uniform,
9922 * - draw "full screen" quad at z: 0,
9923 * - verify that texture is still filled with zeros,
9924 * - verify that early stencil test does not discard all fragments:
9925 * - use program enabling early fragment tests,
9926 * - clean frame buffer with color: 0, stencil: 128 and depth 1,
9927 * - fill texture with zeros,
9928 * - set stencil test to:
9929 * - <func> to GL_LESS,
9931 * - <mask> 0xffffffff,
9932 * - bind texture to image uniform,
9933 * - draw "full screen" quad at z: 0,
9934 * - verify that texture is now filled with 1.0,
9935 * - verify that early stencil test is not applied when disabled:
9936 * - use program disabling early fragment tests,
9937 * - clean frame buffer with color: 0, stencil: 0 and depth 1,
9938 * - fill texture with zeros,
9939 * - set stencil test to:
9940 * - <func> to GL_LESS,
9942 * - <mask> 0xffffffff,
9943 * - bind texture to image uniform,
9944 * - draw "full screen" quad at z: 0,
9945 * - verify that texture is now filled with 1.0
9947 class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase
9951 GLuint m_image_edge;
9952 static const GLint m_invalid_uniform_location = -1;
9955 /** Store id and uniform locations for a single program object
9958 struct programDetails
9960 GLint m_depth_uniform_location;
9961 GLint m_image_uniform_location;
9962 GLuint m_program_id;
9965 : m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9966 , m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9969 /* Nothing to be done here */
9974 /* Storage for texture data */
9975 std::vector<GLfloat> m_clean_texture_data;
9976 std::vector<GLfloat> m_extracted_texture_data;
9978 /* Program details */
9979 programDetails m_disabled_early_tests;
9980 programDetails m_enabled_early_tests;
9982 /* Ids of GL objects */
9983 GLuint m_color_renderbuffer_id;
9984 GLuint m_depth_stencil_renderbuffer_id;
9985 GLuint m_framebuffer_id;
9986 GLuint m_texture_id;
9987 GLuint m_vertex_array_object_id;
9991 ImageLoadStoreEarlyFragmentTestsTest()
9993 , m_color_renderbuffer_id(0)
9994 , m_depth_stencil_renderbuffer_id(0)
9995 , m_framebuffer_id(0)
9997 , m_vertex_array_object_id(0)
9999 /* Nothing to be done here */
10002 /* Methods inherited from SubcaseBase */
10003 virtual long Cleanup()
10005 /* Restore defaults */
10006 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
10007 glBindRenderbuffer(GL_RENDERBUFFER, 0);
10008 glBindTexture(GL_TEXTURE_2D, 0);
10009 glBindVertexArray(0);
10010 glDisable(GL_DEPTH_TEST);
10011 glDisable(GL_STENCIL_TEST);
10014 /* Delete objects */
10015 if (0 != m_disabled_early_tests.m_program_id)
10017 glDeleteProgram(m_disabled_early_tests.m_program_id);
10018 m_disabled_early_tests.m_program_id = 0;
10021 if (0 != m_enabled_early_tests.m_program_id)
10023 glDeleteProgram(m_enabled_early_tests.m_program_id);
10024 m_enabled_early_tests.m_program_id = 0;
10027 if (0 != m_color_renderbuffer_id)
10029 glDeleteRenderbuffers(1, &m_color_renderbuffer_id);
10030 m_color_renderbuffer_id = 0;
10033 if (0 != m_depth_stencil_renderbuffer_id)
10035 glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10036 m_depth_stencil_renderbuffer_id = 0;
10039 if (0 != m_framebuffer_id)
10041 glDeleteFramebuffers(1, &m_framebuffer_id);
10042 m_framebuffer_id = 0;
10045 if (0 != m_texture_id)
10047 glDeleteTextures(1, &m_texture_id);
10051 if (0 != m_vertex_array_object_id)
10053 glDeleteVertexArrays(1, &m_vertex_array_object_id);
10054 m_vertex_array_object_id = 0;
10063 bool result = true;
10065 /* Bind texture to first image unit */
10066 glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
10067 GL_READ_WRITE, GL_R32F);
10068 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
10070 /* Run tests for depth test */
10071 if (false == testEarlyZ())
10076 /* Run tests for stencil test */
10077 if (false == testEarlyStencil())
10082 /* Return ERROR if any problem was found */
10083 if (false == result)
10092 virtual long Setup()
10094 m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
10096 /* Prepare storage for texture data */
10097 m_clean_texture_data.resize(m_image_edge * m_image_edge);
10098 m_extracted_texture_data.resize(m_image_edge * m_image_edge);
10100 /* Prepare programs, framebuffer and texture */
10102 createFramebuffer();
10105 /* Generate vertex array object */
10106 glGenVertexArrays(1, &m_vertex_array_object_id);
10107 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
10109 /* Bind vertex array object */
10110 glBindVertexArray(m_vertex_array_object_id);
10111 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
10113 /* Set clear color */
10114 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
10115 GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor");
10122 /** Build two programs: with enabled and disabled early fragment tests
10125 void buildPrograms()
10127 static const char* const fragment_shader_with_disabled_early_tests =
10128 "#version 400 core\n"
10129 "#extension GL_ARB_shader_image_load_store : require\n"
10131 "precision highp float;\n"
10133 "layout(r32f) uniform image2D u_image;\n"
10137 " vec4 color = vec4(1.0, 0, 0, 0);\n"
10139 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10144 static const char* const fragment_shader_with_enabled_early_tests =
10145 "#version 400 core\n"
10146 "#extension GL_ARB_shader_image_load_store : require\n"
10148 "precision highp float;\n"
10150 "layout(early_fragment_tests) in;\n"
10152 "layout(r32f) uniform image2D u_image;\n"
10156 " vec4 color = vec4(1.0, 0, 0, 0);\n"
10158 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10163 static const char* const geometry_shader_code = "#version 400 core\n"
10164 "#extension GL_ARB_shader_image_load_store : require\n"
10166 "precision highp float;\n"
10168 "layout(points) in;\n"
10169 "layout(triangle_strip, max_vertices = 4) out;\n"
10171 "uniform float u_depth;\n"
10175 " // Left-bottom\n"
10176 " gl_Position = vec4(-1, -1, u_depth, 1);\n"
10180 " gl_Position = vec4(-1, 1, u_depth, 1);\n"
10183 " // Right-bottom\n"
10184 " gl_Position = vec4( 1, -1, u_depth, 1);\n"
10188 " gl_Position = vec4( 1, 1, u_depth, 1);\n"
10192 static const char* const vertex_shader_code = "#version 400 core\n"
10193 "#extension GL_ARB_shader_image_load_store : require\n"
10195 "precision highp float;\n"
10201 prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code,
10202 m_disabled_early_tests);
10204 prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code,
10205 m_enabled_early_tests);
10208 /** Fill texture with zeros
10211 void cleanTexture()
10213 glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge,
10214 GL_RED, GL_FLOAT, &m_clean_texture_data[0]);
10215 GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D");
10218 /** Create and bind (draw) framebuffer with color and depth-stencil attachments
10221 void createFramebuffer()
10223 /* Generate render buffers */
10224 glGenRenderbuffers(1, &m_color_renderbuffer_id);
10225 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10227 glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10228 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10230 /* Generate and bind framebuffer object */
10231 glGenFramebuffers(1, &m_framebuffer_id);
10232 GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers");
10234 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
10235 GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer");
10237 /* Prepare color render buffer */
10238 glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id);
10239 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10241 glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge);
10242 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10244 /* Set up color attachment */
10245 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id);
10246 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10248 /* Prepare depth-stencil render buffer */
10249 glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id);
10250 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10252 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge);
10253 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10255 /* Set up depth-stencil attachment */
10256 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10257 m_depth_stencil_renderbuffer_id);
10258 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10261 /** Create 2D R32F texture
10264 void createTexture()
10266 glGenTextures(1, &m_texture_id);
10267 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
10269 glBindTexture(GL_TEXTURE_2D, m_texture_id);
10270 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
10272 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge);
10273 GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D");
10276 /** Extracts red channel from texture and verify if all texels are set to specified value
10278 * @param value Expected value
10280 * @return true if all texel match expected value, false otherwise
10282 bool isTextureFilledWithValue(GLfloat value)
10284 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]);
10285 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
10287 for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i)
10289 if (value != m_extracted_texture_data[i])
10291 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i
10292 << " has invalid value: " << m_extracted_texture_data[i]
10293 << " expected: " << value << tcu::TestLog::EndMessage;
10302 /** Build program, extract location of uniforms and store results in programDetails instance
10304 * Throws tcu::InternalError if uniforms are inactive
10306 * @param fragment_shader_code Source of fragment shader
10307 * @param geometry_shader_code Source of geometry shader
10308 * @param vertex_shader_code Source of vertex shader
10309 * @param out_program_details Instance of programDetails
10311 void prepareProgramDetails(const char* fragment_shader_code, const char* geometry_shader_code,
10312 const char* vertex_shader_code, programDetails& out_program_details)
10314 static const char* const depth_uniform_name = "u_depth";
10315 static const char* const image_uniform_name = "u_image";
10316 bool is_program_built = true;
10318 GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code,
10319 fragment_shader_code, &is_program_built);
10321 if (false == is_program_built)
10323 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
10326 /* Get depth uniform location */
10327 GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name);
10328 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10330 if (m_invalid_uniform_location == depth_uniform_location)
10332 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10335 /* Get image uniform location */
10336 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name);
10337 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10339 if (m_invalid_uniform_location == image_uniform_location)
10341 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10344 /* Store results */
10345 out_program_details.m_depth_uniform_location = depth_uniform_location;
10346 out_program_details.m_image_uniform_location = image_uniform_location;
10347 out_program_details.m_program_id = program_id;
10350 /** Test if early fragment stencil test works as expected.
10352 * @return true if successful, false otherwise
10354 bool testEarlyStencil()
10356 bool result = true;
10358 glEnable(GL_STENCIL_TEST);
10359 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10361 glClearDepthf(1.0f);
10362 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10364 /* verify that early stencil test is applied when enabled */
10366 glUseProgram(m_enabled_early_tests.m_program_id);
10367 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10370 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10372 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10373 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10377 glStencilFunc(GL_LESS, 128, 0xffffffff);
10378 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10380 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10381 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10383 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10384 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10386 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10387 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10389 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10390 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10392 if (false == isTextureFilledWithValue(0.0f))
10394 m_context.getTestContext().getLog() << tcu::TestLog::Message
10395 << "Problem with early stencil test. It is not applied"
10396 << tcu::TestLog::EndMessage;
10402 /* verify that early stencil test does not discard all fragments */
10404 glClearStencil(128);
10405 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10407 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10408 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10412 glStencilFunc(GL_LESS, 0, 0xffffffff);
10413 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10415 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10416 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10418 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10419 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10421 if (false == isTextureFilledWithValue(1.0f))
10423 m_context.getTestContext().getLog()
10424 << tcu::TestLog::Message
10425 << "Problem with early stencil test. It discards fragments, that shall be drawn"
10426 << tcu::TestLog::EndMessage;
10432 /* verify that early stencil test is not applied when disabled */
10434 glUseProgram(m_disabled_early_tests.m_program_id);
10435 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10438 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10440 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10441 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10445 glStencilFunc(GL_LESS, 128, 0xffffffff);
10446 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10448 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10449 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10451 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10452 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10454 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10455 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10457 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10458 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10460 if (false == isTextureFilledWithValue(1.0f))
10462 m_context.getTestContext().getLog() << tcu::TestLog::Message
10463 << "Problem with early stencil test. It is applied when disabled"
10464 << tcu::TestLog::EndMessage;
10470 glDisable(GL_STENCIL_TEST);
10471 GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10477 /** Test if early fragment depth test works as expected.
10479 * @return true if successful, false otherwise
10483 bool result = true;
10485 glEnable(GL_DEPTH_TEST);
10486 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10488 glClearDepthf(0.5f);
10489 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10492 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10494 /* verify that early z test is applied when enabled */
10496 glUseProgram(m_enabled_early_tests.m_program_id);
10497 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10499 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10500 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10504 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10505 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10507 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10508 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10510 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10511 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10513 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10514 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10516 if (false == isTextureFilledWithValue(0.0f))
10518 m_context.getTestContext().getLog() << tcu::TestLog::Message
10519 << "Problem with early z test. It is not applied"
10520 << tcu::TestLog::EndMessage;
10526 /* verify that early z test does not discard all fragments */
10528 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10529 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10533 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10534 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10536 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */);
10537 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10539 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10540 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10542 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10543 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10545 if (false == isTextureFilledWithValue(1.0f))
10547 m_context.getTestContext().getLog()
10548 << tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn"
10549 << tcu::TestLog::EndMessage;
10555 /* verify that early z test is not applied when disabled */
10557 glUseProgram(m_disabled_early_tests.m_program_id);
10558 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10560 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10561 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10565 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10566 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10568 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10569 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10571 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10572 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10574 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10575 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10577 if (false == isTextureFilledWithValue(1.0f))
10579 m_context.getTestContext().getLog() << tcu::TestLog::Message
10580 << "Problem with early z test. It is applied when disabled"
10581 << tcu::TestLog::EndMessage;
10587 glDisable(GL_DEPTH_TEST);
10588 GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10595 //-----------------------------------------------------------------------------
10596 // 4.1 NegativeUniform
10597 //-----------------------------------------------------------------------------
10598 class NegativeUniform : public ShaderImageLoadStoreBase
10602 virtual long Setup()
10610 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
10611 " gl_Position = i_position;" NL "}";
10612 const char* glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
10613 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(0.0));" NL
10614 " discard;" NL "}";
10615 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
10617 GLint max_image_units;
10618 glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
10619 glUseProgram(m_program);
10621 glUniform1i(glGetUniformLocation(m_program, "g_image"), -1);
10622 if (glGetError() != GL_INVALID_VALUE)
10624 m_context.getTestContext().getLog()
10625 << tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero."
10626 << tcu::TestLog::EndMessage;
10629 glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units);
10630 if (glGetError() != GL_INVALID_VALUE)
10632 m_context.getTestContext().getLog()
10633 << tcu::TestLog::Message
10634 << "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of "
10635 << "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
10640 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10641 if (glGetError() != GL_INVALID_VALUE)
10643 m_context.getTestContext().getLog()
10644 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10645 << tcu::TestLog::EndMessage;
10648 i = max_image_units + 1;
10649 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10650 if (glGetError() != GL_INVALID_VALUE)
10652 m_context.getTestContext().getLog()
10653 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is greater "
10654 "than or equal to the value of MAX_IMAGE_UNITS."
10655 << tcu::TestLog::EndMessage;
10659 glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
10660 if (glGetError() != GL_INVALID_OPERATION)
10662 m_context.getTestContext().getLog()
10663 << tcu::TestLog::Message
10664 << "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable."
10665 << tcu::TestLog::EndMessage;
10668 glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
10669 if (glGetError() != GL_INVALID_OPERATION)
10671 m_context.getTestContext().getLog()
10672 << tcu::TestLog::Message
10673 << "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable."
10674 << tcu::TestLog::EndMessage;
10681 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1);
10682 if (glGetError() != GL_INVALID_VALUE)
10684 m_context.getTestContext().getLog()
10685 << tcu::TestLog::Message
10686 << "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero."
10687 << tcu::TestLog::EndMessage;
10690 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units);
10691 if (glGetError() != GL_INVALID_VALUE)
10693 m_context.getTestContext().getLog()
10694 << tcu::TestLog::Message
10695 << "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the "
10696 "value of MAX_IMAGE_UNITS."
10697 << tcu::TestLog::EndMessage;
10702 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10703 if (glGetError() != GL_INVALID_VALUE)
10705 m_context.getTestContext().getLog()
10706 << tcu::TestLog::Message
10707 << "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10708 << tcu::TestLog::EndMessage;
10711 ii = max_image_units + 1;
10712 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10713 if (glGetError() != GL_INVALID_VALUE)
10715 m_context.getTestContext().getLog()
10716 << tcu::TestLog::Message << "glProgramUniform1iv should generate INVALID_VALUE when <value> "
10717 "is greater than or equal to the value of MAX_IMAGE_UNITS."
10718 << tcu::TestLog::EndMessage;
10722 glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
10723 if (glGetError() != GL_INVALID_OPERATION)
10725 m_context.getTestContext().getLog()
10726 << tcu::TestLog::Message << "glProgramUniform1ui should generate INVALID_OPERATION if the "
10727 "location refers to an image variable."
10728 << tcu::TestLog::EndMessage;
10731 glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
10732 if (glGetError() != GL_INVALID_OPERATION)
10734 m_context.getTestContext().getLog()
10735 << tcu::TestLog::Message << "glProgramUniform2i should generate INVALID_OPERATION if the "
10736 "location refers to an image variable."
10737 << tcu::TestLog::EndMessage;
10745 virtual long Cleanup()
10748 glDeleteProgram(m_program);
10752 //-----------------------------------------------------------------------------
10753 // 4.2 NegativeBind
10754 //-----------------------------------------------------------------------------
10755 class NegativeBind : public ShaderImageLoadStoreBase
10757 virtual long Setup()
10764 glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10765 if (glGetError() != GL_INVALID_VALUE)
10767 m_context.getTestContext().getLog()
10768 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> is "
10769 "greater than or equal to the value of MAX_IMAGE_UNITS."
10770 << tcu::TestLog::EndMessage;
10774 glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10775 if (glGetError() != GL_INVALID_VALUE)
10777 m_context.getTestContext().getLog()
10778 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> is not "
10779 "the name of an existing texture object."
10780 << tcu::TestLog::EndMessage;
10784 glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234);
10785 if (glGetError() != GL_INVALID_VALUE)
10787 m_context.getTestContext().getLog()
10788 << tcu::TestLog::Message
10789 << "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format."
10790 << tcu::TestLog::EndMessage;
10796 virtual long Cleanup()
10801 //-----------------------------------------------------------------------------
10802 // 4.3 NegativeCompileErrors
10803 //-----------------------------------------------------------------------------
10804 class NegativeCompileErrors : public ShaderImageLoadStoreBase
10808 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10809 "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
10810 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10813 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10814 "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
10815 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10818 if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL
10819 "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
10820 " imageStore(g_image, ivec2(0), i_color);" NL " o_color = i_color;" NL "}"))
10823 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL
10824 "void main() {" NL " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10827 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10828 "readonly uniform image2D g_image;" NL "void main() {" NL
10829 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10832 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10833 "layout(rg16i) uniform image1D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}"))
10836 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10837 "layout(rg16) uniform iimage2D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}"))
10840 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10841 "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL
10842 " imageAtomicAdd(g_image, ivec2(1), 10);" NL " o_color = vec4(1.0);" NL "}"))
10845 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10846 "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL
10847 " imageAtomicAdd(g_image, ivec2(1), 1u);" NL " o_color = vec4(1.0);" NL "}"))
10850 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10851 "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL
10852 " imageStore(g_image, ivec3(1), ivec4(1));" NL " o_color = vec4(1.0);" NL "}"))
10855 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10856 "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL
10857 " imageStore(g_image, ivec3(0), uvec4(1));" NL " o_color = vec4(1.0);" NL "}"))
10860 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10861 "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL
10862 " return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL " o_color = Load(g_image);" NL
10869 bool Compile(const std::string& source)
10871 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
10873 const char* const src = source.c_str();
10874 glShaderSource(sh, 1, &src, NULL);
10875 glCompileShader(sh);
10878 glGetShaderInfoLog(sh, sizeof(log), NULL, log);
10879 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
10880 << log << tcu::TestLog::EndMessage;
10883 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
10884 glDeleteShader(sh);
10886 if (status == GL_TRUE)
10888 m_context.getTestContext().getLog()
10889 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
10896 //-----------------------------------------------------------------------------
10897 // 4.4 NegativeLinkErrors
10898 //-----------------------------------------------------------------------------
10899 class NegativeLinkErrors : public ShaderImageLoadStoreBase
10903 if (!SupportedInVS(1))
10904 return NOT_SUPPORTED;
10906 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10907 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10908 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}",
10909 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10910 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL
10911 " imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}"))
10914 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10915 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10916 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}",
10917 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10918 "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL
10919 " imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}"))
10925 bool Link(const std::string& vs, const std::string& fs)
10927 const GLuint p = glCreateProgram();
10929 const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
10930 glAttachShader(p, vsh);
10931 glDeleteShader(vsh);
10932 const char* const vssrc = vs.c_str();
10933 glShaderSource(vsh, 1, &vssrc, NULL);
10934 glCompileShader(vsh);
10936 const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
10937 glAttachShader(p, fsh);
10938 glDeleteShader(fsh);
10939 const char* const fssrc = fs.c_str();
10940 glShaderSource(fsh, 1, &fssrc, NULL);
10941 glCompileShader(fsh);
10944 glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
10945 if (status == GL_FALSE)
10947 glDeleteProgram(p);
10948 m_context.getTestContext().getLog()
10949 << tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
10952 glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
10953 if (status == GL_FALSE)
10955 glDeleteProgram(p);
10956 m_context.getTestContext().getLog()
10957 << tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
10964 glGetProgramInfoLog(p, sizeof(log), NULL, log);
10965 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
10966 << log << tcu::TestLog::EndMessage;
10968 glGetProgramiv(p, GL_LINK_STATUS, &status);
10969 glDeleteProgram(p);
10971 if (status == GL_TRUE)
10973 m_context.getTestContext().getLog()
10974 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
10982 /** Negative Test "Active image uniform limits", description follows.
10984 * Program that exceeds resource limits should not compile and/or link.
10987 * - try to compile and link a program that uses too many image uniforms in
10988 * fragment shader stage,
10989 * - try to compile and link a program that uses too many image uniforms in
10990 * vertex shader stage,
10991 * - try to compile and link a program that uses too many image uniforms in
10992 * tessellation control shader stage,
10993 * - try to compile and link a program that uses too many image uniforms in
10994 * tessellation evaluation shader stage,
10995 * - try to compile and link a program that uses too many image uniforms in
10996 * geometry shader stage,
10997 * - try to compile and link a program that uses too many image uniforms in all
10998 * shader stages combined, any single stage should not exceed its limits, this
10999 * step might be impossible to fulfill.
11001 * Test should use the following declaration of image uniforms:
11002 * layout(r32i) uniform iimage2D u_image[N_UNIFORMS];
11004 * For cases where limit for single stage is tested, N_UNIFORMS should be
11005 * defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant
11006 * corresponding to tested shader stage.
11008 * For case where limit for combined stages is tested:
11009 * - u_image name should be appended with the name of shader stage, like
11011 * - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where
11012 * gl_Max*ImageUniforms is constant corresponding to tested shader stage,
11013 * - compilation and linking shall succeed, when sum of all
11014 * gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to
11015 * gl_MaxCombinedImageUniforms.
11017 * All defined image uniforms have to be active. Each shader stage that declare
11018 * image uniforms should include following code snippet:
11020 * for (int i = 0; i < N_UNIFORMS; ++i)
11022 * value = imageAtomicAdd(u_image[i], coord, value);
11025 class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase
11030 bool m_result_for_combined;
11031 bool m_result_for_fragment_shader;
11032 bool m_result_for_geometry_shader;
11033 bool m_result_for_tesselation_control_shader;
11034 bool m_result_for_tesselatioon_evaluation_shader;
11035 bool m_result_for_vertex_shader;
11039 ImageLoadStoreUniformLimitsTest()
11040 : m_result_for_combined(false)
11041 , m_result_for_fragment_shader(false)
11042 , m_result_for_geometry_shader(false)
11043 , m_result_for_tesselation_control_shader(false)
11044 , m_result_for_tesselatioon_evaluation_shader(false)
11045 , m_result_for_vertex_shader(false)
11047 /* Nothing to be done */
11050 /* Methods inherited from SubcaseBase */
11051 virtual long Cleanup()
11059 m_context.getTestContext().getLog() << tcu::TestLog::Message
11060 << "This test tries to build invalid programs, expect error messages about "
11061 "exceeded number of active image uniforms"
11062 << tcu::TestLog::EndMessage;
11064 testFragmentShaderStage();
11065 testGeometryShaderStage();
11066 testTesselationControlShaderStage();
11067 testTesselationEvaluationShaderStage();
11068 testVertexShaderStage();
11069 testCombinedShaderStages();
11071 /* Return error if any stage failed */
11072 if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) ||
11073 (false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) ||
11074 (false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader))
11083 virtual long Setup()
11090 /** Test fragment shader stage
11093 void testFragmentShaderStage()
11095 static const char* const fragment_shader_code =
11096 "#version 400 core\n"
11097 "#extension GL_ARB_shader_image_load_store : require\n"
11099 "precision highp float;\n"
11101 "#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n"
11103 "flat in ivec2 vs_fs_coord;\n"
11105 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11109 " int value = 1;\n"
11111 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11113 " value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n"
11119 static const char* const vertex_shader_code = "#version 400 core\n"
11120 "#extension GL_ARB_shader_image_load_store : require\n"
11122 "precision highp float;\n"
11124 " in ivec2 vs_in_coord;\n"
11125 "flat out ivec2 vs_fs_coord;\n"
11129 " vs_fs_coord = vs_in_coord;\n"
11132 m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11133 0 /* tesselation_control_shader_code */,
11134 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11136 if (false == m_result_for_fragment_shader)
11138 m_context.getTestContext().getLog()
11139 << tcu::TestLog::Message
11140 << "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully."
11141 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11142 << fragment_shader_code << tcu::TestLog::EndMessage;
11146 /** Test geometry shader stage
11149 void testGeometryShaderStage()
11151 static const char* const fragment_shader_code = "#version 400 core\n"
11152 "#extension GL_ARB_shader_image_load_store : require\n"
11154 "precision highp float;\n"
11161 static const char* const geometry_shader_code =
11162 "#version 400 core\n"
11163 "#extension GL_ARB_shader_image_load_store : require\n"
11165 "precision highp float;\n"
11167 "layout(points) in;\n"
11168 "layout(points, max_vertices = 1) out;\n"
11170 "#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n"
11172 "in ivec2 vs_gs_coord[];\n"
11174 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11178 " int value = 1;\n"
11180 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11182 " value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\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_gs_coord;\n"
11196 " vs_gs_coord = vs_in_coord;\n"
11199 m_result_for_geometry_shader =
11200 !doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */,
11201 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11203 if (false == m_result_for_geometry_shader)
11205 m_context.getTestContext().getLog()
11206 << tcu::TestLog::Message
11207 << "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully."
11208 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11209 << geometry_shader_code << tcu::TestLog::EndMessage;
11213 /** Test tesselation control shader stage
11216 void testTesselationControlShaderStage()
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_control_shader_code =
11229 "#version 400 core\n"
11230 "#extension GL_ARB_shader_image_load_store : require\n"
11232 "precision highp float;\n"
11234 "layout(vertices = 4) out;\n"
11236 "#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n"
11238 "in ivec2 vs_tcs_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_tcs_coord[0], value);\n"
11252 static const char* const tesselation_evaluation_shader_code =
11253 "#version 400 core\n"
11254 "#extension GL_ARB_shader_image_load_store : require\n"
11256 "precision highp float;\n"
11258 "layout(quads, equal_spacing, ccw) in;\n"
11264 static const char* const vertex_shader_code = "#version 400 core\n"
11265 "#extension GL_ARB_shader_image_load_store : require\n"
11267 "precision highp float;\n"
11269 "in ivec2 vs_in_coord;\n"
11270 "out ivec2 vs_tcs_coord;\n"
11274 " vs_tcs_coord = vs_in_coord;\n"
11277 m_result_for_tesselation_control_shader =
11278 !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code,
11279 tesselation_evaluation_shader_code, vertex_shader_code);
11281 if (false == m_result_for_tesselation_control_shader)
11283 m_context.getTestContext().getLog()
11284 << tcu::TestLog::Message
11285 << "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully."
11286 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11287 << tesselation_control_shader_code << tcu::TestLog::EndMessage;
11291 /** Test teselation evaluation shader stage
11294 void testTesselationEvaluationShaderStage()
11296 static const char* const fragment_shader_code = "#version 400 core\n"
11297 "#extension GL_ARB_shader_image_load_store : require\n"
11299 "precision highp float;\n"
11306 static const char* const tesselation_evaluation_shader_code =
11307 "#version 400 core\n"
11308 "#extension GL_ARB_shader_image_load_store : require\n"
11310 "precision highp float;\n"
11312 "layout(quads, equal_spacing, ccw) in;\n"
11314 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n"
11316 "in ivec2 vs_tes_coord[];\n"
11318 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11322 " int value = 1;\n"
11324 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11326 " value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n"
11330 static const char* const vertex_shader_code = "#version 400 core\n"
11331 "#extension GL_ARB_shader_image_load_store : require\n"
11333 "precision highp float;\n"
11335 "in ivec2 vs_in_coord;\n"
11336 "out ivec2 vs_tes_coord;\n"
11340 " vs_tes_coord = vs_in_coord;\n"
11343 m_result_for_tesselatioon_evaluation_shader = !doesProgramLink(
11344 fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */,
11345 tesselation_evaluation_shader_code, vertex_shader_code);
11347 if (false == m_result_for_tesselatioon_evaluation_shader)
11349 m_context.getTestContext().getLog()
11350 << tcu::TestLog::Message
11351 << "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully."
11352 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11353 << tesselation_evaluation_shader_code << tcu::TestLog::EndMessage;
11357 /** Test vertex shader stage
11360 void testVertexShaderStage()
11362 static const char* const fragment_shader_code = "#version 400 core\n"
11363 "#extension GL_ARB_shader_image_load_store : require\n"
11365 "precision highp float;\n"
11372 static const char* const vertex_shader_code =
11373 "#version 400 core\n"
11374 "#extension GL_ARB_shader_image_load_store : require\n"
11376 "precision highp float;\n"
11378 "in ivec2 vs_in_coord;\n"
11380 "#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n"
11382 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11386 " int value = 1;\n"
11388 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11390 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11394 m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11395 0 /* tesselation_control_shader_code */,
11396 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11398 if (false == m_result_for_vertex_shader)
11400 m_context.getTestContext().getLog()
11401 << tcu::TestLog::Message
11402 << "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully."
11403 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11404 << vertex_shader_code << tcu::TestLog::EndMessage;
11408 /** Test combined shader stages
11411 void testCombinedShaderStages()
11413 std::string fragment_shader_code =
11414 "#version 400 core\n"
11415 "#extension GL_ARB_shader_image_load_store : require\n"
11417 "precision highp float;\n"
11419 "#define N_UNIFORMS gl_MaxFragmentImageUniforms\n"
11421 "flat in ivec2 gs_fs_coord;\n"
11423 "layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n"
11427 " int value = 1;\n"
11429 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11431 " value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n"
11437 std::string geometry_shader_code =
11438 "#version 400 core\n"
11439 "#extension GL_ARB_shader_image_load_store : require\n"
11441 "precision highp float;\n"
11443 "layout(points) in;\n"
11444 "layout(points, max_vertices = 1) out;\n"
11446 "#define N_UNIFORMS gl_MaxGeometryImageUniforms\n"
11448 "flat in ivec2 tes_gs_coord[];\n"
11449 "flat out ivec2 gs_fs_coord;\n"
11452 "layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n"
11458 " int value = 1;\n"
11460 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11462 " value = imageAtomicAdd(u_image_geometry[i], tes_gs_coord[0], value);\n"
11466 " gs_fs_coord = tes_gs_coord[0];\n"
11470 std::string tesselation_control_shader_code =
11471 "#version 400 core\n"
11472 "#extension GL_ARB_shader_image_load_store : require\n"
11474 "precision highp float;\n"
11476 "layout(vertices = 4) out;\n"
11478 "#define N_UNIFORMS gl_MaxTessControlImageUniforms\n"
11480 "flat in ivec2 vs_tcs_coord[];\n"
11481 "flat out ivec2 tcs_tes_coord[];\n"
11484 "layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n"
11490 " int value = 1;\n"
11492 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11494 " value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n"
11498 " tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n"
11501 std::string tesselation_evaluation_shader_code =
11502 "#version 400 core\n"
11503 "#extension GL_ARB_shader_image_load_store : require\n"
11505 "precision highp float;\n"
11507 "layout(quads, equal_spacing, ccw) in;\n"
11509 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n"
11511 "flat in ivec2 tcs_tes_coord[];\n"
11512 "flat out ivec2 tes_gs_coord;\n"
11515 "layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n"
11521 " int value = 1;\n"
11523 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11525 " value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n"
11529 " tes_gs_coord = tcs_tes_coord[0];\n"
11532 std::string vertex_shader_code =
11533 "#version 400 core\n"
11534 "#extension GL_ARB_shader_image_load_store : require\n"
11536 "precision highp float;\n"
11538 " in ivec2 vs_in_coord;\n"
11539 "flat out ivec2 vs_tcs_coord;\n"
11541 "#define N_UNIFORMS gl_MaxVertexImageUniforms\n"
11544 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11550 " int value = 1;\n"
11552 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11554 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11558 " vs_tcs_coord = vs_tcs_coord;\n"
11561 /* Active image uniform limits */
11562 GLint max_combined_image_uniforms = 0;
11563 GLint max_fragment_image_uniforms = 0;
11564 GLint max_geometry_image_uniforms = 0;
11565 GLint max_tesselation_control_image_uniforms = 0;
11566 GLint max_tesselation_evaluation_image_uniforms = 0;
11567 GLint max_vertex_image_uniforms = 0;
11569 /* Get limit values */
11570 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms);
11571 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms);
11572 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms);
11573 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms);
11574 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms);
11575 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms);
11576 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
11578 if (max_vertex_image_uniforms)
11579 vertex_shader_code.insert(18, "#define IMAGES\n");
11580 if (max_geometry_image_uniforms)
11581 geometry_shader_code.insert(18, "#define IMAGES\n");
11582 if (max_tesselation_control_image_uniforms)
11583 tesselation_control_shader_code.insert(18, "#define IMAGES\n");
11584 if (max_tesselation_evaluation_image_uniforms)
11585 tesselation_evaluation_shader_code.insert(18, "#define IMAGES\n");
11587 /* Check if program builds */
11588 m_result_for_combined =
11589 !doesProgramLink(fragment_shader_code.c_str(),
11590 geometry_shader_code.c_str(),
11591 tesselation_control_shader_code.c_str(),
11592 tesselation_evaluation_shader_code.c_str(),
11593 vertex_shader_code.c_str());
11595 /* Result depends on the limit values */
11596 if (max_combined_image_uniforms >=
11597 (max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms +
11598 max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms))
11600 /* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */
11601 m_result_for_combined = !m_result_for_combined;
11603 if (false == m_result_for_combined)
11605 m_context.getTestContext().getLog()
11606 << tcu::TestLog::Message << "There was an error while building a program."
11607 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11608 << vertex_shader_code << "\nTesselation control shader code:\n"
11609 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11610 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11611 << geometry_shader_code << "\nFragment shader code:\n"
11612 << fragment_shader_code << tcu::TestLog::EndMessage;
11617 /* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */
11618 if (false == m_result_for_combined)
11620 m_context.getTestContext().getLog()
11621 << tcu::TestLog::Message
11622 << "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully."
11623 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11624 << vertex_shader_code << "\nTesselation control shader code:\n"
11625 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11626 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11627 << geometry_shader_code << "\nFragment shader code:\n"
11628 << fragment_shader_code << tcu::TestLog::EndMessage;
11633 /** Check if program builds successfully
11635 * @param fragment_shader_code Source code for fragment shader stage
11636 * @param geometry_shader_code Source code for geometry shader stage
11637 * @param tesselation_control_shader_code Source code for tesselation control shader stage
11638 * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage
11639 * @param vertex_shader_code Source code for vertex shader stage
11641 * @return true if program was built without errors, false otherwise
11643 bool doesProgramLink(const char* fragment_shader_code, const char* geometry_shader_code,
11644 const char* tesselation_control_shader_code, const char* tesselation_evaluation_shader_code,
11645 const char* vertex_shader_code)
11647 bool is_program_built = true;
11648 GLuint program_id = 0;
11651 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
11652 geometry_shader_code, fragment_shader_code, &is_program_built);
11654 if (0 != program_id)
11656 glDeleteProgram(program_id);
11659 return is_program_built;
11664 ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context& context)
11665 : TestCaseGroup(context, "shader_image_load_store", "")
11669 ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
11673 void ShaderImageLoadStoreTests::init()
11675 using namespace deqp;
11676 addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
11677 addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
11678 addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
11679 addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
11680 addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>));
11681 addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>));
11682 addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages",
11683 TestSubcase::Create<BasicAllFormatsStoreGeometryStages>));
11684 addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages",
11685 TestSubcase::Create<BasicAllFormatsLoadGeometryStages>));
11686 addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
11687 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
11688 addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>));
11689 addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>));
11690 addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>));
11691 addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>));
11693 new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
11695 new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>));
11697 new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>));
11699 new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>));
11701 new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
11702 addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
11703 addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>));
11704 addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>));
11705 addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
11706 addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>));
11707 addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
11708 addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
11709 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
11710 addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
11711 addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>));
11712 addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>));
11713 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
11714 addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>));
11715 addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
11716 addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation",
11717 TestSubcase::Create<AdvancedMemoryDependentInvocation>));
11718 addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>));
11719 addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
11720 addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>));
11721 addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>));
11722 addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>));
11723 addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>));
11724 addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>));
11725 addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>));
11727 new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>));
11729 new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>));
11731 new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>));
11732 addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>));
11734 new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>));
11735 addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
11736 addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
11737 addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
11738 addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
11739 addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>));