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