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