xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl4cShaderImageLoadStoreTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "gl4cShaderImageLoadStoreTests.hpp"
25 #include "gluContextInfo.hpp"
26 #include "glwEnums.hpp"
27 #include "tcuMatrix.hpp"
28 #include "tcuPlatform.hpp"
29 #include "tcuRenderTarget.hpp"
30 #include "tcuVectorUtil.hpp"
31 #include <assert.h>
32 #include <climits>
33 #include <cmath>
34 #include <cstdarg>
35 #include <deque>
36 #include <iomanip>
37 #include <map>
38 #include <sstream>
39 #include <tcuFloat.hpp>
40 
41 namespace gl4cts
42 {
43 using namespace glw;
44 
45 namespace
46 {
47 typedef tcu::Vec2 vec2;
48 typedef tcu::Vec4 vec4;
49 typedef tcu::IVec4 ivec4;
50 typedef tcu::UVec4 uvec4;
51 typedef tcu::Mat4 mat4;
52 
53 class ShaderImageLoadStoreBase : public deqp::SubcaseBase
54 {
Title()55     virtual std::string Title()
56     {
57         return "";
58     }
59 
Purpose()60     virtual std::string Purpose()
61     {
62         return "";
63     }
64 
Method()65     virtual std::string Method()
66     {
67         return "";
68     }
69 
PassCriteria()70     virtual std::string PassCriteria()
71     {
72         return "";
73     }
74 
75 public:
SupportedInVS(int requiredVS)76     bool SupportedInVS(int requiredVS)
77     {
78         GLint imagesVS;
79         glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
80         if (imagesVS >= requiredVS)
81             return true;
82         else
83         {
84             std::ostringstream reason;
85             reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
86                    << std::endl;
87             OutputNotSupported(reason.str());
88             return false;
89         }
90     }
91 
SupportedInTCS(int requiredTCS)92     bool SupportedInTCS(int requiredTCS)
93     {
94         GLint imagesTCS;
95         glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
96         if (imagesTCS >= requiredTCS)
97             return true;
98         else
99         {
100             std::ostringstream reason;
101             reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
102                    << std::endl;
103             OutputNotSupported(reason.str());
104             return false;
105         }
106     }
107 
SupportedInTES(int requiredTES)108     bool SupportedInTES(int requiredTES)
109     {
110         GLint imagesTES;
111         glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
112         if (imagesTES >= requiredTES)
113             return true;
114         else
115         {
116             std::ostringstream reason;
117             reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
118                    << std::endl;
119             OutputNotSupported(reason.str());
120             return false;
121         }
122     }
123 
SupportedInGS(int requiredGS)124     bool SupportedInGS(int requiredGS)
125     {
126         GLint imagesGS;
127         glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
128         if (imagesGS >= requiredGS)
129             return true;
130         else
131         {
132             std::ostringstream reason;
133             reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
134                    << std::endl;
135             OutputNotSupported(reason.str());
136             return false;
137         }
138     }
139 
SupportedInGeomStages(int required)140     bool SupportedInGeomStages(int required)
141     {
142         return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) &&
143                SupportedInGS(required);
144     }
145 
SupportedInStage(int stage,int required)146     bool SupportedInStage(int stage, int required)
147     {
148         switch (stage)
149         {
150         case 0:
151             return SupportedInVS(required);
152         case 1:
153             return SupportedInTCS(required);
154         case 2:
155             return SupportedInTES(required);
156         case 3:
157             return SupportedInGS(required);
158         default:
159             return true;
160         }
161     }
162 
SupportedSamples(int required)163     bool SupportedSamples(int required)
164     {
165         int i;
166         glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
167         if (i >= required)
168             return true;
169         else
170         {
171             std::ostringstream reason;
172             reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
173             OutputNotSupported(reason.str());
174             return false;
175         }
176     }
177 
getWindowWidth()178     int getWindowWidth()
179     {
180         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
181         return renderTarget.getWidth();
182     }
183 
getWindowHeight()184     int getWindowHeight()
185     {
186         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
187         return renderTarget.getHeight();
188     }
189 
scaleDimensionsToMemory(int & width,int & height,int devLayers,int sysLayers,int devBPP,int sysBPP)190     void scaleDimensionsToMemory(int &width, int &height, int devLayers, int sysLayers, int devBPP, int sysBPP)
191     {
192         tcu::PlatformMemoryLimits memoryLimits;
193         m_context.getTestContext().getPlatform().getMemoryLimits(memoryLimits);
194         GLsizeiptr sysSpace = memoryLimits.totalSystemMemory;
195         GLsizeiptr devSpace = memoryLimits.totalDeviceLocalMemory;
196         int devInSysLayers  = 0;
197 
198         if (devSpace == 0)
199         {
200             devInSysLayers = devLayers;
201             devLayers      = 0;
202         }
203 
204         // Check if available memory is enough
205         GLsizeiptr pixelsPerLayer = width * height;
206         GLsizeiptr sysRequired    = pixelsPerLayer * ((sysBPP * sysLayers) + (devBPP * devInSysLayers));
207         GLsizeiptr devRequired    = pixelsPerLayer * devBPP * devLayers;
208         if ((sysRequired <= sysSpace) && (devRequired <= devSpace))
209         {
210             return;
211         }
212 
213         // Scales the width and height such that the overall texture fits into
214         // the available space for both system and device.
215         GLdouble scale = sqrt(sysSpace / GLdouble(sysRequired));
216         if (devSpace != 0)
217         {
218             GLdouble devScale = sqrt(devSpace / GLdouble(devRequired));
219             scale             = de::min(devScale, scale);
220         }
221         int newWidth  = int(width * scale);
222         int newHeight = int(height * scale);
223 
224         m_context.getTestContext().getLog()
225             << tcu::TestLog::Message << "Reducing surface dimensions to fit in memory, from " << width << "x" << height
226             << " to " << newWidth << "x" << newHeight << "." << tcu::TestLog::EndMessage;
227 
228         width  = newWidth;
229         height = newHeight;
230     }
231 
ColorEqual(const vec4 & c0,const vec4 & c1,const vec4 & epsilon)232     inline bool ColorEqual(const vec4 &c0, const vec4 &c1, const vec4 &epsilon)
233     {
234         if (fabs(c0[0] - c1[0]) > epsilon[0])
235             return false;
236         if (fabs(c0[1] - c1[1]) > epsilon[1])
237             return false;
238         if (fabs(c0[2] - c1[2]) > epsilon[2])
239             return false;
240         if (fabs(c0[3] - c1[3]) > epsilon[3])
241             return false;
242         return true;
243     }
244 
IsEqual(vec4 a,vec4 b)245     bool IsEqual(vec4 a, vec4 b)
246     {
247         return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
248     }
249 
Equal(const vec4 & v0,const vec4 & v1,GLenum internalformat)250     bool Equal(const vec4 &v0, const vec4 &v1, GLenum internalformat)
251     {
252         if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM)
253         {
254             return ColorEqual(v0, v1, vec4(0.0001f));
255         }
256         else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM)
257         {
258             return ColorEqual(v0, v1, vec4(0.01f));
259         }
260         return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
261     }
262 
Equal(const ivec4 & a,const ivec4 & b,GLenum)263     bool Equal(const ivec4 &a, const ivec4 &b, GLenum)
264     {
265         return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
266     }
267 
Equal(const uvec4 & a,const uvec4 & b,GLenum)268     bool Equal(const uvec4 &a, const uvec4 &b, GLenum)
269     {
270         return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
271     }
272 
273     template <class T>
ToString(T v)274     std::string ToString(T v)
275     {
276         std::ostringstream s;
277         s << "[";
278         for (int i = 0; i < 4; ++i)
279             s << v[i] << (i == 3 ? "" : ",");
280         s << "]";
281         return s.str();
282     }
283 
ValidateReadBuffer(int x,int y,int w,int h,const vec4 & expected)284     bool ValidateReadBuffer(int x, int y, int w, int h, const vec4 &expected)
285     {
286         bool status                           = true;
287         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
288         const tcu::PixelFormat &pixelFormat   = renderTarget.getPixelFormat();
289         vec4 g_color_eps                      = vec4(
290             1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
291             1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
292 
293         std::vector<vec4> fb(w * h);
294         glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
295 
296         for (int yy = 0; yy < h; ++yy)
297         {
298             for (int xx = 0; xx < w; ++xx)
299             {
300                 const int idx = yy * w + xx;
301                 if (!ColorEqual(fb[idx], expected, g_color_eps))
302                 {
303                     m_context.getTestContext().getLog()
304                         << tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
305                         << tcu::TestLog::EndMessage;
306                     status = false;
307                     return status;
308                 }
309             }
310         }
311         return status;
312     }
313 
CompileShader(GLuint shader)314     bool CompileShader(GLuint shader)
315     {
316         glCompileShader(shader);
317 
318         GLint status;
319         glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
320         if (status == GL_FALSE)
321         {
322             GLsizei length;
323             GLchar log[1024];
324             glGetShaderInfoLog(shader, sizeof(log), &length, log);
325             if (length > 1)
326             {
327                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
328                                                     << log << tcu::TestLog::EndMessage;
329             }
330             return false;
331         }
332         return true;
333     }
334 
LinkProgram(GLuint program)335     bool LinkProgram(GLuint program)
336     {
337         glLinkProgram(program);
338 
339         GLint status;
340         glGetProgramiv(program, GL_LINK_STATUS, &status);
341         if (status == GL_FALSE)
342         {
343             GLsizei length;
344             GLchar log[1024];
345             glGetProgramInfoLog(program, sizeof(log), &length, log);
346             if (length > 1)
347             {
348                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
349                                                     << log << tcu::TestLog::EndMessage;
350             }
351             return false;
352         }
353         return true;
354     }
355 
BuildProgram(const char * src_vs,const char * src_tcs,const char * src_tes,const char * src_gs,const char * src_fs,bool * result=NULL)356     GLuint BuildProgram(const char *src_vs, const char *src_tcs, const char *src_tes, const char *src_gs,
357                         const char *src_fs, bool *result = NULL)
358     {
359         const GLuint p = glCreateProgram();
360 
361         if (src_vs)
362         {
363             GLuint sh = glCreateShader(GL_VERTEX_SHADER);
364             glAttachShader(p, sh);
365             glDeleteShader(sh);
366             glShaderSource(sh, 1, &src_vs, NULL);
367             if (!CompileShader(sh))
368             {
369                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
370                 if (result)
371                     *result = false;
372                 return p;
373             }
374         }
375         if (src_tcs)
376         {
377             GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
378             glAttachShader(p, sh);
379             glDeleteShader(sh);
380             glShaderSource(sh, 1, &src_tcs, NULL);
381             if (!CompileShader(sh))
382             {
383                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
384                 if (result)
385                     *result = false;
386                 return p;
387             }
388         }
389         if (src_tes)
390         {
391             GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
392             glAttachShader(p, sh);
393             glDeleteShader(sh);
394             glShaderSource(sh, 1, &src_tes, NULL);
395             if (!CompileShader(sh))
396             {
397                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
398                 if (result)
399                     *result = false;
400                 return p;
401             }
402         }
403         if (src_gs)
404         {
405             GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
406             glAttachShader(p, sh);
407             glDeleteShader(sh);
408             glShaderSource(sh, 1, &src_gs, NULL);
409             if (!CompileShader(sh))
410             {
411                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
412                 if (result)
413                     *result = false;
414                 return p;
415             }
416         }
417         if (src_fs)
418         {
419             GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
420             glAttachShader(p, sh);
421             glDeleteShader(sh);
422             glShaderSource(sh, 1, &src_fs, NULL);
423             if (!CompileShader(sh))
424             {
425                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
426                 if (result)
427                     *result = false;
428                 return p;
429             }
430         }
431         if (!LinkProgram(p))
432         {
433             if (src_vs)
434                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
435             if (src_tcs)
436                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
437             if (src_tes)
438                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
439             if (src_gs)
440                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
441             if (src_fs)
442                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
443             if (result)
444                 *result = false;
445             return p;
446         }
447 
448         return p;
449     }
450 
BuildShaderProgram(GLenum type,const char * src)451     GLuint BuildShaderProgram(GLenum type, const char *src)
452     {
453         const GLuint p = glCreateShaderProgramv(type, 1, &src);
454 
455         GLint status;
456         glGetProgramiv(p, GL_LINK_STATUS, &status);
457         if (status == GL_FALSE)
458         {
459             GLchar log[1024];
460             glGetProgramInfoLog(p, sizeof(log), NULL, log);
461             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
462                                                 << log << "\n"
463                                                 << src << tcu::TestLog::EndMessage;
464         }
465 
466         return p;
467     }
468 
CreateFullViewportQuad(GLuint * vao,GLuint * vbo,GLuint * ebo)469     void CreateFullViewportQuad(GLuint *vao, GLuint *vbo, GLuint *ebo)
470     {
471         assert(vao && vbo);
472 
473         // interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
474         const float v[] = {
475             -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,
476             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,
477             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,
478         };
479         glGenBuffers(1, vbo);
480         glBindBuffer(GL_ARRAY_BUFFER, *vbo);
481         glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
482         glBindBuffer(GL_ARRAY_BUFFER, 0);
483 
484         if (ebo)
485         {
486             std::vector<GLushort> index_data(4);
487             for (int i = 0; i < 4; ++i)
488             {
489                 index_data[i] = static_cast<GLushort>(i);
490             }
491             glGenBuffers(1, ebo);
492             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
493             glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
494             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
495         }
496 
497         glGenVertexArrays(1, vao);
498         glBindVertexArray(*vao);
499         glBindBuffer(GL_ARRAY_BUFFER, *vbo);
500         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
501         glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11,
502                               reinterpret_cast<void *>(sizeof(float) * 2));
503         glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11,
504                               reinterpret_cast<void *>(sizeof(float) * 5));
505         glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11,
506                               reinterpret_cast<void *>(sizeof(float) * 8));
507         glBindBuffer(GL_ARRAY_BUFFER, 0);
508         glEnableVertexAttribArray(0);
509         glEnableVertexAttribArray(1);
510         glEnableVertexAttribArray(2);
511         glEnableVertexAttribArray(3);
512         if (ebo)
513         {
514             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
515         }
516         glBindVertexArray(0);
517     }
518 
FormatEnumToString(GLenum e)519     std::string FormatEnumToString(GLenum e)
520     {
521         switch (e)
522         {
523         case GL_RGBA32F:
524             return "rgba32f";
525         case GL_RGBA16F:
526             return "rgba16f";
527         case GL_RG32F:
528             return "rg32f";
529         case GL_RG16F:
530             return "rg16f";
531         case GL_R11F_G11F_B10F:
532             return "r11f_g11f_b10f";
533         case GL_R32F:
534             return "r32f";
535         case GL_R16F:
536             return "r16f";
537 
538         case GL_RGBA32UI:
539             return "rgba32ui";
540         case GL_RGBA16UI:
541             return "rgba16ui";
542         case GL_RGB10_A2UI:
543             return "rgb10_a2ui";
544         case GL_RGBA8UI:
545             return "rgba8ui";
546         case GL_RG32UI:
547             return "rg32ui";
548         case GL_RG16UI:
549             return "rg16ui";
550         case GL_RG8UI:
551             return "rg8ui";
552         case GL_R32UI:
553             return "r32ui";
554         case GL_R16UI:
555             return "r16ui";
556         case GL_R8UI:
557             return "r8ui";
558 
559         case GL_RGBA32I:
560             return "rgba32i";
561         case GL_RGBA16I:
562             return "rgba16i";
563         case GL_RGBA8I:
564             return "rgba8i";
565         case GL_RG32I:
566             return "rg32i";
567         case GL_RG16I:
568             return "rg16i";
569         case GL_RG8I:
570             return "rg8i";
571         case GL_R32I:
572             return "r32i";
573         case GL_R16I:
574             return "r16i";
575         case GL_R8I:
576             return "r8i";
577 
578         case GL_RGBA16:
579             return "rgba16";
580         case GL_RGB10_A2:
581             return "rgb10_a2";
582         case GL_RGBA8:
583             return "rgba8";
584         case GL_RG16:
585             return "rg16";
586         case GL_RG8:
587             return "rg8";
588         case GL_R16:
589             return "r16";
590         case GL_R8:
591             return "r8";
592 
593         case GL_RGBA16_SNORM:
594             return "rgba16_snorm";
595         case GL_RGBA8_SNORM:
596             return "rgba8_snorm";
597         case GL_RG16_SNORM:
598             return "rg16_snorm";
599         case GL_RG8_SNORM:
600             return "rg8_snorm";
601         case GL_R16_SNORM:
602             return "r16_snorm";
603         case GL_R8_SNORM:
604             return "r8_snorm";
605         }
606 
607         assert(0);
608         return "";
609     }
610 
StageName(int stage)611     const char *StageName(int stage)
612     {
613         switch (stage)
614         {
615         case 0:
616             return "Vertex Shader";
617         case 1:
618             return "Tessellation Control Shader";
619         case 2:
620             return "Tessellation Evaluation Shader";
621         case 3:
622             return "Geometry Shader";
623         case 4:
624             return "Compute Shader";
625         }
626         assert(0);
627         return NULL;
628     }
629 
630     template <typename T>
631     GLenum Format();
632 
633     template <typename T>
634     GLenum Type();
635 
636     template <typename T>
637     std::string TypePrefix();
638 
639     template <typename T>
640     GLenum ImageType(GLenum target);
641 
ClearBuffer(GLenum buffer,GLint drawbuffer,const vec4 & color)642     void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4 &color)
643     {
644         glClearBufferfv(buffer, drawbuffer, &color[0]);
645     }
646 
ClearBuffer(GLenum buffer,GLint drawbuffer,const ivec4 & color)647     void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4 &color)
648     {
649         glClearBufferiv(buffer, drawbuffer, &color[0]);
650     }
651 
ClearBuffer(GLenum buffer,GLint drawbuffer,const uvec4 & color)652     void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4 &color)
653     {
654         glClearBufferuiv(buffer, drawbuffer, &color[0]);
655     }
656 
CheckUniform(GLuint program,const std::string & name,const std::map<std::string,GLuint> & name_index_map,GLint size,GLenum type)657     bool CheckUniform(GLuint program, const std::string &name, const std::map<std::string, GLuint> &name_index_map,
658                       GLint size, GLenum type)
659     {
660         std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name);
661         assert(iter != name_index_map.end());
662 
663         GLchar name_gl[32];
664         GLsizei length_gl;
665         GLint size_gl;
666         GLenum type_gl;
667 
668         glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl);
669 
670         if (std::string(name_gl) != name)
671         {
672             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl
673                                                 << " should be " << name << tcu::TestLog::EndMessage;
674             return false;
675         }
676         if (length_gl != static_cast<GLsizei>(name.length()))
677         {
678             m_context.getTestContext().getLog()
679                 << tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl
680                 << ")" << tcu::TestLog::EndMessage;
681             return false;
682         }
683         if (size_gl != size)
684         {
685             m_context.getTestContext().getLog()
686                 << tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl
687                 << ")" << tcu::TestLog::EndMessage;
688             return false;
689         }
690         if (type_gl != type)
691         {
692             m_context.getTestContext().getLog()
693                 << tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl
694                 << ")" << tcu::TestLog::EndMessage;
695             return false;
696         }
697 
698         return true;
699     }
700 
CheckMax(GLenum pname,GLint min_value)701     bool CheckMax(GLenum pname, GLint min_value)
702     {
703         GLboolean b;
704         GLint i;
705         GLfloat f;
706         GLdouble d;
707         GLint64 i64;
708 
709         glGetIntegerv(pname, &i);
710         if (i < min_value)
711             return false;
712 
713         glGetBooleanv(pname, &b);
714         if (b != (i ? GL_TRUE : GL_FALSE))
715             return false;
716 
717         glGetFloatv(pname, &f);
718         if (static_cast<GLint>(f) < min_value)
719             return false;
720 
721         glGetDoublev(pname, &d);
722         if (static_cast<GLint>(d) < min_value)
723             return false;
724 
725         glGetInteger64v(pname, &i64);
726         if (static_cast<GLint>(i64) < min_value)
727             return false;
728 
729         return true;
730     }
731 
CheckBinding(GLuint unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)732     bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
733                       GLenum format)
734     {
735         GLint i;
736         GLboolean b;
737 
738         glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
739         if (static_cast<GLuint>(i) != texture)
740         {
741             m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
742                                                 << " should be " << texture << tcu::TestLog::EndMessage;
743             return false;
744         }
745         glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b);
746         if (b != (i ? GL_TRUE : GL_FALSE))
747         {
748             m_context.getTestContext().getLog()
749                 << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be "
750                 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
751             return false;
752         }
753 
754         glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
755         if (i != level)
756         {
757             m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
758                                                 << " should be " << level << tcu::TestLog::EndMessage;
759             return false;
760         }
761         glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b);
762         if (b != (i ? GL_TRUE : GL_FALSE))
763         {
764             m_context.getTestContext().getLog()
765                 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be "
766                 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
767             return false;
768         }
769 
770         glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
771         if (i != layered)
772         {
773             m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
774                                                 << " should be " << layered << tcu::TestLog::EndMessage;
775             return false;
776         }
777         glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
778         if (b != (i ? GL_TRUE : GL_FALSE))
779         {
780             m_context.getTestContext().getLog()
781                 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be "
782                 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
783             return false;
784         }
785 
786         glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
787         if (i != layer)
788         {
789             m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
790                                                 << " should be " << layer << tcu::TestLog::EndMessage;
791             return false;
792         }
793         glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b);
794         if (b != (i ? GL_TRUE : GL_FALSE))
795         {
796             m_context.getTestContext().getLog()
797                 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be "
798                 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
799             return false;
800         }
801 
802         glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
803         if (static_cast<GLenum>(i) != access)
804         {
805             m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
806                                                 << " should be " << access << tcu::TestLog::EndMessage;
807             return false;
808         }
809         glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b);
810         if (b != (i ? GL_TRUE : GL_FALSE))
811         {
812             m_context.getTestContext().getLog()
813                 << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be "
814                 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
815             return false;
816         }
817 
818         glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
819         if (static_cast<GLenum>(i) != format)
820         {
821             m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
822                                                 << " should be " << format << tcu::TestLog::EndMessage;
823             return false;
824         }
825         glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b);
826         if (b != (i ? GL_TRUE : GL_FALSE))
827         {
828             m_context.getTestContext().getLog()
829                 << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be "
830                 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
831             return false;
832         }
833 
834         return true;
835     }
EnumToString(GLenum e)836     const char *EnumToString(GLenum e)
837     {
838         switch (e)
839         {
840         case GL_TEXTURE_1D:
841             return "GL_TEXTURE_1D";
842         case GL_TEXTURE_2D:
843             return "GL_TEXTURE_2D";
844         case GL_TEXTURE_3D:
845             return "GL_TEXTURE_3D";
846         case GL_TEXTURE_RECTANGLE:
847             return "GL_TEXTURE_RECTANGLE";
848         case GL_TEXTURE_CUBE_MAP:
849             return "GL_TEXTURE_CUBE_MAP";
850         case GL_TEXTURE_1D_ARRAY:
851             return "GL_TEXTURE_1D_ARRAY";
852         case GL_TEXTURE_2D_ARRAY:
853             return "GL_TEXTURE_2D_ARRAY";
854         case GL_TEXTURE_CUBE_MAP_ARRAY:
855             return "GL_TEXTURE_CUBE_MAP_ARRAY";
856 
857         default:
858             assert(0);
859             break;
860         }
861         return NULL;
862     }
863 };
864 
865 template <>
Format()866 GLenum ShaderImageLoadStoreBase::Format<vec4>()
867 {
868     return GL_RGBA;
869 }
870 
871 template <>
Format()872 GLenum ShaderImageLoadStoreBase::Format<ivec4>()
873 {
874     return GL_RGBA_INTEGER;
875 }
876 
877 template <>
Format()878 GLenum ShaderImageLoadStoreBase::Format<uvec4>()
879 {
880     return GL_RGBA_INTEGER;
881 }
882 
883 template <>
Format()884 GLenum ShaderImageLoadStoreBase::Format<GLint>()
885 {
886     return GL_RED_INTEGER;
887 }
888 
889 template <>
Format()890 GLenum ShaderImageLoadStoreBase::Format<GLuint>()
891 {
892     return GL_RED_INTEGER;
893 }
894 
895 template <>
Type()896 GLenum ShaderImageLoadStoreBase::Type<vec4>()
897 {
898     return GL_FLOAT;
899 }
900 
901 template <>
Type()902 GLenum ShaderImageLoadStoreBase::Type<ivec4>()
903 {
904     return GL_INT;
905 }
906 
907 template <>
Type()908 GLenum ShaderImageLoadStoreBase::Type<uvec4>()
909 {
910     return GL_UNSIGNED_INT;
911 }
912 
913 template <>
Type()914 GLenum ShaderImageLoadStoreBase::Type<GLint>()
915 {
916     return GL_INT;
917 }
918 
919 template <>
Type()920 GLenum ShaderImageLoadStoreBase::Type<GLuint>()
921 {
922     return GL_UNSIGNED_INT;
923 }
924 
925 template <>
TypePrefix()926 std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
927 {
928     return "";
929 }
930 
931 template <>
TypePrefix()932 std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
933 {
934     return "i";
935 }
936 
937 template <>
TypePrefix()938 std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
939 {
940     return "u";
941 }
942 
943 template <>
TypePrefix()944 std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
945 {
946     return "i";
947 }
948 
949 template <>
TypePrefix()950 std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
951 {
952     return "u";
953 }
954 
955 template <>
ImageType(GLenum target)956 GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
957 {
958     switch (target)
959     {
960     case GL_TEXTURE_1D:
961         return GL_IMAGE_1D;
962     case GL_TEXTURE_2D:
963         return GL_IMAGE_2D;
964     case GL_TEXTURE_3D:
965         return GL_IMAGE_3D;
966     case GL_TEXTURE_RECTANGLE:
967         return GL_IMAGE_2D_RECT;
968     case GL_TEXTURE_CUBE_MAP:
969         return GL_IMAGE_CUBE;
970     case GL_TEXTURE_BUFFER:
971         return GL_IMAGE_BUFFER;
972     case GL_TEXTURE_1D_ARRAY:
973         return GL_IMAGE_1D_ARRAY;
974     case GL_TEXTURE_2D_ARRAY:
975         return GL_IMAGE_2D_ARRAY;
976     case GL_TEXTURE_CUBE_MAP_ARRAY:
977         return GL_IMAGE_CUBE_MAP_ARRAY;
978     case GL_TEXTURE_2D_MULTISAMPLE:
979         return GL_IMAGE_2D_MULTISAMPLE;
980     case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
981         return GL_IMAGE_2D_MULTISAMPLE_ARRAY;
982     }
983     assert(0);
984     return 0;
985 }
986 
987 template <>
ImageType(GLenum target)988 GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
989 {
990     switch (target)
991     {
992     case GL_TEXTURE_1D:
993         return GL_INT_IMAGE_1D;
994     case GL_TEXTURE_2D:
995         return GL_INT_IMAGE_2D;
996     case GL_TEXTURE_3D:
997         return GL_INT_IMAGE_3D;
998     case GL_TEXTURE_RECTANGLE:
999         return GL_INT_IMAGE_2D_RECT;
1000     case GL_TEXTURE_CUBE_MAP:
1001         return GL_INT_IMAGE_CUBE;
1002     case GL_TEXTURE_BUFFER:
1003         return GL_INT_IMAGE_BUFFER;
1004     case GL_TEXTURE_1D_ARRAY:
1005         return GL_INT_IMAGE_1D_ARRAY;
1006     case GL_TEXTURE_2D_ARRAY:
1007         return GL_INT_IMAGE_2D_ARRAY;
1008     case GL_TEXTURE_CUBE_MAP_ARRAY:
1009         return GL_INT_IMAGE_CUBE_MAP_ARRAY;
1010     case GL_TEXTURE_2D_MULTISAMPLE:
1011         return GL_INT_IMAGE_2D_MULTISAMPLE;
1012     case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1013         return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1014     }
1015     assert(0);
1016     return 0;
1017 }
1018 
1019 template <>
ImageType(GLenum target)1020 GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
1021 {
1022     switch (target)
1023     {
1024     case GL_TEXTURE_1D:
1025         return GL_UNSIGNED_INT_IMAGE_1D;
1026     case GL_TEXTURE_2D:
1027         return GL_UNSIGNED_INT_IMAGE_2D;
1028     case GL_TEXTURE_3D:
1029         return GL_UNSIGNED_INT_IMAGE_3D;
1030     case GL_TEXTURE_RECTANGLE:
1031         return GL_UNSIGNED_INT_IMAGE_2D_RECT;
1032     case GL_TEXTURE_CUBE_MAP:
1033         return GL_UNSIGNED_INT_IMAGE_CUBE;
1034     case GL_TEXTURE_BUFFER:
1035         return GL_UNSIGNED_INT_IMAGE_BUFFER;
1036     case GL_TEXTURE_1D_ARRAY:
1037         return GL_UNSIGNED_INT_IMAGE_1D_ARRAY;
1038     case GL_TEXTURE_2D_ARRAY:
1039         return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
1040     case GL_TEXTURE_CUBE_MAP_ARRAY:
1041         return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
1042     case GL_TEXTURE_2D_MULTISAMPLE:
1043         return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
1044     case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1045         return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1046     }
1047     assert(0);
1048     return 0;
1049 }
1050 
1051 //-----------------------------------------------------------------------------
1052 // 1.1.1 BasicAPIGet
1053 //-----------------------------------------------------------------------------
1054 class BasicAPIGet : public ShaderImageLoadStoreBase
1055 {
Run()1056     virtual long Run()
1057     {
1058         if (!CheckMax(GL_MAX_IMAGE_UNITS, 8))
1059         {
1060             m_context.getTestContext().getLog()
1061                 << tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
1062             return ERROR;
1063         }
1064         if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8))
1065         {
1066             m_context.getTestContext().getLog()
1067                 << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
1068                 << tcu::TestLog::EndMessage;
1069             return ERROR;
1070         }
1071         if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0))
1072         {
1073             m_context.getTestContext().getLog()
1074                 << tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage;
1075             return ERROR;
1076         }
1077         if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
1078         {
1079             m_context.getTestContext().getLog()
1080                 << tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
1081                 << tcu::TestLog::EndMessage;
1082             return ERROR;
1083         }
1084         if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0))
1085         {
1086             m_context.getTestContext().getLog()
1087                 << tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid."
1088                 << tcu::TestLog::EndMessage;
1089             return ERROR;
1090         }
1091         if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0))
1092         {
1093             m_context.getTestContext().getLog()
1094                 << tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid."
1095                 << tcu::TestLog::EndMessage;
1096             return ERROR;
1097         }
1098         if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0))
1099         {
1100             m_context.getTestContext().getLog()
1101                 << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid."
1102                 << tcu::TestLog::EndMessage;
1103             return ERROR;
1104         }
1105         if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8))
1106         {
1107             m_context.getTestContext().getLog()
1108                 << tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
1109                 << tcu::TestLog::EndMessage;
1110             return ERROR;
1111         }
1112         if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8))
1113         {
1114             m_context.getTestContext().getLog()
1115                 << tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
1116                 << tcu::TestLog::EndMessage;
1117             return ERROR;
1118         }
1119         return NO_ERROR;
1120     }
1121 };
1122 //-----------------------------------------------------------------------------
1123 // 1.1.2 BasicAPIBind
1124 //-----------------------------------------------------------------------------
1125 class BasicAPIBind : public ShaderImageLoadStoreBase
1126 {
1127     GLuint m_texture;
1128 
Setup()1129     virtual long Setup()
1130     {
1131         m_texture = 0;
1132         return NO_ERROR;
1133     }
1134 
Run()1135     virtual long Run()
1136     {
1137         for (GLuint index = 0; index < 8; ++index)
1138         {
1139             if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8))
1140             {
1141                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
1142                                                     << " has invalid default state." << tcu::TestLog::EndMessage;
1143                 return ERROR;
1144             }
1145         }
1146 
1147         glGenTextures(1, &m_texture);
1148         glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
1149         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL);
1150         glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL);
1151         glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL);
1152         glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL);
1153         glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL);
1154         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1155 
1156         glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
1157         if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
1158             return ERROR;
1159 
1160         glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
1161         if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
1162             return ERROR;
1163 
1164         glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16);
1165         if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16))
1166             return ERROR;
1167 
1168         glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
1169         if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
1170             return ERROR;
1171 
1172         glDeleteTextures(1, &m_texture);
1173         m_texture = 0;
1174 
1175         for (GLuint index = 0; index < 8; ++index)
1176         {
1177             GLint name;
1178             glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
1179             if (name != 0)
1180             {
1181                 m_context.getTestContext().getLog()
1182                     << tcu::TestLog::Message << "Binding point " << index
1183                     << " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
1184                 return ERROR;
1185             }
1186         }
1187 
1188         return NO_ERROR;
1189     }
1190 
Cleanup()1191     virtual long Cleanup()
1192     {
1193         glDeleteTextures(1, &m_texture);
1194         return NO_ERROR;
1195     }
1196 };
1197 //-----------------------------------------------------------------------------
1198 // 1.1.3 BasicAPIBarrier
1199 //-----------------------------------------------------------------------------
1200 class BasicAPIBarrier : public ShaderImageLoadStoreBase
1201 {
Run()1202     virtual long Run()
1203     {
1204         glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
1205         glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
1206         glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
1207         glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1208         glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1209         glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1210         glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1211         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1212         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1213         glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1214         glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1215         glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1216 
1217         glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1218                         GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1219                         GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1220                         GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
1221 
1222         glMemoryBarrier(GL_ALL_BARRIER_BITS);
1223 
1224         return NO_ERROR;
1225     }
1226 };
1227 //-----------------------------------------------------------------------------
1228 // 1.1.4 BasicAPITexParam
1229 //-----------------------------------------------------------------------------
1230 class BasicAPITexParam : public ShaderImageLoadStoreBase
1231 {
1232     GLuint m_texture;
1233 
Setup()1234     virtual long Setup()
1235     {
1236         m_texture = 0;
1237         return NO_ERROR;
1238     }
1239 
Run()1240     virtual long Run()
1241     {
1242         glGenTextures(1, &m_texture);
1243         glBindTexture(GL_TEXTURE_2D, m_texture);
1244         glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL);
1245 
1246         GLint i;
1247         GLfloat f;
1248         GLuint ui;
1249 
1250         glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1251         if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1252         {
1253             m_context.getTestContext().getLog()
1254                 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1255                 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1256                 << tcu::TestLog::EndMessage;
1257             return ERROR;
1258         }
1259         glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1260         if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1261         {
1262             m_context.getTestContext().getLog()
1263                 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1264                 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1265                 << tcu::TestLog::EndMessage;
1266             return ERROR;
1267         }
1268         glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1269         if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1270         {
1271             m_context.getTestContext().getLog()
1272                 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1273                 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1274                 << tcu::TestLog::EndMessage;
1275             return ERROR;
1276         }
1277         glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui);
1278         if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1279         {
1280             m_context.getTestContext().getLog()
1281                 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1282                 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1283                 << tcu::TestLog::EndMessage;
1284             return ERROR;
1285         }
1286 
1287         return NO_ERROR;
1288     }
1289 
Cleanup()1290     virtual long Cleanup()
1291     {
1292         glDeleteTextures(1, &m_texture);
1293         return NO_ERROR;
1294     }
1295 };
1296 //-----------------------------------------------------------------------------
1297 // 1.2.1 BasicAllFormatsStore
1298 //-----------------------------------------------------------------------------
1299 class BasicAllFormatsStore : public ShaderImageLoadStoreBase
1300 {
1301     GLuint m_vao;
1302     GLuint m_vbo;
1303 
Setup()1304     virtual long Setup()
1305     {
1306         m_vao = 0;
1307         m_vbo = 0;
1308         return NO_ERROR;
1309     }
1310 
Run()1311     virtual long Run()
1312     {
1313         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1314 
1315         if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1316             return ERROR;
1317         if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1318             return ERROR;
1319         if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1320             return ERROR;
1321 
1322         if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1323             return ERROR;
1324         if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1325             return ERROR;
1326         if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1327             return ERROR;
1328 
1329         if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1330             return ERROR;
1331         if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1332             return ERROR;
1333         if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1334             return ERROR;
1335 
1336         if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1337             return ERROR;
1338 
1339         if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1340             return ERROR;
1341         if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1342             return ERROR;
1343         if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1344             return ERROR;
1345 
1346         if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1347             return ERROR;
1348         if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1349             return ERROR;
1350         if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1351             return ERROR;
1352 
1353         if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1354             return ERROR;
1355         if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1356             return ERROR;
1357         if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1358             return ERROR;
1359         if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1360             return ERROR;
1361 
1362         if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1363             return ERROR;
1364         if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1365             return ERROR;
1366         if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1367             return ERROR;
1368 
1369         if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1370             return ERROR;
1371         if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1372             return ERROR;
1373         if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1374             return ERROR;
1375 
1376         if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1377             return ERROR;
1378         if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1379             return ERROR;
1380         if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1381             return ERROR;
1382         if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1383             return ERROR;
1384 
1385         if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1386             return ERROR;
1387         if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1388             return ERROR;
1389         if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1390             return ERROR;
1391 
1392         if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1393             return ERROR;
1394         if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1395             return ERROR;
1396         if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1397             return ERROR;
1398 
1399         if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1400             return ERROR;
1401         if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1402             return ERROR;
1403         if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1404             return ERROR;
1405 
1406         return NO_ERROR;
1407     }
1408 
1409     template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1410     bool Write(GLenum internalformat, const T &write_value, const T &expected_value)
1411     {
1412         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1413                              "  gl_Position = i_position;" NL "}";
1414         const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
1415         const int kSize      = 16;
1416         std::vector<T> data(kSize * kSize);
1417         GLuint texture;
1418         glGenTextures(1, &texture);
1419 
1420         for (GLuint unit = 0; unit < 8; ++unit)
1421         {
1422             glBindTexture(GL_TEXTURE_2D, texture);
1423             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1424             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1425             glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1426             glBindTexture(GL_TEXTURE_2D, 0);
1427 
1428             glViewport(0, 0, kSize, kSize);
1429             glUseProgram(program);
1430             glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1431             glBindVertexArray(m_vao);
1432             glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1433 
1434             glBindTexture(GL_TEXTURE_2D, texture);
1435             glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1436             glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
1437 
1438             for (int i = 0; i < kSize * kSize; ++i)
1439             {
1440                 if (!Equal(data[i], expected_value, internalformat))
1441                 {
1442                     glDeleteTextures(1, &texture);
1443                     glUseProgram(0);
1444                     glDeleteProgram(program);
1445                     m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i])
1446                                                         << ". Value should be: " << ToString(expected_value)
1447                                                         << ". Format is: " << FormatEnumToString(internalformat)
1448                                                         << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1449                     return false;
1450                 }
1451             }
1452 
1453             if (unit < 7)
1454             {
1455                 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1456             }
1457         }
1458 
1459         glDeleteTextures(1, &texture);
1460         glUseProgram(0);
1461         glDeleteProgram(program);
1462 
1463         return true;
1464     }
1465 
Cleanup()1466     virtual long Cleanup()
1467     {
1468         glViewport(0, 0, getWindowWidth(), getWindowHeight());
1469         glDeleteVertexArrays(1, &m_vao);
1470         glDeleteBuffers(1, &m_vbo);
1471         return NO_ERROR;
1472     }
1473 
1474     template <typename T>
GenFS(GLenum internalformat,const T & value)1475     std::string GenFS(GLenum internalformat, const T &value)
1476     {
1477         std::ostringstream os;
1478         os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1479            << TypePrefix<T>()
1480            << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1481               "  imageStore(g_image, coord, "
1482            << TypePrefix<T>() << "vec4" << value << ");" NL "  discard;" NL "}";
1483         return os.str();
1484     }
1485 };
1486 //-----------------------------------------------------------------------------
1487 // 1.2.2 BasicAllFormatsLoad
1488 //-----------------------------------------------------------------------------
1489 class BasicAllFormatsLoad : public ShaderImageLoadStoreBase
1490 {
1491     GLuint m_vao;
1492     GLuint m_vbo;
1493 
Setup()1494     virtual long Setup()
1495     {
1496         m_vao = 0;
1497         m_vbo = 0;
1498         return NO_ERROR;
1499     }
1500 
Run()1501     virtual long Run()
1502     {
1503         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1504 
1505         if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1506             return ERROR;
1507         if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1508             return ERROR;
1509         if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1510             return ERROR;
1511 
1512         if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1513             return ERROR;
1514         if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1515             return ERROR;
1516         if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1517             return ERROR;
1518 
1519         if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1520             return ERROR;
1521         if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1522             return ERROR;
1523         if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1524             return ERROR;
1525 
1526         if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1527             return ERROR;
1528 
1529         if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1530             return ERROR;
1531         if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1532             return ERROR;
1533         if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1534             return ERROR;
1535 
1536         if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1537             return ERROR;
1538         if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1539             return ERROR;
1540         if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1541             return ERROR;
1542 
1543         if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1544             return ERROR;
1545         if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1546             return ERROR;
1547         if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1548             return ERROR;
1549         if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1550             return ERROR;
1551 
1552         if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1553             return ERROR;
1554         if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1555             return ERROR;
1556         if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1557             return ERROR;
1558 
1559         if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1560             return ERROR;
1561         if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1562             return ERROR;
1563         if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1564             return ERROR;
1565 
1566         if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1567             return ERROR;
1568         if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1569             return ERROR;
1570         if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1571             return ERROR;
1572         if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1573             return ERROR;
1574 
1575         if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1576             return ERROR;
1577         if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1578             return ERROR;
1579         if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1580             return ERROR;
1581 
1582         if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1583             return ERROR;
1584         if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1585             return ERROR;
1586         if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1587             return ERROR;
1588 
1589         if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1590             return ERROR;
1591         if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1592             return ERROR;
1593         if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1594             return ERROR;
1595 
1596         return NO_ERROR;
1597     }
1598 
1599     template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)1600     bool Read(GLenum internalformat, const T &value, const T &expected_value)
1601     {
1602         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1603                              "  gl_Position = i_position;" NL "}";
1604         const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
1605         const int kSize      = 16;
1606         std::vector<T> data(kSize * kSize, value);
1607         GLuint texture;
1608         glGenTextures(1, &texture);
1609 
1610         for (GLuint unit = 0; unit < 8; ++unit)
1611         {
1612             glBindTexture(GL_TEXTURE_2D, texture);
1613             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1614             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1615             glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1616             glBindTexture(GL_TEXTURE_2D, 0);
1617 
1618             glViewport(0, 0, kSize, kSize);
1619             glClear(GL_COLOR_BUFFER_BIT);
1620             glUseProgram(program);
1621             glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1622             glBindVertexArray(m_vao);
1623             glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1624 
1625             if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
1626             {
1627                 glDeleteTextures(1, &texture);
1628                 glUseProgram(0);
1629                 glDeleteProgram(program);
1630                 m_context.getTestContext().getLog()
1631                     << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
1632                     << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1633                 return false;
1634             }
1635 
1636             if (unit < 7)
1637             {
1638                 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1639             }
1640         }
1641 
1642         glDeleteTextures(1, &texture);
1643         glUseProgram(0);
1644         glDeleteProgram(program);
1645 
1646         return true;
1647     }
1648 
Cleanup()1649     virtual long Cleanup()
1650     {
1651         glViewport(0, 0, getWindowWidth(), getWindowHeight());
1652         glDeleteVertexArrays(1, &m_vao);
1653         glDeleteBuffers(1, &m_vbo);
1654         return NO_ERROR;
1655     }
1656 
1657     template <typename T>
GenFS(GLenum internalformat,const T & expected_value)1658     std::string GenFS(GLenum internalformat, const T &expected_value)
1659     {
1660         std::ostringstream os;
1661         os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
1662            << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
1663            << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
1664            << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
1665            << expected_value
1666            << ") o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  else o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1667         return os.str();
1668     }
1669 };
1670 //-----------------------------------------------------------------------------
1671 // 1.2.3 BasicAllFormatsStoreGeometryStages
1672 //-----------------------------------------------------------------------------
1673 class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase
1674 {
1675     GLuint m_vao;
1676 
Setup()1677     virtual long Setup()
1678     {
1679         glGenVertexArrays(1, &m_vao);
1680         return NO_ERROR;
1681     }
1682 
Run()1683     virtual long Run()
1684     {
1685         if (!SupportedInGeomStages(1))
1686             return NOT_SUPPORTED;
1687         glEnable(GL_RASTERIZER_DISCARD);
1688 
1689         if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1690             return ERROR;
1691         if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1692             return ERROR;
1693         if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1694             return ERROR;
1695 
1696         if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1697             return ERROR;
1698         if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1699             return ERROR;
1700         if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1701             return ERROR;
1702 
1703         if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1704             return ERROR;
1705         if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1706             return ERROR;
1707         if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1708             return ERROR;
1709 
1710         if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1711             return ERROR;
1712 
1713         if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1714             return ERROR;
1715         if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1716             return ERROR;
1717         if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1718             return ERROR;
1719 
1720         if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1721             return ERROR;
1722         if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1723             return ERROR;
1724         if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1725             return ERROR;
1726 
1727         if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1728             return ERROR;
1729         if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1730             return ERROR;
1731         if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1732             return ERROR;
1733         if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1734             return ERROR;
1735 
1736         if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1737             return ERROR;
1738         if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1739             return ERROR;
1740         if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1741             return ERROR;
1742 
1743         if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1744             return ERROR;
1745         if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1746             return ERROR;
1747         if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1748             return ERROR;
1749 
1750         if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1751             return ERROR;
1752         if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1753             return ERROR;
1754         if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1755             return ERROR;
1756         if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1757             return ERROR;
1758 
1759         if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1760             return ERROR;
1761         if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1762             return ERROR;
1763         if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1764             return ERROR;
1765 
1766         if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1767             return ERROR;
1768         if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1769             return ERROR;
1770         if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1771             return ERROR;
1772 
1773         if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1774             return ERROR;
1775         if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1776             return ERROR;
1777         if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1778             return ERROR;
1779 
1780         return NO_ERROR;
1781     }
1782 
1783     template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1784     bool Write(GLenum internalformat, const T &write_value, const T &expected_value)
1785     {
1786         const GLuint program =
1787             BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(),
1788                          GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL);
1789         const int kSize = 1;
1790         std::vector<T> data(kSize * kSize);
1791         GLuint texture[4];
1792         glGenTextures(4, texture);
1793 
1794         for (int i = 0; i < 4; ++i)
1795         {
1796             glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1797             glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1798             glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1799             glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1800         }
1801         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1802 
1803         glUseProgram(program);
1804         glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1805         glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1806         glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1807         glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1808         for (GLuint i = 0; i < 4; ++i)
1809         {
1810             glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1811         }
1812         glBindVertexArray(m_vao);
1813         glPatchParameteri(GL_PATCH_VERTICES, 1);
1814         glDrawArrays(GL_PATCHES, 0, 1);
1815         glPatchParameteri(GL_PATCH_VERTICES, 3);
1816 
1817         for (int i = 0; i < 4; ++i)
1818         {
1819             glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1820             glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1821             glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
1822 
1823             if (!Equal(data[0], expected_value, internalformat))
1824             {
1825                 glDeleteTextures(4, texture);
1826                 glUseProgram(0);
1827                 glDeleteProgram(program);
1828                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0])
1829                                                     << ". Value should be: " << ToString(expected_value)
1830                                                     << ". Format is: " << FormatEnumToString(internalformat)
1831                                                     << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
1832                 return false;
1833             }
1834         }
1835         glDeleteTextures(4, texture);
1836         glUseProgram(0);
1837         glDeleteProgram(program);
1838         return true;
1839     }
1840 
Cleanup()1841     virtual long Cleanup()
1842     {
1843         glDisable(GL_RASTERIZER_DISCARD);
1844         glDeleteVertexArrays(1, &m_vao);
1845         return NO_ERROR;
1846     }
1847 
1848     template <typename T>
GenVS(GLenum internalformat,const T & value)1849     std::string GenVS(GLenum internalformat, const T &value)
1850     {
1851         std::ostringstream os;
1852         os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1853            << TypePrefix<T>()
1854            << "image2DArray g_image0;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL
1855               "  imageStore(g_image0, coord, "
1856            << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1857         return os.str();
1858     }
1859 
1860     template <typename T>
GenTCS(GLenum internalformat,const T & value)1861     std::string GenTCS(GLenum internalformat, const T &value)
1862     {
1863         std::ostringstream os;
1864         os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
1865            << ") writeonly uniform " << TypePrefix<T>()
1866            << "image2DArray g_image1;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
1867               "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
1868               "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
1869               "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  imageStore(g_image1, coord, "
1870            << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1871         return os.str();
1872     }
1873 
1874     template <typename T>
GenTES(GLenum internalformat,const T & value)1875     std::string GenTES(GLenum internalformat, const T &value)
1876     {
1877         std::ostringstream os;
1878         os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
1879            << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1880            << "image2DArray g_image2;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL
1881               "  imageStore(g_image2, coord, "
1882            << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1883         return os.str();
1884     }
1885 
1886     template <typename T>
GenGS(GLenum internalformat,const T & value)1887     std::string GenGS(GLenum internalformat, const T &value)
1888     {
1889         std::ostringstream os;
1890         os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
1891            << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1892            << "image2DArray g_image3;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL
1893               "  imageStore(g_image3, coord, "
1894            << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1895         return os.str();
1896     }
1897 };
1898 //-----------------------------------------------------------------------------
1899 // 1.2.4 BasicAllFormatsLoadGeometryStages
1900 //-----------------------------------------------------------------------------
1901 class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase
1902 {
1903     GLuint m_vao;
1904 
Setup()1905     virtual long Setup()
1906     {
1907         glGenVertexArrays(1, &m_vao);
1908         return NO_ERROR;
1909     }
1910 
Run()1911     virtual long Run()
1912     {
1913         if (!SupportedInGeomStages(2))
1914             return NOT_SUPPORTED;
1915         glEnable(GL_RASTERIZER_DISCARD);
1916 
1917         if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1918             return ERROR;
1919         if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1920             return ERROR;
1921         if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1922             return ERROR;
1923 
1924         if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1925             return ERROR;
1926         if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1927             return ERROR;
1928         if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1929             return ERROR;
1930 
1931         if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1932             return ERROR;
1933         if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1934             return ERROR;
1935         if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1936             return ERROR;
1937 
1938         if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1939             return ERROR;
1940 
1941         if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1942             return ERROR;
1943         if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1944             return ERROR;
1945         if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1946             return ERROR;
1947 
1948         if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1949             return ERROR;
1950         if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1951             return ERROR;
1952         if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1953             return ERROR;
1954 
1955         if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1956             return ERROR;
1957         if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1958             return ERROR;
1959         if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1960             return ERROR;
1961         if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1962             return ERROR;
1963 
1964         if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1965             return ERROR;
1966         if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1967             return ERROR;
1968         if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1969             return ERROR;
1970 
1971         if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1972             return ERROR;
1973         if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1974             return ERROR;
1975         if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1976             return ERROR;
1977 
1978         if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1979             return ERROR;
1980         if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1981             return ERROR;
1982         if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1983             return ERROR;
1984         if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1985             return ERROR;
1986 
1987         if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1988             return ERROR;
1989         if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1990             return ERROR;
1991         if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1992             return ERROR;
1993 
1994         if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1995             return ERROR;
1996         if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1997             return ERROR;
1998         if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1999             return ERROR;
2000 
2001         if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2002             return ERROR;
2003         if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2004             return ERROR;
2005         if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2006             return ERROR;
2007 
2008         return NO_ERROR;
2009     }
2010 
2011     template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2012     bool Read(GLenum internalformat, const T &value, const T &expected_value)
2013     {
2014         const GLuint program = BuildProgram(
2015             GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(),
2016             GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL);
2017         const int kSize = 1;
2018         std::vector<T> data(kSize * kSize, value);
2019         GLuint texture[8];
2020         glGenTextures(8, texture);
2021 
2022         for (int i = 0; i < 4; ++i)
2023         {
2024             glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
2025             glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2026             glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2027             glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
2028         }
2029         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2030         vec4 zero(0);
2031         for (int i = 4; i < 8; ++i)
2032         {
2033             glBindTexture(GL_TEXTURE_2D, texture[i]);
2034             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2035             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2036             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero);
2037         }
2038         glBindTexture(GL_TEXTURE_2D, 0);
2039 
2040         glUseProgram(program);
2041         glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
2042         glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
2043         glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
2044         glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
2045         glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4);
2046         glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5);
2047         glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6);
2048         glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7);
2049 
2050         for (GLuint i = 0; i < 4; ++i)
2051         {
2052             glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2053         }
2054         for (GLuint i = 4; i < 8; ++i)
2055         {
2056             glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
2057         }
2058         glBindVertexArray(m_vao);
2059         glPatchParameteri(GL_PATCH_VERTICES, 1);
2060         glDrawArrays(GL_PATCHES, 0, 1);
2061         glPatchParameteri(GL_PATCH_VERTICES, 3);
2062 
2063         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
2064         const tcu::PixelFormat &pixelFormat   = renderTarget.getPixelFormat();
2065         vec4 g_color_eps                      = vec4(
2066             1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
2067             1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
2068 
2069         for (int i = 0; i < 4; ++i)
2070         {
2071             glBindTexture(GL_TEXTURE_2D, texture[i + 4]);
2072             glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2073             vec4 result;
2074             glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]);
2075             if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps))
2076             {
2077                 glDeleteTextures(8, texture);
2078                 glUseProgram(0);
2079                 glDeleteProgram(program);
2080                 m_context.getTestContext().getLog()
2081                     << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
2082                     << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
2083                 return false;
2084             }
2085         }
2086         glDeleteTextures(8, texture);
2087         glUseProgram(0);
2088         glDeleteProgram(program);
2089         return true;
2090     }
2091 
Cleanup()2092     virtual long Cleanup()
2093     {
2094         glDisable(GL_RASTERIZER_DISCARD);
2095         glDeleteVertexArrays(1, &m_vao);
2096         return NO_ERROR;
2097     }
2098 
2099     template <typename T>
GenVS(GLenum internalformat,const T & expected_value)2100     std::string GenVS(GLenum internalformat, const T &expected_value)
2101     {
2102         std::ostringstream os;
2103         os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
2104            << TypePrefix<T>()
2105            << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL
2106               "void main() {" NL "  ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL "  "
2107            << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2108            << expected_value
2109            << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2110               "  else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2111         return os.str();
2112     }
2113 
2114     template <typename T>
GenTCS(GLenum internalformat,const T & expected_value)2115     std::string GenTCS(GLenum internalformat, const T &expected_value)
2116     {
2117         std::ostringstream os;
2118         os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
2119            << ") readonly uniform " << TypePrefix<T>()
2120            << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL
2121               "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL "  gl_TessLevelInner[1] = 1;" NL
2122               "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL "  gl_TessLevelOuter[2] = 1;" NL
2123               "  gl_TessLevelOuter[3] = 1;" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  "
2124            << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2125            << expected_value
2126            << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2127               "  else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2128         return os.str();
2129     }
2130 
2131     template <typename T>
GenTES(GLenum internalformat,const T & expected_value)2132     std::string GenTES(GLenum internalformat, const T &expected_value)
2133     {
2134         std::ostringstream os;
2135         os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
2136            << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2137            << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL
2138               "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  "
2139            << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2140            << expected_value
2141            << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2142               "  else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2143         return os.str();
2144     }
2145 
2146     template <typename T>
GenGS(GLenum internalformat,const T & expected_value)2147     std::string GenGS(GLenum internalformat, const T &expected_value)
2148     {
2149         std::ostringstream os;
2150         os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
2151            << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2152            << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL
2153               "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL "  "
2154            << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2155            << expected_value
2156            << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2157               "  else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2158         return os.str();
2159     }
2160 };
2161 //-----------------------------------------------------------------------------
2162 // 1.2.5 BasicAllFormatsLoadStoreComputeStage
2163 //-----------------------------------------------------------------------------
2164 class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
2165 {
Run()2166     virtual long Run()
2167     {
2168         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
2169         {
2170             m_context.getTestContext().getLog()
2171                 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
2172                 << tcu::TestLog::EndMessage;
2173             return NOT_SUPPORTED;
2174         }
2175 
2176         if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2177             return ERROR;
2178         if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2179             return ERROR;
2180         if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2181             return ERROR;
2182 
2183         if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2184             return ERROR;
2185         if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2186             return ERROR;
2187         if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2188             return ERROR;
2189 
2190         if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2191             return ERROR;
2192         if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2193             return ERROR;
2194         if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2195             return ERROR;
2196 
2197         if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
2198             return ERROR;
2199 
2200         if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2201             return ERROR;
2202         if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2203             return ERROR;
2204         if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2205             return ERROR;
2206 
2207         if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2208             return ERROR;
2209         if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2210             return ERROR;
2211         if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2212             return ERROR;
2213 
2214         if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2215             return ERROR;
2216         if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2217             return ERROR;
2218         if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2219             return ERROR;
2220         if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2221             return ERROR;
2222 
2223         if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2224             return ERROR;
2225         if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2226             return ERROR;
2227         if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2228             return ERROR;
2229 
2230         if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2231             return ERROR;
2232         if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2233             return ERROR;
2234         if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2235             return ERROR;
2236 
2237         if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
2238             return ERROR;
2239         if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
2240             return ERROR;
2241         if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2242             return ERROR;
2243         if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2244             return ERROR;
2245 
2246         if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
2247             return ERROR;
2248         if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2249             return ERROR;
2250         if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2251             return ERROR;
2252 
2253         if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2254             return ERROR;
2255         if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2256             return ERROR;
2257         if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2258             return ERROR;
2259 
2260         if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2261             return ERROR;
2262         if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2263             return ERROR;
2264         if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2265             return ERROR;
2266 
2267         return NO_ERROR;
2268     }
2269 
2270     template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2271     bool Read(GLenum internalformat, const T &value, const T &expected_value)
2272     {
2273         GLuint program;
2274         std::string source    = GenCS<T>(internalformat);
2275         const char *const src = source.c_str();
2276         GLuint sh             = glCreateShader(GL_COMPUTE_SHADER);
2277         glShaderSource(sh, 1, &src, NULL);
2278         glCompileShader(sh);
2279         program = glCreateProgram();
2280         glAttachShader(program, sh);
2281         glLinkProgram(program);
2282         glDeleteShader(sh);
2283 
2284         const int kSize = 1;
2285         std::vector<T> data(kSize * kSize, value);
2286         GLuint texture[2];
2287         glGenTextures(2, texture);
2288 
2289         glBindTexture(GL_TEXTURE_2D, texture[0]);
2290         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2291         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2292         glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2293         glBindTexture(GL_TEXTURE_2D, texture[1]);
2294         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2295         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2296         vec4 zero(0);
2297         glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero);
2298 
2299         glBindTexture(GL_TEXTURE_2D, 0);
2300 
2301         glUseProgram(program);
2302         glUniform1i(glGetUniformLocation(program, "g_image_read"), 0);
2303         glUniform1i(glGetUniformLocation(program, "g_image_write"), 1);
2304 
2305         glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2306         glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2307 
2308         glDispatchCompute(1, 1, 1);
2309 
2310         for (int i = 0; i < 2; ++i)
2311         {
2312             glBindTexture(GL_TEXTURE_2D, texture[i]);
2313             glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2314             glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2315 
2316             if (!Equal(data[0], expected_value, internalformat))
2317             {
2318                 glDeleteTextures(4, texture);
2319                 glUseProgram(0);
2320                 glDeleteProgram(program);
2321                 m_context.getTestContext().getLog()
2322                     << tcu::TestLog::Message << "Value is: " << ToString(data[0])
2323                     << ". Value should be: " << ToString(expected_value)
2324                     << ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage;
2325                 return false;
2326             }
2327         }
2328         glDeleteTextures(2, texture);
2329         glUseProgram(0);
2330         glDeleteProgram(program);
2331         return true;
2332     }
2333 
2334     template <typename T>
GenCS(GLenum internalformat)2335     std::string GenCS(GLenum internalformat)
2336     {
2337         std::ostringstream os;
2338         os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL
2339               "layout("
2340            << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2341            << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2342            << TypePrefix<T>()
2343            << "image2D g_image_write;" NL "void main() {" NL
2344               "  ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL "  "
2345            << TypePrefix<T>()
2346            << "vec4 v = imageLoad(g_image_read, coord);" NL "  imageStore(g_image_write, coord, v);" NL "}";
2347         return os.str();
2348     }
2349 };
2350 //-----------------------------------------------------------------------------
2351 // 1.3.1 BasicAllTargetsStore
2352 //-----------------------------------------------------------------------------
2353 class BasicAllTargetsStore : public ShaderImageLoadStoreBase
2354 {
2355     GLuint m_vao;
2356     GLuint m_vbo;
2357 
Setup()2358     virtual long Setup()
2359     {
2360         m_vao = 0;
2361         m_vbo = 0;
2362         return NO_ERROR;
2363     }
2364 
Run()2365     virtual long Run()
2366     {
2367         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2368 
2369         if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2370             return ERROR;
2371         if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2372             return ERROR;
2373         if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2374             return ERROR;
2375 
2376         if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2377             return ERROR;
2378         if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2379             return ERROR;
2380         if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2381             return ERROR;
2382 
2383         if (SupportedSamples(4))
2384         {
2385             if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2386                 return ERROR;
2387 
2388             GLint isamples;
2389             glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
2390             if (isamples >= 4)
2391             {
2392                 if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2393                     return ERROR;
2394                 if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2395                     return ERROR;
2396             }
2397         }
2398         return NO_ERROR;
2399     }
2400 
Cleanup()2401     virtual long Cleanup()
2402     {
2403         glViewport(0, 0, getWindowWidth(), getWindowHeight());
2404         glDeleteVertexArrays(1, &m_vao);
2405         glDeleteBuffers(1, &m_vbo);
2406         return NO_ERROR;
2407     }
2408 
2409     template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)2410     bool Write(GLenum internalformat, const T &write_value, const T &expected_value)
2411     {
2412         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2413                              "  gl_Position = i_position;" NL "}";
2414         const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
2415         GLuint textures[8];
2416         GLuint buffer;
2417         glGenTextures(8, textures);
2418         glGenBuffers(1, &buffer);
2419 
2420         const int kSize = 16;
2421         std::vector<T> data(kSize * kSize * 2);
2422 
2423         glBindTexture(GL_TEXTURE_1D, textures[0]);
2424         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2425         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2426         glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2427         glBindTexture(GL_TEXTURE_1D, 0);
2428 
2429         glBindTexture(GL_TEXTURE_2D, textures[1]);
2430         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2431         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2432         glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2433         glBindTexture(GL_TEXTURE_2D, 0);
2434 
2435         glBindTexture(GL_TEXTURE_3D, textures[2]);
2436         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2437         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2438         glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2439         glBindTexture(GL_TEXTURE_3D, 0);
2440 
2441         glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2442         glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2443         glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2444         glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2445         glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2446 
2447         glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2448         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2449         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2450         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2451                      &data[0]);
2452         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2453                      &data[0]);
2454         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2455                      &data[0]);
2456         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2457                      &data[0]);
2458         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2459                      &data[0]);
2460         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2461                      &data[0]);
2462         glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2463 
2464         glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2465         glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2466         glBindBuffer(GL_TEXTURE_BUFFER, 0);
2467         glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2468         glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2469         glBindTexture(GL_TEXTURE_BUFFER, 0);
2470 
2471         glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2472         glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2473         glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2474         glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2475         glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2476 
2477         glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2478         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2479         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2480         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2481         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2482 
2483         glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2484         glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2485         glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2486         glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2487         glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2488         glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2489         glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2490         glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2491 
2492         glUseProgram(program);
2493         glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2494         glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2495         glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2496         glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2497         glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
2498         glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
2499         glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
2500         glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
2501 
2502         glBindVertexArray(m_vao);
2503         glViewport(0, 0, kSize, kSize);
2504         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2505 
2506         bool status = true;
2507 
2508         glBindTexture(GL_TEXTURE_1D, textures[0]);
2509         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2510         glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]);
2511         glBindTexture(GL_TEXTURE_1D, 0);
2512         for (int i = 0; i < kSize; ++i)
2513         {
2514             if (!tcu::allEqual(data[i], expected_value))
2515             {
2516                 status = false;
2517                 m_context.getTestContext().getLog()
2518                     << tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i])
2519                     << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2520                 break;
2521             }
2522         }
2523         std::fill(data.begin(), data.end(), T(0));
2524 
2525         glBindTexture(GL_TEXTURE_2D, textures[1]);
2526         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2527         glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2528         glBindTexture(GL_TEXTURE_2D, 0);
2529         for (int i = 0; i < kSize * kSize; ++i)
2530         {
2531             if (!tcu::allEqual(data[i], expected_value))
2532             {
2533                 status = false;
2534                 m_context.getTestContext().getLog()
2535                     << tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i])
2536                     << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2537                 break;
2538             }
2539         }
2540 
2541         glBindTexture(GL_TEXTURE_3D, textures[2]);
2542         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2543         glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]);
2544         glBindTexture(GL_TEXTURE_3D, 0);
2545         for (int i = 0; i < kSize * kSize * 2; ++i)
2546         {
2547             if (!tcu::allEqual(data[i], expected_value))
2548             {
2549                 status = false;
2550                 m_context.getTestContext().getLog()
2551                     << tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i])
2552                     << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2553                 break;
2554             }
2555         }
2556 
2557         glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2558         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2559         glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]);
2560         glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2561         for (int i = 0; i < kSize * kSize; ++i)
2562         {
2563             if (!tcu::allEqual(data[i], expected_value))
2564             {
2565                 status = false;
2566                 m_context.getTestContext().getLog()
2567                     << tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i])
2568                     << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2569                 break;
2570             }
2571         }
2572 
2573         {
2574             glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2575             glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2576             for (int face = 0; face < 6; ++face)
2577             {
2578                 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
2579                 for (int i = 0; i < kSize * kSize; ++i)
2580                 {
2581                     if (!tcu::allEqual(data[i], expected_value))
2582                     {
2583                         status = false;
2584                         m_context.getTestContext().getLog()
2585                             << tcu::TestLog::Message
2586                             << "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i])
2587                             << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2588                         break;
2589                     }
2590                 }
2591             }
2592             glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2593         }
2594 
2595         glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2596         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2597         glBindTexture(GL_TEXTURE_BUFFER, 0);
2598         glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2599         glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]);
2600         glBindBuffer(GL_TEXTURE_BUFFER, 0);
2601         for (int i = 0; i < kSize; ++i)
2602         {
2603             if (!tcu::allEqual(data[i], expected_value))
2604             {
2605                 status = false;
2606                 m_context.getTestContext().getLog()
2607                     << tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i])
2608                     << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2609                 break;
2610             }
2611         }
2612 
2613         glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2614         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2615         glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2616         glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2617         for (int i = 0; i < kSize * 2; ++i)
2618         {
2619             if (!tcu::allEqual(data[i], expected_value))
2620             {
2621                 status = false;
2622                 m_context.getTestContext().getLog()
2623                     << tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i])
2624                     << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2625                 break;
2626             }
2627         }
2628 
2629         glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2630         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2631         glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2632         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2633         for (int i = 0; i < kSize * kSize * 2; ++i)
2634         {
2635             if (!tcu::allEqual(data[i], expected_value))
2636             {
2637                 status = false;
2638                 m_context.getTestContext().getLog()
2639                     << tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i])
2640                     << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2641                 break;
2642             }
2643         }
2644 
2645         glUseProgram(0);
2646         glDeleteProgram(program);
2647         glDeleteTextures(8, textures);
2648         glDeleteBuffers(1, &buffer);
2649 
2650         return status;
2651     }
2652 
2653     template <typename T>
WriteMS(GLenum internalformat,const T & write_value,const T & expected_value)2654     bool WriteMS(GLenum internalformat, const T &write_value, const T &expected_value)
2655     {
2656 
2657         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2658                              "  gl_Position = i_position;" NL "}";
2659         const GLuint program     = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str());
2660         const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str());
2661         GLuint textures[2];
2662         glGenTextures(2, textures);
2663 
2664         const int kSize = 16;
2665 
2666         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2667         glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
2668         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
2669 
2670         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2671         glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
2672         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
2673 
2674         glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2675         glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2676 
2677         glClear(GL_COLOR_BUFFER_BIT);
2678         glUseProgram(program);
2679         glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
2680         glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
2681 
2682         glBindVertexArray(m_vao);
2683         glViewport(0, 0, kSize, kSize);
2684         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2685 
2686         bool status = true;
2687 
2688         glActiveTexture(GL_TEXTURE0);
2689         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2690         glActiveTexture(GL_TEXTURE1);
2691         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2692 
2693         glUseProgram(val_program);
2694         glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0);
2695         glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1);
2696 
2697         glBindVertexArray(m_vao);
2698         glViewport(0, 0, kSize, kSize);
2699         glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2700         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2701 
2702         if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2703         {
2704             status = false;
2705             m_context.getTestContext().getLog()
2706                 << tcu::TestLog::Message
2707                 << "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed."
2708                 << tcu::TestLog::EndMessage;
2709         }
2710 
2711         glActiveTexture(GL_TEXTURE0);
2712         glDeleteTextures(2, textures);
2713         glUseProgram(0);
2714         glDeleteProgram(program);
2715         glDeleteProgram(val_program);
2716 
2717         return status;
2718     }
2719 
2720     template <typename T>
WriteCubeArray(GLenum internalformat,const T & write_value,const T & expected_value)2721     bool WriteCubeArray(GLenum internalformat, const T &write_value, const T &expected_value)
2722     {
2723         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2724                              "  gl_Position = i_position;" NL "}";
2725         const GLuint program =
2726             BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str());
2727         GLuint textures[1];
2728         glGenTextures(1, textures);
2729 
2730         const int kSize = 16;
2731 
2732         std::vector<T> data(kSize * kSize * 12);
2733         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2734         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2735         glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
2736                      &data[0]);
2737         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2738 
2739         glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2740 
2741         glUseProgram(program);
2742         glBindVertexArray(m_vao);
2743         glViewport(0, 0, kSize, kSize);
2744         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2745 
2746         bool status = true;
2747 
2748         std::fill(data.begin(), data.end(), T(0));
2749         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2750         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2751         glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2752         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2753         for (int i = 0; i < kSize * kSize * 12; ++i)
2754         {
2755             if (!tcu::allEqual(data[i], expected_value))
2756             {
2757                 status = false;
2758                 m_context.getTestContext().getLog()
2759                     << tcu::TestLog::Message
2760                     << "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i])
2761                     << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2762                 break;
2763             }
2764         }
2765 
2766         glDeleteTextures(1, textures);
2767         glUseProgram(0);
2768         glDeleteProgram(program);
2769 
2770         return status;
2771     }
2772 
2773     template <typename T>
GenFS(GLenum internalformat,const T & write_value)2774     std::string GenFS(GLenum internalformat, const T &write_value)
2775     {
2776         std::ostringstream os;
2777         os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2778            << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat)
2779            << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2780            << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2781            << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2782            << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat)
2783            << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2784            << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2785            << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2786            << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
2787            << ") writeonly uniform " << TypePrefix<T>()
2788            << "image2DArray g_image_2darray;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2789               "  imageStore(g_image_1d, coord.x, "
2790            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2d, coord, " << TypePrefix<T>()
2791            << "vec4" << write_value << ");" NL "  imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>()
2792            << "vec4" << write_value << ");" NL "  imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>()
2793            << "vec4" << write_value << ");" NL "  imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4"
2794            << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2795            << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2796            << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4"
2797            << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4"
2798            << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4"
2799            << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4"
2800            << write_value << ");" NL "  imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4"
2801            << write_value << ");" NL "  imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4"
2802            << write_value << ");" NL "  imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4"
2803            << write_value << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2804            << write_value << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2805            << write_value << ");" NL "  discard;" NL "}";
2806         return os.str();
2807     }
2808 
2809     template <typename T>
GenFSMS(GLenum internalformat,const T & write_value)2810     std::string GenFSMS(GLenum internalformat, const T &write_value)
2811     {
2812         std::ostringstream os;
2813         os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2814            << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat)
2815            << ") writeonly uniform " << TypePrefix<T>()
2816            << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2817               "  imageStore(g_image_2dms, coord, 0, "
2818            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 1, "
2819            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 2, "
2820            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 3, "
2821            << TypePrefix<T>() << "vec4" << write_value
2822            << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4"
2823            << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>()
2824            << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 2, "
2825            << TypePrefix<T>() << "vec4" << write_value
2826            << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4"
2827            << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>()
2828            << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 1, "
2829            << TypePrefix<T>() << "vec4" << write_value
2830            << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4"
2831            << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>()
2832            << "vec4" << write_value << ");" NL "  discard;" NL "}";
2833         return os.str();
2834     }
2835 
2836     template <typename T>
GenFSMSVal(const T & expected_value)2837     std::string GenFSMSVal(const T &expected_value)
2838     {
2839         std::ostringstream os;
2840         os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>()
2841            << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>()
2842            << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
2843               "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  if (texelFetch(g_sampler_2dms, coord, 0) != "
2844            << TypePrefix<T>() << "vec4" << expected_value
2845            << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 1) != "
2846            << TypePrefix<T>() << "vec4" << expected_value
2847            << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 2) != "
2848            << TypePrefix<T>() << "vec4" << expected_value
2849            << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 3) != "
2850            << TypePrefix<T>() << "vec4" << expected_value
2851            << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
2852               "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != "
2853            << TypePrefix<T>() << "vec4" << expected_value
2854            << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2855               "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != "
2856            << TypePrefix<T>() << "vec4" << expected_value
2857            << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2858               "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != "
2859            << TypePrefix<T>() << "vec4" << expected_value
2860            << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2861               "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != "
2862            << TypePrefix<T>() << "vec4" << expected_value
2863            << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2864               "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != "
2865            << TypePrefix<T>() << "vec4" << expected_value
2866            << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2867               "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != "
2868            << TypePrefix<T>() << "vec4" << expected_value
2869            << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2870               "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != "
2871            << TypePrefix<T>() << "vec4" << expected_value
2872            << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2873               "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != "
2874            << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
2875         return os.str();
2876     }
2877 
2878     template <typename T>
GenFSCubeArray(GLenum internalformat,const T & write_value)2879     std::string GenFSCubeArray(GLenum internalformat, const T &write_value)
2880     {
2881         std::ostringstream os;
2882         os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2883            << TypePrefix<T>()
2884            << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2885               "  imageStore(g_image_cube_array, ivec3(coord, 0), "
2886            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 1), "
2887            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 2), "
2888            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 3), "
2889            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 4), "
2890            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 5), "
2891            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 6), "
2892            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 7), "
2893            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 8), "
2894            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 9), "
2895            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 10), "
2896            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 11), "
2897            << TypePrefix<T>() << "vec4" << write_value << ");" NL "  discard;" NL "}";
2898         return os.str();
2899     }
2900 };
2901 //-----------------------------------------------------------------------------
2902 // 1.3.2.1 BasicAllTargetsLoadNonMS
2903 //-----------------------------------------------------------------------------
2904 class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase
2905 {
2906     GLuint m_vao;
2907     GLuint m_vbo;
2908 
Setup()2909     virtual long Setup()
2910     {
2911         m_vao = 0;
2912         m_vbo = 0;
2913         return NO_ERROR;
2914     }
2915 
Run()2916     virtual long Run()
2917     {
2918         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2919 
2920         if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2921             return ERROR;
2922         if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2923             return ERROR;
2924         if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2925             return ERROR;
2926 
2927         if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2928             return ERROR;
2929         if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2930             return ERROR;
2931         if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2932             return ERROR;
2933 
2934         return NO_ERROR;
2935     }
2936 
Cleanup()2937     virtual long Cleanup()
2938     {
2939         glViewport(0, 0, getWindowWidth(), getWindowHeight());
2940         glDeleteVertexArrays(1, &m_vao);
2941         glDeleteBuffers(1, &m_vbo);
2942         return NO_ERROR;
2943     }
2944 
2945     template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2946     bool Read(GLenum internalformat, const T &value, const T &expected_value)
2947     {
2948         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2949                              "  gl_Position = i_position;" NL "}";
2950         const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
2951         GLuint textures[7];
2952         GLuint buffer;
2953         glGenTextures(7, textures);
2954         glGenBuffers(1, &buffer);
2955 
2956         const int kSize = 16;
2957         std::vector<T> data(kSize * kSize * 2, value);
2958 
2959         glBindTexture(GL_TEXTURE_1D, textures[0]);
2960         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2961         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2962         glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2963         glBindTexture(GL_TEXTURE_1D, 0);
2964 
2965         glBindTexture(GL_TEXTURE_2D, textures[1]);
2966         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2967         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2968         glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2969         glBindTexture(GL_TEXTURE_2D, 0);
2970 
2971         glBindTexture(GL_TEXTURE_3D, textures[2]);
2972         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2973         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2974         glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2975         glBindTexture(GL_TEXTURE_3D, 0);
2976 
2977         glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2978         glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2979         glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2980         glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2981         glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2982 
2983         glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2984         glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2985         glBindBuffer(GL_TEXTURE_BUFFER, 0);
2986         glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
2987         glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2988         glBindTexture(GL_TEXTURE_BUFFER, 0);
2989 
2990         glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
2991         glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2992         glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2993         glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2994         glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2995 
2996         glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
2997         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2998         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2999         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3000         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3001 
3002         glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3003         glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3004         glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3005         glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3006         glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3007         glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3008         glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3009 
3010         glClear(GL_COLOR_BUFFER_BIT);
3011 
3012         glUseProgram(program);
3013         glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3014         glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3015         glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3016         glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3017         glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3018         glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3019         glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3020 
3021         glBindVertexArray(m_vao);
3022         glViewport(0, 0, kSize, kSize);
3023         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3024 
3025         bool status = true;
3026 
3027         if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3028         {
3029             status = false;
3030         }
3031 
3032         std::map<std::string, GLuint> name_index_map;
3033         GLint uniforms;
3034         glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3035         if (uniforms != 7)
3036         {
3037             status = false;
3038             m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3039                                                 << " should be 7." << tcu::TestLog::EndMessage;
3040         }
3041         for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3042         {
3043             GLchar name[32];
3044             glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3045             name_index_map.insert(std::make_pair(std::string(name), index));
3046         }
3047 
3048         if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D)))
3049             status = false;
3050         if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D)))
3051             status = false;
3052         if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D)))
3053             status = false;
3054         if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE)))
3055             status = false;
3056         if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER)))
3057             status = false;
3058         if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY)))
3059             status = false;
3060         if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY)))
3061             status = false;
3062 
3063         glUseProgram(0);
3064         glDeleteProgram(program);
3065         glDeleteTextures(7, textures);
3066         glDeleteBuffers(1, &buffer);
3067 
3068         return status;
3069     }
3070 
3071     template <typename T>
ReadCube(GLenum internalformat,const T & value,const T & expected_value)3072     bool ReadCube(GLenum internalformat, const T &value, const T &expected_value)
3073     {
3074         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3075                              "  gl_Position = i_position;" NL "}";
3076         const GLuint program =
3077             BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str());
3078         GLuint textures[2];
3079         glGenTextures(2, textures);
3080 
3081         const int kSize = 16;
3082         std::vector<T> data(kSize * kSize * 12, value);
3083 
3084         glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3085         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3086         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3087         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3088                      &data[0]);
3089         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3090                      &data[0]);
3091         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3092                      &data[0]);
3093         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3094                      &data[0]);
3095         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3096                      &data[0]);
3097         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3098                      &data[0]);
3099         glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3100 
3101         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3102         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3103         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3104         glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3105                      &data[0]);
3106         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3107 
3108         glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3109         glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3110 
3111         glClear(GL_COLOR_BUFFER_BIT);
3112 
3113         glUseProgram(program);
3114         glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3115         glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3116 
3117         glBindVertexArray(m_vao);
3118         glViewport(0, 0, kSize, kSize);
3119         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3120 
3121         bool status = true;
3122 
3123         if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3124         {
3125             status = false;
3126         }
3127 
3128         std::map<std::string, GLuint> name_index_map;
3129         GLint uniforms;
3130         glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3131         if (uniforms != 2)
3132         {
3133             status = false;
3134             m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3135                                                 << " should be 2." << tcu::TestLog::EndMessage;
3136         }
3137         for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3138         {
3139             GLchar name[32];
3140             glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3141             name_index_map.insert(std::make_pair(std::string(name), index));
3142         }
3143 
3144         if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP)))
3145             status = false;
3146         if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY)))
3147             status = false;
3148 
3149         glUseProgram(0);
3150         glDeleteProgram(program);
3151         glDeleteTextures(2, textures);
3152 
3153         return status;
3154     }
3155 
3156     template <typename T>
GenFS(GLenum internalformat,const T & expected_value)3157     std::string GenFS(GLenum internalformat, const T &expected_value)
3158     {
3159         std::ostringstream os;
3160         os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3161            << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3162            << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3163            << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3164            << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3165            << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3166            << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3167            << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3168            << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3169            << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3170            << "image2DArray g_image_2darray;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3171               "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
3172            << TypePrefix<T>()
3173            << "vec4 v;" NL "  v = imageLoad(g_image_1d, coord.x);" NL "  if (v != " << TypePrefix<T>() << "vec4"
3174            << expected_value
3175            << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL "  v = imageLoad(g_image_2d, coord);" NL "  if (v != "
3176            << TypePrefix<T>() << "vec4" << expected_value
3177            << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL
3178               "  if (v != "
3179            << TypePrefix<T>() << "vec4" << expected_value
3180            << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
3181               "  if (v != "
3182            << TypePrefix<T>() << "vec4" << expected_value
3183            << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  v = imageLoad(g_image_2drect, coord);" NL "  if (v != "
3184            << TypePrefix<T>() << "vec4" << expected_value
3185            << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL "  v = imageLoad(g_image_buffer, coord.x);" NL "  if (v != "
3186            << TypePrefix<T>() << "vec4" << expected_value
3187            << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "  v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL
3188               "  if (v != "
3189            << TypePrefix<T>() << "vec4" << expected_value
3190            << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL "  v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL
3191               "  if (v != "
3192            << TypePrefix<T>() << "vec4" << expected_value
3193            << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL "  v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL
3194               "  if (v != "
3195            << TypePrefix<T>() << "vec4" << expected_value
3196            << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL "  v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
3197               "  if (v != "
3198            << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}";
3199         return os.str();
3200     }
3201 
3202     template <typename T>
GenFSCube(GLenum internalformat,const T & expected_value)3203     std::string GenFSCube(GLenum internalformat, const T &expected_value)
3204     {
3205         std::ostringstream os;
3206         os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3207            << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3208            << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3209            << TypePrefix<T>()
3210            << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3211               "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
3212            << TypePrefix<T>()
3213            << "vec4 v;" NL "  v = imageLoad(g_image_cube, ivec3(coord, 0));" NL "  if (v != " << TypePrefix<T>()
3214            << "vec4" << expected_value
3215            << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 1));" NL
3216               "  if (v != "
3217            << TypePrefix<T>() << "vec4" << expected_value
3218            << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
3219               "  if (v != "
3220            << TypePrefix<T>() << "vec4" << expected_value
3221            << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
3222               "  if (v != "
3223            << TypePrefix<T>() << "vec4" << expected_value
3224            << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
3225               "  if (v != "
3226            << TypePrefix<T>() << "vec4" << expected_value
3227            << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 5));" NL
3228               "  if (v != "
3229            << TypePrefix<T>() << "vec4" << expected_value
3230            << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL
3231               "  if (v != "
3232            << TypePrefix<T>() << "vec4" << expected_value
3233            << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL
3234               "  if (v != "
3235            << TypePrefix<T>() << "vec4" << expected_value
3236            << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL
3237               "  if (v != "
3238            << TypePrefix<T>() << "vec4" << expected_value
3239            << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL
3240               "  if (v != "
3241            << TypePrefix<T>() << "vec4" << expected_value
3242            << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL
3243               "  if (v != "
3244            << TypePrefix<T>() << "vec4" << expected_value
3245            << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL
3246               "  if (v != "
3247            << TypePrefix<T>() << "vec4" << expected_value
3248            << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL
3249               "  if (v != "
3250            << TypePrefix<T>() << "vec4" << expected_value
3251            << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL
3252               "  if (v != "
3253            << TypePrefix<T>() << "vec4" << expected_value
3254            << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL
3255               "  if (v != "
3256            << TypePrefix<T>() << "vec4" << expected_value
3257            << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL
3258               "  if (v != "
3259            << TypePrefix<T>() << "vec4" << expected_value
3260            << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL
3261               "  if (v != "
3262            << TypePrefix<T>() << "vec4" << expected_value
3263            << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL
3264               "  if (v != "
3265            << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}";
3266         return os.str();
3267     }
3268 };
3269 //-----------------------------------------------------------------------------
3270 // 1.3.2.2 BasicAllTargetsLoadMS
3271 //-----------------------------------------------------------------------------
3272 class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase
3273 {
3274     GLuint m_vao;
3275     GLuint m_vbo;
3276 
Setup()3277     virtual long Setup()
3278     {
3279         m_vao = 0;
3280         m_vbo = 0;
3281         return NO_ERROR;
3282     }
3283 
Run()3284     virtual long Run()
3285     {
3286         if (!SupportedSamples(4))
3287             return NOT_SUPPORTED;
3288 
3289         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3290 
3291         if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
3292             return ERROR;
3293 
3294         GLint isamples;
3295         glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3296         if (isamples >= 4)
3297         {
3298             if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3299                 return ERROR;
3300             if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
3301                 return ERROR;
3302         }
3303 
3304         return NO_ERROR;
3305     }
3306 
Cleanup()3307     virtual long Cleanup()
3308     {
3309         glViewport(0, 0, getWindowWidth(), getWindowHeight());
3310         glDeleteVertexArrays(1, &m_vao);
3311         glDeleteBuffers(1, &m_vbo);
3312         return NO_ERROR;
3313     }
3314 
3315     template <typename T>
ReadMS(GLenum internalformat,const T & value,const T & expected_value)3316     bool ReadMS(GLenum internalformat, const T &value, const T &expected_value)
3317     {
3318         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3319                              "  gl_Position = i_position;" NL "}";
3320         const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str());
3321         GLuint textures[2];
3322         glGenTextures(2, textures);
3323 
3324         const int kSize = 16;
3325 
3326         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3327         glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3328         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3329 
3330         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3331         glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3332         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3333 
3334         GLuint fbo;
3335         glGenFramebuffers(1, &fbo);
3336         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3337         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3338         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3339         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3340         const GLenum draw_buffers[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
3341         glDrawBuffers(3, draw_buffers);
3342         ClearBuffer(GL_COLOR, 0, value);
3343         ClearBuffer(GL_COLOR, 1, value);
3344         ClearBuffer(GL_COLOR, 2, value);
3345         glDeleteFramebuffers(1, &fbo);
3346 
3347         glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3348         glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3349 
3350         glUseProgram(program);
3351         glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3352         glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3353 
3354         glClear(GL_COLOR_BUFFER_BIT);
3355         glBindVertexArray(m_vao);
3356         glViewport(0, 0, kSize, kSize);
3357         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3358 
3359         bool status = true;
3360 
3361         if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3362         {
3363             status = false;
3364         }
3365 
3366         std::map<std::string, GLuint> name_index_map;
3367         GLint uniforms;
3368         glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3369         if (uniforms != 2)
3370         {
3371             status = false;
3372             m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3373                                                 << " should be 2." << tcu::TestLog::EndMessage;
3374         }
3375         for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3376         {
3377             GLchar name[32];
3378             glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3379             name_index_map.insert(std::make_pair(std::string(name), index));
3380         }
3381 
3382         if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE)))
3383             status = false;
3384         if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1,
3385                           ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)))
3386             status = false;
3387 
3388         glDeleteTextures(2, textures);
3389         glUseProgram(0);
3390         glDeleteProgram(program);
3391 
3392         return status;
3393     }
3394 
3395     template <typename T>
GenFSMS(GLenum internalformat,const T & expected_value)3396     std::string GenFSMS(GLenum internalformat, const T &expected_value)
3397     {
3398         std::ostringstream os;
3399         os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3400            << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3401            << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3402            << TypePrefix<T>()
3403            << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3404               "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  if (imageLoad(g_image_2dms, coord, 0) != "
3405            << TypePrefix<T>() << "vec4" << expected_value
3406            << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 1) != "
3407            << TypePrefix<T>() << "vec4" << expected_value
3408            << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 2) != "
3409            << TypePrefix<T>() << "vec4" << expected_value
3410            << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 3) != "
3411            << TypePrefix<T>() << "vec4" << expected_value
3412            << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != "
3413            << TypePrefix<T>() << "vec4" << expected_value
3414            << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != "
3415            << TypePrefix<T>() << "vec4" << expected_value
3416            << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != "
3417            << TypePrefix<T>() << "vec4" << expected_value
3418            << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != "
3419            << TypePrefix<T>() << "vec4" << expected_value
3420            << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != "
3421            << TypePrefix<T>() << "vec4" << expected_value
3422            << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != "
3423            << TypePrefix<T>() << "vec4" << expected_value
3424            << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != "
3425            << TypePrefix<T>() << "vec4" << expected_value
3426            << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != "
3427            << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
3428         return os.str();
3429     }
3430 };
3431 //-----------------------------------------------------------------------------
3432 // 1.3.3 BasicAllTargetsAtomic
3433 //-----------------------------------------------------------------------------
3434 class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase
3435 {
3436     GLuint m_vao;
3437     GLuint m_vbo;
3438 
Setup()3439     virtual long Setup()
3440     {
3441         m_vao = 0;
3442         m_vbo = 0;
3443         return NO_ERROR;
3444     }
3445 
Run()3446     virtual long Run()
3447     {
3448         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3449 
3450         if (!Atomic<GLint>(GL_R32I))
3451             return ERROR;
3452         if (!Atomic<GLuint>(GL_R32UI))
3453             return ERROR;
3454 
3455         if (!AtomicCube<GLint>(GL_R32I))
3456             return ERROR;
3457         if (!AtomicCube<GLuint>(GL_R32UI))
3458             return ERROR;
3459 
3460         GLint isamples;
3461         glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3462         if (SupportedSamples(4) && isamples >= 4)
3463         {
3464             if (!AtomicMS<GLint>(GL_R32I))
3465                 return ERROR;
3466             if (!AtomicMS<GLuint>(GL_R32UI))
3467                 return ERROR;
3468         }
3469 
3470         return NO_ERROR;
3471     }
3472 
Cleanup()3473     virtual long Cleanup()
3474     {
3475         glViewport(0, 0, getWindowWidth(), getWindowHeight());
3476         glDeleteVertexArrays(1, &m_vao);
3477         glDeleteBuffers(1, &m_vbo);
3478         return NO_ERROR;
3479     }
3480 
3481     template <typename T>
Atomic(GLenum internalformat)3482     bool Atomic(GLenum internalformat)
3483     {
3484         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3485                              "  gl_Position = i_position;" NL "}";
3486         const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str());
3487         GLuint textures[7];
3488         GLuint buffer;
3489         glGenTextures(7, textures);
3490         glGenBuffers(1, &buffer);
3491 
3492         const int kSize = 16;
3493         std::vector<T> data(kSize * kSize * 2);
3494 
3495         glBindTexture(GL_TEXTURE_1D, textures[0]);
3496         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3497         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3498         glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3499         glBindTexture(GL_TEXTURE_1D, 0);
3500 
3501         glBindTexture(GL_TEXTURE_2D, textures[1]);
3502         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3503         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3504         glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3505         glBindTexture(GL_TEXTURE_2D, 0);
3506 
3507         glBindTexture(GL_TEXTURE_3D, textures[2]);
3508         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3509         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3510         glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3511         glBindTexture(GL_TEXTURE_3D, 0);
3512 
3513         glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
3514         glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3515         glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3516         glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3517         glBindTexture(GL_TEXTURE_RECTANGLE, 0);
3518 
3519         glBindBuffer(GL_TEXTURE_BUFFER, buffer);
3520         glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
3521         glBindBuffer(GL_TEXTURE_BUFFER, 0);
3522         glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
3523         glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
3524         glBindTexture(GL_TEXTURE_BUFFER, 0);
3525 
3526         glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
3527         glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3528         glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3529         glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3530         glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
3531 
3532         glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
3533         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3534         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3535         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3536         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3537 
3538         glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3539         glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3540         glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3541         glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3542         glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3543         glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3544         glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3545 
3546         glClear(GL_COLOR_BUFFER_BIT);
3547 
3548         glUseProgram(program);
3549         glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3550         glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3551         glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3552         glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3553         glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3554         glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3555         glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3556 
3557         glBindVertexArray(m_vao);
3558         glViewport(0, 0, kSize, 1);
3559         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3560 
3561         bool status = true;
3562 
3563         if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1)))
3564         {
3565             status = false;
3566         }
3567 
3568         glUseProgram(0);
3569         glDeleteProgram(program);
3570         glDeleteTextures(7, textures);
3571         glDeleteBuffers(1, &buffer);
3572 
3573         return status;
3574     }
3575 
3576     template <typename T>
AtomicCube(GLenum internalformat)3577     bool AtomicCube(GLenum internalformat)
3578     {
3579         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3580                              "  gl_Position = i_position;" NL "}";
3581         const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str());
3582         GLuint textures[2];
3583         glGenTextures(2, textures);
3584 
3585         const int kSize = 16;
3586         std::vector<T> data(kSize * kSize * 12);
3587 
3588         glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3589         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3590         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3591         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3592                      &data[0]);
3593         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3594                      &data[0]);
3595         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3596                      &data[0]);
3597         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3598                      &data[0]);
3599         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3600                      &data[0]);
3601         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3602                      &data[0]);
3603         glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3604 
3605         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3606         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3607         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3608         glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3609                      &data[0]);
3610         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3611 
3612         glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3613         glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3614 
3615         glClear(GL_COLOR_BUFFER_BIT);
3616 
3617         glUseProgram(program);
3618         glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3619         glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3620 
3621         glBindVertexArray(m_vao);
3622         glViewport(0, 0, kSize, kSize);
3623         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3624 
3625         bool status = true;
3626 
3627         if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3628         {
3629             status = false;
3630         }
3631 
3632         glUseProgram(0);
3633         glDeleteProgram(program);
3634         glDeleteTextures(2, textures);
3635 
3636         return status;
3637     }
3638 
3639     template <typename T>
AtomicMS(GLenum internalformat)3640     bool AtomicMS(GLenum internalformat)
3641     {
3642         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3643                              "  gl_Position = i_position;" NL "}";
3644         const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str());
3645         GLuint textures[2];
3646         glGenTextures(2, textures);
3647 
3648         const int kSize = 16;
3649 
3650         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3651         glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3652         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3653 
3654         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3655         glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3656         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3657 
3658         GLuint fbo;
3659         glGenFramebuffers(1, &fbo);
3660         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3661         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3662         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3663         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3664         const GLenum draw_buffers[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
3665         glDrawBuffers(3, draw_buffers);
3666         if (internalformat == GL_R32I)
3667         {
3668             const GLint value[4] = {0, 0, 0, 0};
3669             glClearBufferiv(GL_COLOR, 0, value);
3670             glClearBufferiv(GL_COLOR, 1, value);
3671             glClearBufferiv(GL_COLOR, 2, value);
3672         }
3673         else
3674         {
3675             const GLuint value[4] = {0, 0, 0, 0};
3676             glClearBufferuiv(GL_COLOR, 0, value);
3677             glClearBufferuiv(GL_COLOR, 1, value);
3678             glClearBufferuiv(GL_COLOR, 2, value);
3679         }
3680         glDeleteFramebuffers(1, &fbo);
3681 
3682         glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3683         glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3684 
3685         glUseProgram(program);
3686         glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3687         glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3688 
3689         glClear(GL_COLOR_BUFFER_BIT);
3690         glBindVertexArray(m_vao);
3691         glViewport(0, 0, kSize, kSize);
3692         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3693 
3694         bool status = true;
3695 
3696         if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3697         {
3698             status = false;
3699         }
3700 
3701         glDeleteTextures(2, textures);
3702         glUseProgram(0);
3703         glDeleteProgram(program);
3704 
3705         return status;
3706     }
3707 
3708     template <typename T>
GenFS(GLenum internalformat)3709     std::string GenFS(GLenum internalformat)
3710     {
3711         std::ostringstream os;
3712         os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3713            << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3714            << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3715            << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3716            << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3717            << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3718            << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3719            << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3720            << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3721            << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3722            << "image2DArray g_image_2darray;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3723               "  ivec2 coord = ivec2(gl_FragCoord.xy);"
3724 
3725             NL "  if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3726               "  if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3727               "  if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3728               "  if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3729               "  if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3730               "  if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3731               "  if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3732               "  if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3733               "  if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3734 
3735             NL "  if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3736               "  if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3737               "  if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3738               "  if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3739               "  if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3740               "  if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3741               "  if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3742               "  if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3743               "  if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3744 
3745             NL "  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3746               "  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3747               "  if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3748               "  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3749               "  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3750               "  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3751               "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3752               "  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3753               "1.0);" NL
3754               "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3755 
3756             NL "  if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3757               "  if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3758               "  if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3759               "  if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3760               "  if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3761               "  if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3762               "  if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3763               "  if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3764               "  if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3765 
3766             NL "  if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3767               "  if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3768               "  if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3769               "  if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3770               "  if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3771               "  if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3772               "  if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3773               "  if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3774               "  if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3775 
3776             NL
3777               "  if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3778               "  if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3779               "  if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3780               "  if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3781               "  if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3782               "  if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3783               "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3784               "1.0);" NL "  if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = "
3785               "vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), "
3786               "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3787 
3788             NL "  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3789               "  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3790               "  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3791               "  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3792               "  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3793               "  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3794               "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3795               "1.0);" NL "  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, "
3796               "0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) "
3797               "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3798         return os.str();
3799     }
3800 
3801     template <typename T>
GenFSCube(GLenum internalformat)3802     std::string GenFSCube(GLenum internalformat)
3803     {
3804         std::ostringstream os;
3805         os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3806            << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3807            << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3808            << TypePrefix<T>()
3809            << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3810               "  ivec2 coord = ivec2(gl_FragCoord.xy);"
3811 
3812             NL "  if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3813               "  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3814               "  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3815               "  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3816               "  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3817               "  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3818               "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3819               "  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3820               "1.0);" NL
3821               "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3822 
3823             NL "  if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3824               "1.0);" NL "  if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, "
3825               "0.0, 1.0);" NL "  if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color "
3826               "= vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicAnd(g_image_cube_array, "
3827               "ivec3(coord, 0), 0) != 4) o_color = "
3828               "vec4(1.0, 0.0, 0.0, 1.0);" NL
3829               "  if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3830               "  if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, "
3831               "1.0);" NL "  if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, "
3832               "0.0, 0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != "
3833               "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3834               "  if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, "
3835               "1.0);" NL "}";
3836         return os.str();
3837     }
3838 
3839     template <typename T>
GenFSMS(GLenum internalformat)3840     std::string GenFSMS(GLenum internalformat)
3841     {
3842         std::ostringstream os;
3843         os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3844            << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3845            << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3846            << TypePrefix<T>()
3847            << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3848               "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3849               "  if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3850               "  if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3851               "  if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3852               "  if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3853               "  if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3854               "  if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3855               "  if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3856               "  if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3857               "  if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL
3858               "  if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3859               "1.0);" NL "  if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, "
3860               "0.0, 0.0, 1.0);" NL "  if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) "
3861               "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3862               "  if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, "
3863               "1.0);" NL "  if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, "
3864               "0.0, 0.0, 1.0);" NL "  if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) "
3865               "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3866               "  if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, "
3867               "0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = "
3868               "vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_2dms_array, "
3869               "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, "
3870               "0.0, 1.0);" NL "}";
3871         return os.str();
3872     }
3873 };
3874 //-----------------------------------------------------------------------------
3875 // LoadStoreMachine
3876 //-----------------------------------------------------------------------------
3877 class LoadStoreMachine : public ShaderImageLoadStoreBase
3878 {
3879     GLuint m_vao;
3880     int m_stage;
3881 
Setup()3882     virtual long Setup()
3883     {
3884         glGenVertexArrays(1, &m_vao);
3885         return NO_ERROR;
3886     }
3887 
Cleanup()3888     virtual long Cleanup()
3889     {
3890         glDisable(GL_RASTERIZER_DISCARD);
3891         glDeleteVertexArrays(1, &m_vao);
3892         return NO_ERROR;
3893     }
3894 
3895     template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)3896     bool Write(GLenum internalformat, const T &write_value, const T &expected_value)
3897     {
3898         const GLenum targets[] = {
3899             GL_TEXTURE_1D,       GL_TEXTURE_2D,       GL_TEXTURE_3D,       GL_TEXTURE_RECTANGLE,
3900             GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY};
3901         const int kTargets   = sizeof(targets) / sizeof(targets[0]);
3902         GLuint program_store = 0;
3903         GLuint program_load  = 0;
3904         if (m_stage == 0)
3905         { // VS
3906             program_store =
3907                 BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL);
3908             program_load =
3909                 BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL);
3910         }
3911         else if (m_stage == 1)
3912         { // TCS
3913             const char *const glsl_vs  = "#version 420 core" NL "void main() {}";
3914             const char *const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
3915             program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(),
3916                                          glsl_tes, NULL, NULL);
3917             program_load  = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(),
3918                                          glsl_tes, NULL, NULL);
3919         }
3920         else if (m_stage == 2)
3921         { // TES
3922             const char *const glsl_vs = "#version 420 core" NL "void main() {}";
3923             program_store =
3924                 BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL);
3925             program_load =
3926                 BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL);
3927         }
3928         else if (m_stage == 3)
3929         { // GS
3930             const char *const glsl_vs = "#version 420 core" NL "void main() {}";
3931             program_store =
3932                 BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL);
3933             program_load =
3934                 BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL);
3935         }
3936         else if (m_stage == 4)
3937         { // CS
3938             {
3939                 std::string source    = GenStoreShader(m_stage, internalformat, write_value);
3940                 const char *const src = source.c_str();
3941                 GLuint sh             = glCreateShader(GL_COMPUTE_SHADER);
3942                 glShaderSource(sh, 1, &src, NULL);
3943                 glCompileShader(sh);
3944                 program_store = glCreateProgram();
3945                 glAttachShader(program_store, sh);
3946                 glLinkProgram(program_store);
3947                 glDeleteShader(sh);
3948             }
3949             {
3950                 std::string source    = GenLoadShader(m_stage, internalformat, expected_value);
3951                 const char *const src = source.c_str();
3952                 GLuint sh             = glCreateShader(GL_COMPUTE_SHADER);
3953                 glShaderSource(sh, 1, &src, NULL);
3954                 glCompileShader(sh);
3955                 program_load = glCreateProgram();
3956                 glAttachShader(program_load, sh);
3957                 glLinkProgram(program_load);
3958                 glDeleteShader(sh);
3959             }
3960         }
3961         GLuint textures[kTargets], texture_result;
3962         glGenTextures(kTargets, textures);
3963         glGenTextures(1, &texture_result);
3964 
3965         glBindTexture(GL_TEXTURE_2D, texture_result);
3966         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3967         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3968         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3969 
3970         for (int i = 0; i < kTargets; ++i)
3971         {
3972             glBindTexture(targets[i], textures[i]);
3973             glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3974             glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3975 
3976             if (targets[i] == GL_TEXTURE_1D)
3977             {
3978                 glTexStorage1D(targets[i], 1, internalformat, 1);
3979             }
3980             else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
3981             {
3982                 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3983             }
3984             else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3985             {
3986                 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
3987             }
3988             else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3989             {
3990                 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3991             }
3992             else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
3993             {
3994                 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12);
3995             }
3996             else if (targets[i] == GL_TEXTURE_1D_ARRAY)
3997             {
3998                 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
3999             }
4000         }
4001         glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
4002         glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
4003         glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4004         glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
4005         glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4006         glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4007         glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4008         glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4009 
4010         glUseProgram(program_store);
4011         glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0);
4012         glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1);
4013         glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2);
4014         glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3);
4015         glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4);
4016         glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5);
4017         glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6);
4018         glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7);
4019 
4020         glBindVertexArray(m_vao);
4021         if (m_stage == 1 || m_stage == 2)
4022         { // TCS or TES
4023             glPatchParameteri(GL_PATCH_VERTICES, 1);
4024             glDrawArrays(GL_PATCHES, 0, 1);
4025             glPatchParameteri(GL_PATCH_VERTICES, 3);
4026         }
4027         else if (m_stage == 4)
4028         { // CS
4029             glDispatchCompute(1, 1, 1);
4030         }
4031         else
4032         {
4033             glDrawArrays(GL_POINTS, 0, 1);
4034         }
4035 
4036         bool status = true;
4037         for (int i = 0; i < kTargets; ++i)
4038         {
4039             glBindTexture(targets[i], textures[i]);
4040             glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4041 
4042             if (targets[i] == GL_TEXTURE_CUBE_MAP)
4043             {
4044                 for (int face = 0; face < 6; ++face)
4045                 {
4046                     T data;
4047                     glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
4048                     if (!Equal(data, expected_value, internalformat))
4049                     {
4050                         status = false;
4051                         m_context.getTestContext().getLog()
4052                             << tcu::TestLog::Message << "Value is: " << ToString(data)
4053                             << ". Value should be: " << ToString(expected_value)
4054                             << ". Format is: " << FormatEnumToString(internalformat)
4055                             << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4056                             << tcu::TestLog::EndMessage;
4057                     }
4058                 }
4059             }
4060             else
4061             {
4062                 T data[12];
4063 
4064                 for (uint32_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(data); ndx++)
4065                     data[ndx] = T(0);
4066 
4067                 glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]);
4068 
4069                 int count = 1;
4070                 if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4071                     count = 2;
4072                 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
4073                     count = 12;
4074                 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4075                     count = 2;
4076 
4077                 for (int j = 0; j < count; ++j)
4078                 {
4079                     if (!Equal(data[j], expected_value, internalformat))
4080                     {
4081                         status = false;
4082                         m_context.getTestContext().getLog()
4083                             << tcu::TestLog::Message << "Value is: " << ToString(data[j])
4084                             << ". Value should be: " << ToString(expected_value)
4085                             << ". Format is: " << FormatEnumToString(internalformat)
4086                             << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4087                             << tcu::TestLog::EndMessage;
4088                     }
4089                 }
4090             }
4091         }
4092         glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4093         glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4094         glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4095         glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4096         glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4097         glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4098         glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4099         glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4100 
4101         glUseProgram(program_load);
4102         glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0);
4103         glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1);
4104         glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2);
4105         glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3);
4106         glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4);
4107         glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5);
4108         glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6);
4109         glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7);
4110 
4111         if (m_stage == 1 || m_stage == 2)
4112         { // TCS or TES
4113             glPatchParameteri(GL_PATCH_VERTICES, 1);
4114             glDrawArrays(GL_PATCHES, 0, 1);
4115             glPatchParameteri(GL_PATCH_VERTICES, 3);
4116         }
4117         else if (m_stage == 4)
4118         { // CS
4119             glDispatchCompute(1, 1, 1);
4120         }
4121         else
4122         {
4123             glDrawArrays(GL_POINTS, 0, 1);
4124         }
4125         {
4126             vec4 color;
4127             glBindTexture(GL_TEXTURE_2D, texture_result);
4128             glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4129             glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4130             if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4131             {
4132                 status = false;
4133                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4134                                                     << ". Format is: " << FormatEnumToString(internalformat)
4135                                                     << ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage;
4136             }
4137         }
4138         glUseProgram(0);
4139         glDeleteProgram(program_store);
4140         glDeleteProgram(program_load);
4141         glDeleteTextures(kTargets, textures);
4142         glDeleteTextures(1, &texture_result);
4143         return status;
4144     }
4145 
4146     template <typename T>
GenStoreShader(int stage,GLenum internalformat,const T & write_value)4147     std::string GenStoreShader(int stage, GLenum internalformat, const T &write_value)
4148     {
4149         std::ostringstream os;
4150         os << "#version 420 core";
4151         if (stage == 4)
4152         { // CS
4153             os << NL "#extension GL_ARB_compute_shader : require";
4154         }
4155         os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4156            << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4157            << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
4158            << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
4159            << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4160            << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4161            << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
4162            << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4163            << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4164            << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat)
4165            << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform "
4166            << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value
4167            << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4168         if (stage == 0)
4169         { // VS
4170             os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4171         }
4172         else if (stage == 1)
4173         { // TCS
4174             os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4175                      "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4176                      "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4177                      "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4178         }
4179         else if (stage == 2)
4180         { // TES
4181             os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4182                      "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4183         }
4184         else if (stage == 3)
4185         { // GS
4186             os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4187                      "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4188         }
4189         else if (stage == 4)
4190         { // CS
4191             os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4192                      "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4193         }
4194         os << NL "  imageStore(g_image_1d, coord.x, g_value);" NL "  imageStore(g_image_2d, coord, g_value);" NL
4195                  "  imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
4196                  "  imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
4197                  "  imageStore(g_image_2drect, coord, g_value);" NL "  for (int i = 0; i < 6; ++i) {" NL
4198                  "    imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
4199                  "  imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL
4200                  "  imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL
4201                  "  imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
4202                  "  imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL
4203                  "  for (int i = 0; i < 6; ++i) {" NL
4204                  "    imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
4205                  "  for (int i = 0; i < 6; ++i) {" NL
4206                  "    imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL "  }" NL "}";
4207         return os.str();
4208     }
4209 
4210     template <typename T>
GenLoadShader(int stage,GLenum internalformat,const T & expected_value)4211     std::string GenLoadShader(int stage, GLenum internalformat, const T &expected_value)
4212     {
4213         std::ostringstream os;
4214         os << "#version 420 core";
4215         if (stage == 4)
4216         { // CS
4217             os << NL "#extension GL_ARB_compute_shader : require";
4218         }
4219         os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4220            << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4221            << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4222            << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4223            << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4224            << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4225            << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
4226            << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout("
4227            << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4228            << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4229               "uniform "
4230            << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value
4231            << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4232         if (stage == 0)
4233         { // VS
4234             os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4235         }
4236         else if (stage == 1)
4237         { // TCS
4238             os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4239                      "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4240                      "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4241                      "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4242         }
4243         else if (stage == 2)
4244         { // TES
4245             os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4246                      "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4247         }
4248         else if (stage == 3)
4249         { // GS
4250             os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4251                      "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4252         }
4253         else if (stage == 4)
4254         { // CS
4255             os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4256                      "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4257         }
4258         os << NL "  vec4 r = vec4(0, 1, 0, 1);" NL "  " << TypePrefix<T>()
4259            << "vec4 v;" NL "  v = imageLoad(g_image_2d, coord);" NL
4260               "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4261               "  v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
4262               "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  v = imageLoad(g_image_2drect, coord);" NL
4263               "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4264               "  v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
4265               "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  v = imageLoad(g_image_1darray, coord);" NL
4266               "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4267               "  v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
4268               "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4269               "  v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL
4270               "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  imageStore(g_image_result, coord, r);" NL "}";
4271         return os.str();
4272     }
4273 
4274 protected:
RunStage(int stage)4275     long RunStage(int stage)
4276     {
4277         if (!SupportedInStage(stage, 8))
4278             return NOT_SUPPORTED;
4279 
4280         glEnable(GL_RASTERIZER_DISCARD);
4281         m_stage = stage;
4282 
4283         if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4284             return ERROR;
4285         if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4286             return ERROR;
4287         if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4288             return ERROR;
4289 
4290         if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4291             return ERROR;
4292         if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4293             return ERROR;
4294         if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4295             return ERROR;
4296 
4297         if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4298             return ERROR;
4299         if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4300             return ERROR;
4301         if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4302             return ERROR;
4303 
4304         if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
4305             return ERROR;
4306 
4307         if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4308             return ERROR;
4309         if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4310             return ERROR;
4311         if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4312             return ERROR;
4313 
4314         if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4315             return ERROR;
4316         if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4317             return ERROR;
4318         if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4319             return ERROR;
4320 
4321         if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4322             return ERROR;
4323         if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4324             return ERROR;
4325         if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4326             return ERROR;
4327         if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4328             return ERROR;
4329 
4330         if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4331             return ERROR;
4332         if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4333             return ERROR;
4334         if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4335             return ERROR;
4336 
4337         if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4338             return ERROR;
4339         if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4340             return ERROR;
4341         if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4342             return ERROR;
4343 
4344         if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
4345             return ERROR;
4346         if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
4347             return ERROR;
4348         if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4349             return ERROR;
4350         if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4351             return ERROR;
4352 
4353         if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
4354             return ERROR;
4355         if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4356             return ERROR;
4357         if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4358             return ERROR;
4359 
4360         //
4361         {
4362             if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4363                 return ERROR;
4364             if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4365                 return ERROR;
4366             if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4367                 return ERROR;
4368 
4369             if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4370                 return ERROR;
4371             if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4372                 return ERROR;
4373             if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4374                 return ERROR;
4375         }
4376         return NO_ERROR;
4377     }
4378 };
4379 //-----------------------------------------------------------------------------
4380 // AtomicMachine
4381 //-----------------------------------------------------------------------------
4382 class AtomicMachine : public ShaderImageLoadStoreBase
4383 {
4384     GLuint m_vao;
4385 
Setup()4386     virtual long Setup()
4387     {
4388         glEnable(GL_RASTERIZER_DISCARD);
4389         glGenVertexArrays(1, &m_vao);
4390         return NO_ERROR;
4391     }
4392 
Cleanup()4393     virtual long Cleanup()
4394     {
4395         glDisable(GL_RASTERIZER_DISCARD);
4396         glDeleteVertexArrays(1, &m_vao);
4397         return NO_ERROR;
4398     }
4399 
4400     template <typename T>
Atomic(int stage,GLenum internalformat)4401     bool Atomic(int stage, GLenum internalformat)
4402     {
4403         GLuint program = 0;
4404         if (stage == 0)
4405         { // VS
4406             program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL);
4407         }
4408         else if (stage == 1)
4409         { // TCS
4410             const char *const glsl_vs  = "#version 420 core" NL "void main() {}";
4411             const char *const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
4412             program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL);
4413         }
4414         else if (stage == 2)
4415         { // TES
4416             const char *const glsl_vs = "#version 420 core" NL "void main() {}";
4417             program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL);
4418         }
4419         else if (stage == 3)
4420         { // GS
4421             const char *const glsl_vs = "#version 420 core" NL "void main() {}";
4422             program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL);
4423         }
4424         else if (stage == 4)
4425         { // CS
4426             std::string source    = GenShader<T>(stage, internalformat);
4427             const char *const src = source.c_str();
4428             GLuint sh             = glCreateShader(GL_COMPUTE_SHADER);
4429             glShaderSource(sh, 1, &src, NULL);
4430             glCompileShader(sh);
4431             program = glCreateProgram();
4432             glAttachShader(program, sh);
4433             glLinkProgram(program);
4434             glDeleteShader(sh);
4435         }
4436         GLuint texture_result;
4437         glGenTextures(1, &texture_result);
4438         glBindTexture(GL_TEXTURE_2D, texture_result);
4439         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4440         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4441         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
4442 
4443         const GLenum targets[] = {GL_TEXTURE_2D,     GL_TEXTURE_3D,       GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP,
4444                                   GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY};
4445         const int kTargets     = sizeof(targets) / sizeof(targets[0]);
4446 
4447         GLuint textures[kTargets];
4448         GLuint buffer;
4449         glGenTextures(kTargets, textures);
4450         glGenBuffers(1, &buffer);
4451 
4452         for (int i = 0; i < kTargets; ++i)
4453         {
4454             glBindTexture(targets[i], textures[i]);
4455             if (targets[i] != GL_TEXTURE_BUFFER)
4456             {
4457                 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4458                 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4459             }
4460             if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
4461             {
4462                 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4463             }
4464             else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4465             {
4466                 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
4467             }
4468             else if (targets[i] == GL_TEXTURE_CUBE_MAP)
4469             {
4470                 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4471             }
4472             else if (targets[i] == GL_TEXTURE_BUFFER)
4473             {
4474                 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
4475                 glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
4476                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
4477                 glTexBuffer(targets[i], internalformat, buffer);
4478             }
4479             else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4480             {
4481                 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
4482             }
4483         }
4484         glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4485         glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4486         glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4487         glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4488         glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4489         glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4490         glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4491         glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4492 
4493         glUseProgram(program);
4494         glUniform1i(glGetUniformLocation(program, "g_image_result"), 0);
4495         glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
4496         glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
4497         glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
4498         glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
4499         glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
4500         glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
4501         glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
4502 
4503         glBindVertexArray(m_vao);
4504         if (stage == 1 || stage == 2)
4505         { // TCS or TES
4506             glPatchParameteri(GL_PATCH_VERTICES, 1);
4507             glDrawArrays(GL_PATCHES, 0, 1);
4508             glPatchParameteri(GL_PATCH_VERTICES, 3);
4509         }
4510         else if (stage == 4)
4511         { // CS
4512             glDispatchCompute(1, 1, 1);
4513         }
4514         else
4515         {
4516             glDrawArrays(GL_POINTS, 0, 1);
4517         }
4518 
4519         bool status = true;
4520         {
4521             vec4 color;
4522             glBindTexture(GL_TEXTURE_2D, texture_result);
4523             glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4524             glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4525             if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4526             {
4527                 status = false;
4528                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4529                                                     << ". Format is: " << FormatEnumToString(internalformat)
4530                                                     << ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage;
4531             }
4532         }
4533         glUseProgram(0);
4534         glDeleteProgram(program);
4535         glDeleteTextures(7, textures);
4536         glDeleteTextures(1, &texture_result);
4537         glDeleteBuffers(1, &buffer);
4538         return status;
4539     }
4540 
4541     template <typename T>
GenShader(int stage,GLenum internalformat)4542     std::string GenShader(int stage, GLenum internalformat)
4543     {
4544         std::ostringstream os;
4545         os << "#version 420 core";
4546         if (stage == 4)
4547         { // CS
4548             os << NL "#extension GL_ARB_compute_shader : require";
4549         }
4550         os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4551            << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4552            << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4553            << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4554            << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4555            << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4556            << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
4557            << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4558            << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4559            << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4560               "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);";
4561         if (stage == 0)
4562         { // VS
4563             os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
4564         }
4565         else if (stage == 1)
4566         { // TCS
4567             os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4568                      "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4569                      "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4570                      "  ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4571         }
4572         else if (stage == 2)
4573         { // TES
4574             os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4575                      "  ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4576         }
4577         else if (stage == 3)
4578         { // GS
4579             os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4580                      "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);";
4581         }
4582         else if (stage == 4)
4583         { // CS
4584             os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4585                      "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
4586         }
4587         os << NL
4588             "  vec4 o_color = vec4(0, 1, 0, 1);" NL "  imageAtomicExchange(g_image_2d, coord, 0);" NL
4589             "  if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4590             "  if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4591             "  if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4592             "  if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4593             "  if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4594             "  if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4595             "  if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4596             "  if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4597             "  if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4598 
4599             NL "  imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL
4600             "  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4601             "  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4602             "  if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4603             "  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4604             "  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4605             "  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4606             "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4607             "  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4608             "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4609 
4610             NL "  imageAtomicExchange(g_image_2drect, coord, 0);" NL
4611             "  if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4612             "  if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4613             "  if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4614             "  if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4615             "  if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4616             "  if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4617             "  if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4618             "  if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
4619             "1.0);" NL "  if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4620 
4621             NL "  imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL "  if (imageAtomicAdd(g_image_cube, "
4622             "ivec3(coord, 0), g_value[2]) != 0) "
4623             "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4624             "  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4625             "  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4626             "  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4627             "  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4628             "  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4629             "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4630             "  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, "
4631             "0.0, 1.0);" NL
4632             "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4633 
4634             NL "  imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL
4635             "  if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4636             "  if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4637             "  if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4638             "  if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4639             "  if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4640             "  if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4641             "  if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4642             "1.0);" NL
4643             "  if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4644             "  if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4645 
4646             NL "  imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL
4647             "  if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4648             "  if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4649             "  if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, "
4650             "1.0);" NL
4651             "  if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4652             "  if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4653             "  if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4654             "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4655             "1.0);" NL "  if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, "
4656             "0.0, 0.0, 1.0);" NL
4657             "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4658 
4659             NL "  imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL
4660             "  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4661             "  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4662             "  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4663             "  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4664             "  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4665             "  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, "
4666             "1.0);" NL "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, "
4667             "0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) "
4668             "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4669             "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4670 
4671             NL "  imageStore(g_image_result, coord, o_color);" NL "}";
4672         return os.str();
4673     }
4674 
4675 protected:
RunStage(int stage)4676     long RunStage(int stage)
4677     {
4678         if (!SupportedInStage(stage, 8))
4679             return NOT_SUPPORTED;
4680         if (!Atomic<GLint>(stage, GL_R32I))
4681             return ERROR;
4682         if (!Atomic<GLuint>(stage, GL_R32UI))
4683             return ERROR;
4684         return NO_ERROR;
4685     }
4686 };
4687 //-----------------------------------------------------------------------------
4688 // 1.3.4 BasicAllTargetsLoadStoreVS
4689 //-----------------------------------------------------------------------------
4690 class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
4691 {
Run()4692     virtual long Run()
4693     {
4694         return RunStage(0);
4695     }
4696 };
4697 //-----------------------------------------------------------------------------
4698 // 1.3.5 BasicAllTargetsLoadStoreTCS
4699 //-----------------------------------------------------------------------------
4700 class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine
4701 {
Run()4702     virtual long Run()
4703     {
4704         return RunStage(1);
4705     }
4706 };
4707 //-----------------------------------------------------------------------------
4708 // 1.3.6 BasicAllTargetsLoadStoreTES
4709 //-----------------------------------------------------------------------------
4710 class BasicAllTargetsLoadStoreTES : public LoadStoreMachine
4711 {
Run()4712     virtual long Run()
4713     {
4714         return RunStage(2);
4715     }
4716 };
4717 //-----------------------------------------------------------------------------
4718 // 1.3.7 BasicAllTargetsLoadStoreGS
4719 //-----------------------------------------------------------------------------
4720 class BasicAllTargetsLoadStoreGS : public LoadStoreMachine
4721 {
Run()4722     virtual long Run()
4723     {
4724         return RunStage(3);
4725     }
4726 };
4727 //-----------------------------------------------------------------------------
4728 // 1.3.8 BasicAllTargetsLoadStoreCS
4729 //-----------------------------------------------------------------------------
4730 class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
4731 {
Run()4732     virtual long Run()
4733     {
4734         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4735         {
4736             m_context.getTestContext().getLog()
4737                 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4738                 << tcu::TestLog::EndMessage;
4739             return NO_ERROR;
4740         }
4741 
4742         return RunStage(4);
4743     }
4744 };
4745 //-----------------------------------------------------------------------------
4746 // 1.3.9 BasicAllTargetsAtomicVS
4747 //-----------------------------------------------------------------------------
4748 class BasicAllTargetsAtomicVS : public AtomicMachine
4749 {
Run()4750     virtual long Run()
4751     {
4752         return RunStage(0);
4753     }
4754 };
4755 //-----------------------------------------------------------------------------
4756 // 1.3.10 BasicAllTargetsAtomicTCS
4757 //-----------------------------------------------------------------------------
4758 class BasicAllTargetsAtomicTCS : public AtomicMachine
4759 {
Run()4760     virtual long Run()
4761     {
4762         return RunStage(1);
4763     }
4764 };
4765 //-----------------------------------------------------------------------------
4766 // 1.3.11 BasicAllTargetsAtomicTES
4767 //-----------------------------------------------------------------------------
4768 class BasicAllTargetsAtomicTES : public AtomicMachine
4769 {
Run()4770     virtual long Run()
4771     {
4772         return RunStage(2);
4773     }
4774 };
4775 //-----------------------------------------------------------------------------
4776 // 1.3.12 BasicAllTargetsAtomicGS
4777 //-----------------------------------------------------------------------------
4778 class BasicAllTargetsAtomicGS : public AtomicMachine
4779 {
Run()4780     virtual long Run()
4781     {
4782         return RunStage(3);
4783     }
4784 };
4785 //-----------------------------------------------------------------------------
4786 // 1.3.13 BasicAllTargetsAtomicCS
4787 //-----------------------------------------------------------------------------
4788 class BasicAllTargetsAtomicCS : public AtomicMachine
4789 {
Run()4790     virtual long Run()
4791     {
4792         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4793         {
4794             m_context.getTestContext().getLog()
4795                 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4796                 << tcu::TestLog::EndMessage;
4797             return NO_ERROR;
4798         }
4799 
4800         return RunStage(4);
4801     }
4802 };
4803 //-----------------------------------------------------------------------------
4804 // 1.4.1 BasicGLSLMisc
4805 //-----------------------------------------------------------------------------
4806 class BasicGLSLMisc : public ShaderImageLoadStoreBase
4807 {
4808     GLuint m_texture;
4809     GLuint m_program;
4810     GLuint m_vao, m_vbo;
4811 
Setup()4812     virtual long Setup()
4813     {
4814         m_texture = 0;
4815         m_program = 0;
4816         m_vao = m_vbo = 0;
4817         return NO_ERROR;
4818     }
4819 
Run()4820     virtual long Run()
4821     {
4822         const int kSize = 32;
4823         std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f));
4824 
4825         glGenTextures(1, &m_texture);
4826         glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4827         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4828         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]);
4829         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
4830 
4831         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4832                              "  gl_Position = i_position;" NL "}";
4833         const char *src_fs =
4834             "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4835             "layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL
4836             "layout(rgba32f) volatile uniform image2D g_image_layer1;" NL "void main() {" NL
4837             "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image_layer0, coord, vec4(1.0));" NL
4838             "  memoryBarrier();" NL "  imageStore(g_image_layer0, coord, vec4(2.0));" NL "  memoryBarrier();" NL
4839             "  imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL "  memoryBarrier();" NL
4840             "  o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}";
4841         m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs);
4842 
4843         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4844 
4845         glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4846         glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F);
4847 
4848         glClear(GL_COLOR_BUFFER_BIT);
4849         glViewport(0, 0, kSize, kSize);
4850 
4851         glUseProgram(m_program);
4852         glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0);
4853         glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1);
4854 
4855         glBindVertexArray(m_vao);
4856         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4857 
4858         if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
4859         {
4860             return ERROR;
4861         }
4862         return NO_ERROR;
4863     }
4864 
Cleanup()4865     virtual long Cleanup()
4866     {
4867         glViewport(0, 0, getWindowWidth(), getWindowHeight());
4868         glDeleteTextures(1, &m_texture);
4869         glDeleteVertexArrays(1, &m_vao);
4870         glDeleteBuffers(1, &m_vbo);
4871         glUseProgram(0);
4872         glDeleteProgram(m_program);
4873         return NO_ERROR;
4874     }
4875 };
4876 //-----------------------------------------------------------------------------
4877 // 1.4.2 BasicGLSLEarlyFragTests
4878 //-----------------------------------------------------------------------------
4879 class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
4880 {
4881     GLuint m_texture[2];
4882     GLuint m_program[2];
4883     GLuint m_vao, m_vbo;
4884 
Setup()4885     virtual long Setup()
4886     {
4887         m_texture[0] = m_texture[1] = 0;
4888         m_program[0] = m_program[1] = 0;
4889         m_vao = m_vbo = 0;
4890         return NO_ERROR;
4891     }
4892 
Run()4893     virtual long Run()
4894     {
4895         int ds = m_context.getRenderContext().getRenderTarget().getDepthBits();
4896 
4897         const int kSize = 32;
4898         std::vector<vec4> data(kSize * kSize);
4899 
4900         glGenTextures(2, m_texture);
4901         glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4902         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4903         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4904         glBindTexture(GL_TEXTURE_2D, 0);
4905 
4906         glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4907         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4908         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4909         glBindTexture(GL_TEXTURE_2D, 0);
4910 
4911         const char *glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4912                               "  gl_Position = i_position;" NL "}";
4913         const char *glsl_early_frag_tests_fs =
4914             "#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
4915             "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4916             "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(1.0));" NL
4917             "  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4918         const char *glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4919                               "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4920                               "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(1.0));" NL
4921                               "  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4922         m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs);
4923         m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
4924 
4925         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4926 
4927         glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4928         glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4929 
4930         glViewport(0, 0, kSize, kSize);
4931         glBindVertexArray(m_vao);
4932 
4933         glEnable(GL_DEPTH_TEST);
4934         glClearColor(0.0, 1.0f, 0.0, 1.0f);
4935         glClearDepthf(0.0f);
4936 
4937         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4938         glUseProgram(m_program[0]);
4939         glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0);
4940 
4941         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4942 
4943         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4944         glUseProgram(m_program[1]);
4945         glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1);
4946         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4947 
4948         glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4949         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4950         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4951         for (int i = 0; i < kSize * kSize; ++i)
4952         {
4953             if (IsEqual(data[i], vec4(1.0f)) && ds != 0)
4954                 return ERROR;
4955         }
4956 
4957         glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4958         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4959         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4960         for (int i = 0; i < kSize * kSize; ++i)
4961         {
4962             if (!IsEqual(data[i], vec4(1.0f)) && ds != 0)
4963                 return ERROR;
4964         }
4965 
4966         return NO_ERROR;
4967     }
4968 
Cleanup()4969     virtual long Cleanup()
4970     {
4971         glDisable(GL_DEPTH_TEST);
4972         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4973         glClearDepthf(1.0f);
4974         glViewport(0, 0, getWindowWidth(), getWindowHeight());
4975         glDeleteTextures(2, m_texture);
4976         glDeleteVertexArrays(1, &m_vao);
4977         glDeleteBuffers(1, &m_vbo);
4978         glUseProgram(0);
4979         glDeleteProgram(m_program[0]);
4980         glDeleteProgram(m_program[1]);
4981         return NO_ERROR;
4982     }
4983 };
4984 //-----------------------------------------------------------------------------
4985 // 1.4.3 BasicGLSLConst
4986 //-----------------------------------------------------------------------------
4987 class BasicGLSLConst : public ShaderImageLoadStoreBase
4988 {
4989     GLuint m_program;
4990     GLuint m_vao, m_vbo;
4991 
Setup()4992     virtual long Setup()
4993     {
4994         m_program = 0;
4995         m_vao = m_vbo = 0;
4996         return NO_ERROR;
4997     }
4998 
Run()4999     virtual long Run()
5000     {
5001         bool isAtLeast44Context =
5002             glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4));
5003 
5004         const char *src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
5005                              "  gl_Position = i_position;" NL "}";
5006         std::ostringstream src_fs;
5007         src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core";
5008         src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL
5009                      "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL
5010                      "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL
5011                      "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL
5012                      "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL
5013                      "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5014                      "  if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);";
5015         if (isAtLeast44Context)
5016             src_fs << NL "  if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = "
5017                          "vec4(0.2, 0.0, 0.0, 0.2);";
5018         else
5019             src_fs << NL "  if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) "
5020                          "o_color = vec4(0.2, 0.0, 0.0, 0.2);";
5021         src_fs << NL
5022             "  if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
5023             "  if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL
5024             "  if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, "
5025             "0.5);" NL "  if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, "
5026             "0.0, 0.0, 0.6);" NL
5027             "  if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL
5028             "  if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL
5029             "  if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}";
5030 
5031         m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str());
5032         glUseProgram(m_program);
5033 
5034         GLint i;
5035         glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
5036         glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
5037 
5038         glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
5039         glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
5040 
5041         glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
5042         glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i);
5043 
5044         glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
5045         glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
5046 
5047         glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i);
5048         glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i);
5049 
5050         glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i);
5051         glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i);
5052 
5053         glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i);
5054         glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i);
5055 
5056         glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
5057         glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
5058 
5059         glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
5060         glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
5061 
5062         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5063 
5064         glClear(GL_COLOR_BUFFER_BIT);
5065         glBindVertexArray(m_vao);
5066         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5067 
5068         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5069         {
5070             return ERROR;
5071         }
5072         return NO_ERROR;
5073     }
5074 
Cleanup()5075     virtual long Cleanup()
5076     {
5077         glDeleteVertexArrays(1, &m_vao);
5078         glDeleteBuffers(1, &m_vbo);
5079         glUseProgram(0);
5080         glDeleteProgram(m_program);
5081         return NO_ERROR;
5082     }
5083 };
5084 //-----------------------------------------------------------------------------
5085 // 2.1.1 AdvancedSyncImageAccess
5086 //-----------------------------------------------------------------------------
5087 class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
5088 {
5089     GLuint m_buffer;
5090     GLuint m_buffer_tex;
5091     GLuint m_store_program;
5092     GLuint m_draw_program;
5093     GLuint m_attribless_vao;
5094 
Setup()5095     virtual long Setup()
5096     {
5097         m_buffer         = 0;
5098         m_buffer_tex     = 0;
5099         m_store_program  = 0;
5100         m_draw_program   = 0;
5101         m_attribless_vao = 0;
5102         return NO_ERROR;
5103     }
5104 
Run()5105     virtual long Run()
5106     {
5107         if (!SupportedInVS(1))
5108             return NOT_SUPPORTED;
5109         const char *const glsl_store_vs =
5110             "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5111             "  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5112             "  imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}";
5113         const char *const glsl_draw_vs =
5114             "#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL
5115             "uniform samplerBuffer g_sampler;" NL "void main() {" NL "  vec4 pi = imageLoad(g_image, gl_VertexID);" NL
5116             "  vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL
5117             "  if (pi != ps) vs_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  else vs_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5118             "  gl_Position = pi;" NL "}";
5119         const char *const glsl_draw_fs =
5120             "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5121             "  o_color = vs_color;" NL "}";
5122         m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5123         m_draw_program  = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5124 
5125         glGenVertexArrays(1, &m_attribless_vao);
5126         glBindVertexArray(m_attribless_vao);
5127 
5128         glGenBuffers(1, &m_buffer);
5129         glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5130         glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5131         glBindBuffer(GL_TEXTURE_BUFFER, 0);
5132 
5133         glGenTextures(1, &m_buffer_tex);
5134         glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5135         glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer);
5136 
5137         glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
5138 
5139         glEnable(GL_RASTERIZER_DISCARD);
5140         glUseProgram(m_store_program);
5141         glDrawArrays(GL_POINTS, 0, 4);
5142 
5143         glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
5144 
5145         glDisable(GL_RASTERIZER_DISCARD);
5146         glClear(GL_COLOR_BUFFER_BIT);
5147         glUseProgram(m_draw_program);
5148         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5149 
5150         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5151         {
5152             return ERROR;
5153         }
5154         return NO_ERROR;
5155     }
5156 
Cleanup()5157     virtual long Cleanup()
5158     {
5159         glUseProgram(0);
5160         glDeleteBuffers(1, &m_buffer);
5161         glDeleteTextures(1, &m_buffer_tex);
5162         glDeleteProgram(m_store_program);
5163         glDeleteProgram(m_draw_program);
5164         glDeleteVertexArrays(1, &m_attribless_vao);
5165         return NO_ERROR;
5166     }
5167 };
5168 //-----------------------------------------------------------------------------
5169 // 2.1.2 AdvancedSyncVertexArray
5170 //-----------------------------------------------------------------------------
5171 class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
5172 {
5173     GLuint m_position_buffer;
5174     GLuint m_color_buffer;
5175     GLuint m_element_buffer;
5176     GLuint m_position_buffer_tex;
5177     GLuint m_color_buffer_tex;
5178     GLuint m_element_buffer_tex;
5179     GLuint m_store_program;
5180     GLuint m_draw_program;
5181     GLuint m_attribless_vao;
5182     GLuint m_draw_vao;
5183 
Setup()5184     virtual long Setup()
5185     {
5186         m_position_buffer     = 0;
5187         m_color_buffer        = 0;
5188         m_element_buffer      = 0;
5189         m_position_buffer_tex = 0;
5190         m_color_buffer_tex    = 0;
5191         m_element_buffer_tex  = 0;
5192         m_store_program       = 0;
5193         m_draw_program        = 0;
5194         m_attribless_vao      = 0;
5195         m_draw_vao            = 0;
5196         return NO_ERROR;
5197     }
5198 
Run()5199     virtual long Run()
5200     {
5201         if (!SupportedInVS(3))
5202             return NOT_SUPPORTED;
5203         const char *const glsl_store_vs =
5204             "#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL
5205             "layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL
5206             "layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL
5207             "void main() {" NL "  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5208             "  imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL
5209             "  imageStore(g_color_buffer, gl_VertexID, g_color);" NL
5210             "  imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}";
5211         const char *const glsl_draw_vs =
5212             "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5213             "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL
5214             "  gl_Position = i_position;" NL "  vs_color = i_color;" NL "}";
5215         const char *const glsl_draw_fs =
5216             "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5217             "  o_color = vs_color;" NL "}";
5218         m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5219         glUseProgram(m_store_program);
5220         glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0);
5221         glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1);
5222         glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2);
5223         glUseProgram(0);
5224 
5225         m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5226 
5227         glGenBuffers(1, &m_position_buffer);
5228         glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer);
5229         glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5230         glBindBuffer(GL_TEXTURE_BUFFER, 0);
5231 
5232         glGenBuffers(1, &m_color_buffer);
5233         glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer);
5234         glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW);
5235         glBindBuffer(GL_TEXTURE_BUFFER, 0);
5236 
5237         glGenBuffers(1, &m_element_buffer);
5238         glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer);
5239         glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW);
5240         glBindBuffer(GL_TEXTURE_BUFFER, 0);
5241 
5242         glGenTextures(1, &m_position_buffer_tex);
5243         glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex);
5244         glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer);
5245         glBindTexture(GL_TEXTURE_BUFFER, 0);
5246 
5247         glGenTextures(1, &m_color_buffer_tex);
5248         glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex);
5249         glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer);
5250         glBindTexture(GL_TEXTURE_BUFFER, 0);
5251 
5252         glGenTextures(1, &m_element_buffer_tex);
5253         glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex);
5254         glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer);
5255         glBindTexture(GL_TEXTURE_BUFFER, 0);
5256 
5257         glGenVertexArrays(1, &m_attribless_vao);
5258 
5259         glGenVertexArrays(1, &m_draw_vao);
5260         glBindVertexArray(m_draw_vao);
5261         glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
5262         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5263         glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
5264         glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
5265         glBindBuffer(GL_ARRAY_BUFFER, 0);
5266         glEnableVertexAttribArray(0);
5267         glEnableVertexAttribArray(1);
5268         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
5269         glBindVertexArray(0);
5270 
5271         glEnable(GL_RASTERIZER_DISCARD);
5272         glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F);
5273         glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5274         glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
5275         glUseProgram(m_store_program);
5276         glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5277         glBindVertexArray(m_attribless_vao);
5278         glDrawArrays(GL_POINTS, 0, 4);
5279 
5280         glDisable(GL_RASTERIZER_DISCARD);
5281         glClear(GL_COLOR_BUFFER_BIT);
5282         glUseProgram(m_draw_program);
5283         glBindVertexArray(m_draw_vao);
5284         glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5285         glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5286 
5287         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5288         {
5289             return ERROR;
5290         }
5291 
5292         glEnable(GL_RASTERIZER_DISCARD);
5293         glUseProgram(m_store_program);
5294         glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
5295         glBindVertexArray(m_attribless_vao);
5296         glDrawArrays(GL_POINTS, 0, 4);
5297 
5298         glDisable(GL_RASTERIZER_DISCARD);
5299         glClear(GL_COLOR_BUFFER_BIT);
5300         glUseProgram(m_draw_program);
5301         glBindVertexArray(m_draw_vao);
5302         glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5303         glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5304 
5305         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1)))
5306         {
5307             return ERROR;
5308         }
5309         return NO_ERROR;
5310     }
5311 
Cleanup()5312     virtual long Cleanup()
5313     {
5314         glDisable(GL_RASTERIZER_DISCARD);
5315         glUseProgram(0);
5316         glDeleteBuffers(1, &m_position_buffer);
5317         glDeleteBuffers(1, &m_color_buffer);
5318         glDeleteBuffers(1, &m_element_buffer);
5319         glDeleteTextures(1, &m_position_buffer_tex);
5320         glDeleteTextures(1, &m_color_buffer_tex);
5321         glDeleteTextures(1, &m_element_buffer_tex);
5322         glDeleteProgram(m_store_program);
5323         glDeleteProgram(m_draw_program);
5324         glDeleteVertexArrays(1, &m_attribless_vao);
5325         glDeleteVertexArrays(1, &m_draw_vao);
5326         return NO_ERROR;
5327     }
5328 };
5329 
5330 //-----------------------------------------------------------------------------
5331 // 2.1.4 AdvancedSyncDrawIndirect
5332 //-----------------------------------------------------------------------------
5333 class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase
5334 {
5335     GLuint m_draw_command_buffer;
5336     GLuint m_draw_command_buffer_tex;
5337     GLuint m_store_program;
5338     GLuint m_draw_program;
5339     GLuint m_attribless_vao;
5340     GLuint m_draw_vao;
5341     GLuint m_draw_vbo;
5342 
Setup()5343     virtual long Setup()
5344     {
5345         m_draw_command_buffer     = 0;
5346         m_draw_command_buffer_tex = 0;
5347         m_store_program           = 0;
5348         m_draw_program            = 0;
5349         m_attribless_vao          = 0;
5350         m_draw_vao                = 0;
5351         m_draw_vbo                = 0;
5352         return NO_ERROR;
5353     }
5354 
Run()5355     virtual long Run()
5356     {
5357         if (!SupportedInVS(1))
5358             return NOT_SUPPORTED;
5359         const char *const glsl_store_vs =
5360             "#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL
5361             "  imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}";
5362         const char *const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5363                                          "void main() {" NL "  gl_Position = i_position;" NL "}";
5364         const char *const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5365                                          "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5366         m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5367         m_draw_program  = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5368 
5369         glGenBuffers(1, &m_draw_command_buffer);
5370         glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5371         glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW);
5372         glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
5373 
5374         glGenTextures(1, &m_draw_command_buffer_tex);
5375         glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex);
5376         glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer);
5377         glBindTexture(GL_TEXTURE_BUFFER, 0);
5378 
5379         glGenVertexArrays(1, &m_attribless_vao);
5380         CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL);
5381 
5382         glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
5383 
5384         glEnable(GL_RASTERIZER_DISCARD);
5385         glUseProgram(m_store_program);
5386         glBindVertexArray(m_attribless_vao);
5387         glDrawArrays(GL_POINTS, 0, 1);
5388 
5389         glDisable(GL_RASTERIZER_DISCARD);
5390         glClear(GL_COLOR_BUFFER_BIT);
5391         glUseProgram(m_draw_program);
5392         glBindVertexArray(m_draw_vao);
5393         glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5394         glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
5395         glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0);
5396 
5397         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5398         {
5399             return ERROR;
5400         }
5401         return NO_ERROR;
5402     }
5403 
Cleanup()5404     virtual long Cleanup()
5405     {
5406         glUseProgram(0);
5407         glDeleteBuffers(1, &m_draw_command_buffer);
5408         glDeleteTextures(1, &m_draw_command_buffer_tex);
5409         glDeleteProgram(m_store_program);
5410         glDeleteProgram(m_draw_program);
5411         glDeleteVertexArrays(1, &m_attribless_vao);
5412         glDeleteVertexArrays(1, &m_draw_vao);
5413         glDeleteBuffers(1, &m_draw_vbo);
5414         return NO_ERROR;
5415     }
5416 };
5417 //-----------------------------------------------------------------------------
5418 // 2.1.5 AdvancedSyncTextureUpdate
5419 //-----------------------------------------------------------------------------
5420 class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase
5421 {
5422     GLuint m_texture;
5423     GLuint m_store_program;
5424     GLuint m_draw_program;
5425     GLuint m_vao;
5426     GLuint m_vbo;
5427     GLuint m_pbo;
5428 
Setup()5429     virtual long Setup()
5430     {
5431         m_texture       = 0;
5432         m_store_program = 0;
5433         m_draw_program  = 0;
5434         m_vao           = 0;
5435         m_vbo           = 0;
5436         m_pbo           = 0;
5437         return NO_ERROR;
5438     }
5439 
Run()5440     virtual long Run()
5441     {
5442         const char *const glsl_vs =
5443             "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5444             "void main() {" NL "  gl_Position = i_position;" NL "  vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5445         const char *const glsl_store_fs =
5446             "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
5447             "  imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL "  discard;" NL "}";
5448         const char *const glsl_draw_fs =
5449             "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5450             "uniform sampler2D g_sampler;" NL "void main() {" NL "  o_color = texture(g_sampler, vs_texcoord);" NL "}";
5451         m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5452         m_draw_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5453 
5454         std::vector<vec4> data(16 * 16, vec4(1.0f));
5455         glGenBuffers(1, &m_pbo);
5456         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5457         glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ);
5458         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5459 
5460         glGenTextures(1, &m_texture);
5461         glBindTexture(GL_TEXTURE_2D, m_texture);
5462         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5463         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
5464         glBindTexture(GL_TEXTURE_2D, 0);
5465 
5466         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5467 
5468         glViewport(0, 0, 16, 16);
5469         glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5470         glUseProgram(m_store_program);
5471         glBindVertexArray(m_vao);
5472         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5473 
5474         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5475         glBindTexture(GL_TEXTURE_2D, m_texture);
5476         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
5477         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0);
5478         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5479 
5480         glViewport(0, 0, getWindowWidth(), getWindowHeight());
5481         glClear(GL_COLOR_BUFFER_BIT);
5482         glUseProgram(m_draw_program);
5483         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5484 
5485         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1)))
5486         {
5487             return ERROR;
5488         }
5489         return NO_ERROR;
5490     }
5491 
Cleanup()5492     virtual long Cleanup()
5493     {
5494         glUseProgram(0);
5495         glDeleteBuffers(1, &m_vbo);
5496         glDeleteBuffers(1, &m_pbo);
5497         glDeleteTextures(1, &m_texture);
5498         glDeleteProgram(m_store_program);
5499         glDeleteProgram(m_draw_program);
5500         glDeleteVertexArrays(1, &m_vao);
5501         return NO_ERROR;
5502     }
5503 };
5504 //-----------------------------------------------------------------------------
5505 // 2.1.6 AdvancedSyncImageAccess2
5506 //-----------------------------------------------------------------------------
5507 class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
5508 {
5509     GLuint m_texture;
5510     GLuint m_store_program;
5511     GLuint m_draw_program;
5512     GLuint m_vao;
5513     GLuint m_vbo;
5514 
Setup()5515     virtual long Setup()
5516     {
5517         m_texture       = 0;
5518         m_store_program = 0;
5519         m_draw_program  = 0;
5520         m_vao           = 0;
5521         m_vbo           = 0;
5522         return NO_ERROR;
5523     }
5524 
Run()5525     virtual long Run()
5526     {
5527         const char *const glsl_vs =
5528             "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5529             "void main() {" NL "  gl_Position = i_position;" NL "  vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5530         const char *const glsl_store_fs =
5531             "#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
5532             "  imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL "  discard;" NL "}";
5533         const char *const glsl_draw_fs =
5534             "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5535             "uniform sampler2D g_sampler;" NL "void main() {" NL "  o_color = texture(g_sampler, vs_texcoord);" NL "}";
5536         m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5537         m_draw_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5538 
5539         int width  = getWindowWidth();
5540         int height = getWindowHeight();
5541         scaleDimensionsToMemory(width, height, 1, 1, 16, 16);
5542 
5543         glGenTextures(1, &m_texture);
5544         glBindTexture(GL_TEXTURE_2D, m_texture);
5545         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5546         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
5547         glBindTexture(GL_TEXTURE_2D, 0);
5548 
5549         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5550 
5551         glViewport(0, 0, width, height);
5552         glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5553         glUseProgram(m_store_program);
5554         glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
5555         glBindVertexArray(m_vao);
5556         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5557 
5558         glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5559 
5560         glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5561         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5562 
5563         glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
5564 
5565         glClear(GL_COLOR_BUFFER_BIT);
5566         glBindTexture(GL_TEXTURE_2D, m_texture);
5567         glUseProgram(m_draw_program);
5568         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5569 
5570         if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5571         {
5572             return ERROR;
5573         }
5574         return NO_ERROR;
5575     }
5576 
Cleanup()5577     virtual long Cleanup()
5578     {
5579         glViewport(0, 0, getWindowWidth(), getWindowHeight());
5580         glUseProgram(0);
5581         glDeleteBuffers(1, &m_vbo);
5582         glDeleteTextures(1, &m_texture);
5583         glDeleteProgram(m_store_program);
5584         glDeleteProgram(m_draw_program);
5585         glDeleteVertexArrays(1, &m_vao);
5586         return NO_ERROR;
5587     }
5588 };
5589 //-----------------------------------------------------------------------------
5590 // 2.1.7 AdvancedSyncBufferUpdate
5591 //-----------------------------------------------------------------------------
5592 class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase
5593 {
5594     GLuint m_buffer;
5595     GLuint m_buffer_tex;
5596     GLuint m_store_program;
5597     GLuint m_attribless_vao;
5598 
Setup()5599     virtual long Setup()
5600     {
5601         m_buffer         = 0;
5602         m_buffer_tex     = 0;
5603         m_store_program  = 0;
5604         m_attribless_vao = 0;
5605         return NO_ERROR;
5606     }
5607 
Run()5608     virtual long Run()
5609     {
5610         if (!SupportedInVS(1))
5611             return NOT_SUPPORTED;
5612         const char *const glsl_store_vs =
5613             "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5614             "  imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}";
5615         m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5616 
5617         glGenVertexArrays(1, &m_attribless_vao);
5618         glBindVertexArray(m_attribless_vao);
5619 
5620         glGenBuffers(1, &m_buffer);
5621         glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5622         glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW);
5623         glBindBuffer(GL_TEXTURE_BUFFER, 0);
5624 
5625         glGenTextures(1, &m_buffer_tex);
5626         glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5627         glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5628 
5629         glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5630 
5631         glEnable(GL_RASTERIZER_DISCARD);
5632         glUseProgram(m_store_program);
5633         glDrawArrays(GL_POINTS, 0, 1000);
5634 
5635         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5636 
5637         glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5638         vec4 *ptr =
5639             reinterpret_cast<vec4 *>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT));
5640         for (int i = 0; i < 1000; ++i)
5641         {
5642             if (!IsEqual(ptr[i], vec4(static_cast<float>(i))))
5643             {
5644                 m_context.getTestContext().getLog()
5645                     << tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage;
5646                 return ERROR;
5647             }
5648         }
5649         return NO_ERROR;
5650     }
5651 
Cleanup()5652     virtual long Cleanup()
5653     {
5654         glDisable(GL_RASTERIZER_DISCARD);
5655         glUseProgram(0);
5656         glDeleteBuffers(1, &m_buffer);
5657         glDeleteTextures(1, &m_buffer_tex);
5658         glDeleteProgram(m_store_program);
5659         glDeleteVertexArrays(1, &m_attribless_vao);
5660         return NO_ERROR;
5661     }
5662 };
5663 //-----------------------------------------------------------------------------
5664 // 2.2.1 AdvancedAllStagesOneImage
5665 //-----------------------------------------------------------------------------
5666 class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
5667 {
5668     GLuint m_program;
5669     GLuint m_vao;
5670     GLuint m_vbo;
5671     GLuint m_ebo;
5672     GLuint m_buffer;
5673     GLuint m_buffer_tex;
5674     GLuint m_texture;
5675 
Setup()5676     virtual long Setup()
5677     {
5678         m_program    = 0;
5679         m_vao        = 0;
5680         m_vbo        = 0;
5681         m_ebo        = 0;
5682         m_buffer     = 0;
5683         m_buffer_tex = 0;
5684         m_texture    = 0;
5685         return NO_ERROR;
5686     }
5687 
Run()5688     virtual long Run()
5689     {
5690         if (!SupportedInGeomStages(2))
5691             return NOT_SUPPORTED;
5692         const char *const glsl_vs =
5693             "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5694             "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5695             "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5696             "  gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL "  imageAtomicAdd(g_buffer, 0, 1);" NL
5697             "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5698         const char *const glsl_tcs =
5699             "#version 420 core" NL "layout(vertices = 1) out;" NL
5700             "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5701             "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5702             "  gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL "  gl_TessLevelInner[0] = 1.0;" NL
5703             "  gl_TessLevelInner[1] = 1.0;" NL "  gl_TessLevelOuter[0] = 1.0;" NL "  gl_TessLevelOuter[1] = 1.0;" NL
5704             "  gl_TessLevelOuter[2] = 1.0;" NL "  gl_TessLevelOuter[3] = 1.0;" NL "  imageAtomicAdd(g_buffer, 0, 1);" NL
5705             "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5706         const char *const glsl_tes =
5707             "#version 420 core" NL "layout(triangles, point_mode) in;" NL
5708             "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5709             "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5710             "  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5711             "  gl_Position = gl_in[0].gl_Position;" NL "}";
5712         const char *const glsl_gs =
5713             "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
5714             "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5715             "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5716             "  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5717             "  gl_Position = gl_in[0].gl_Position;" NL "  EmitVertex();" NL "}";
5718         const char *const glsl_fs =
5719             "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5720             "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5721             "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5722             "  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5723             "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5724         m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs);
5725         glUseProgram(m_program);
5726         glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5727         glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5728 
5729         CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
5730 
5731         GLint i32 = 0;
5732         glGenBuffers(1, &m_buffer);
5733         glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5734         glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW);
5735         glBindBuffer(GL_TEXTURE_BUFFER, 0);
5736 
5737         glGenTextures(1, &m_buffer_tex);
5738         glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5739         glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer);
5740         glBindTexture(GL_TEXTURE_BUFFER, 0);
5741 
5742         GLuint ui32 = 0;
5743         glGenTextures(1, &m_texture);
5744         glBindTexture(GL_TEXTURE_2D, m_texture);
5745         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5746         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5747         glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5748         glBindTexture(GL_TEXTURE_2D, 0);
5749 
5750         glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5751         glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5752 
5753         glBindVertexArray(m_vao);
5754         glPatchParameteri(GL_PATCH_VERTICES, 1);
5755 
5756         glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0);
5757         glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1);
5758 
5759         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5760         glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5761         glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32);
5762         if (i32 < 20 || i32 > 50)
5763         {
5764             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32
5765                                                 << " should be in the range [20;50]" << tcu::TestLog::EndMessage;
5766             return ERROR;
5767         }
5768 
5769         glBindTexture(GL_TEXTURE_2D, m_texture);
5770         glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5771         if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32))
5772         {
5773             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be "
5774                                                 << (2 * i32) << tcu::TestLog::EndMessage;
5775             return ERROR;
5776         }
5777 
5778         return NO_ERROR;
5779     }
5780 
Cleanup()5781     virtual long Cleanup()
5782     {
5783         glPatchParameteri(GL_PATCH_VERTICES, 3);
5784         glUseProgram(0);
5785         glDeleteBuffers(1, &m_buffer);
5786         glDeleteBuffers(1, &m_vbo);
5787         glDeleteBuffers(1, &m_ebo);
5788         glDeleteTextures(1, &m_buffer_tex);
5789         glDeleteTextures(1, &m_texture);
5790         glDeleteProgram(m_program);
5791         glDeleteVertexArrays(1, &m_vao);
5792         return NO_ERROR;
5793     }
5794 };
5795 //-----------------------------------------------------------------------------
5796 // 2.3.1 AdvancedMemoryDependentInvocation
5797 //-----------------------------------------------------------------------------
5798 class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase
5799 {
5800     GLuint m_buffer;
5801     GLuint m_buffer_tex;
5802     GLuint m_texture;
5803     GLuint m_program;
5804     GLuint m_vao;
5805     GLuint m_vbo;
5806 
Setup()5807     virtual long Setup()
5808     {
5809         m_buffer     = 0;
5810         m_buffer_tex = 0;
5811         m_texture    = 0;
5812         m_program    = 0;
5813         m_vao        = 0;
5814         m_vbo        = 0;
5815         return NO_ERROR;
5816     }
5817 
Run()5818     virtual long Run()
5819     {
5820         if (!SupportedInVS(2))
5821             return NOT_SUPPORTED;
5822         const char *const glsl_vs =
5823             "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5824             "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL
5825             "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5826             "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL "  gl_Position = i_position;" NL
5827             "  vs_color = i_color;" NL "  imageStore(g_buffer, 0, vec4(1.0));" NL
5828             "  imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL "  memoryBarrier();" NL "}";
5829         const char *const glsl_fs =
5830             "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5831             "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5832             "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL "  o_color = vs_color;" NL
5833             "  if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
5834             "  if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}";
5835         m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5836         glUseProgram(m_program);
5837         glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5838         glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5839 
5840         vec4 zero(0);
5841         glGenBuffers(1, &m_buffer);
5842         glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5843         glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW);
5844         glBindBuffer(GL_TEXTURE_BUFFER, 0);
5845 
5846         glGenTextures(1, &m_buffer_tex);
5847         glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5848         glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5849         glBindTexture(GL_TEXTURE_BUFFER, 0);
5850 
5851         glGenTextures(1, &m_texture);
5852         glBindTexture(GL_TEXTURE_2D, m_texture);
5853         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5854         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero);
5855         glBindTexture(GL_TEXTURE_2D, 0);
5856 
5857         glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5858         glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5859 
5860         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5861 
5862         glClear(GL_COLOR_BUFFER_BIT);
5863         glBindVertexArray(m_vao);
5864         glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5865 
5866         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5867         {
5868             return ERROR;
5869         }
5870         return NO_ERROR;
5871     }
5872 
Cleanup()5873     virtual long Cleanup()
5874     {
5875         glUseProgram(0);
5876         glDeleteBuffers(1, &m_vbo);
5877         glDeleteBuffers(1, &m_buffer);
5878         glDeleteTextures(1, &m_texture);
5879         glDeleteTextures(1, &m_buffer_tex);
5880         glDeleteProgram(m_program);
5881         glDeleteVertexArrays(1, &m_vao);
5882         return NO_ERROR;
5883     }
5884 };
5885 //-----------------------------------------------------------------------------
5886 // 2.3.2 AdvancedMemoryOrder
5887 //-----------------------------------------------------------------------------
5888 class AdvancedMemoryOrder : public ShaderImageLoadStoreBase
5889 {
5890     GLuint m_buffer;
5891     GLuint m_buffer_tex;
5892     GLuint m_texture;
5893     GLuint m_program;
5894     GLuint m_vao;
5895     GLuint m_vbo;
5896 
Setup()5897     virtual long Setup()
5898     {
5899         m_buffer     = 0;
5900         m_buffer_tex = 0;
5901         m_texture    = 0;
5902         m_program    = 0;
5903         m_vao        = 0;
5904         m_vbo        = 0;
5905         return NO_ERROR;
5906     }
5907 
Run()5908     virtual long Run()
5909     {
5910         if (!SupportedInVS(1))
5911             return NOT_SUPPORTED;
5912         const char *const glsl_vs =
5913             "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
5914             "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL
5915             "  gl_Position = i_position;" NL "  vs_color = vec4(0, 1, 0, 1);" NL
5916             "  imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL "  imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL
5917             "  imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL
5918             "  if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}";
5919         const char *const glsl_fs =
5920             "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5921             "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL "  o_color = vs_color;" NL
5922             "  ivec2 coord = ivec2(gl_FragCoord);" NL "  for (int i = 0; i < 3; ++i) {" NL
5923             "    imageStore(g_image, coord, vec4(i));" NL "    vec4 v = imageLoad(g_image, coord);" NL
5924             "    if (v != vec4(i)) {" NL "      o_color = vec4(v.xyz, 0.0);" NL "      break;" NL "    }" NL "  }" NL
5925             "}";
5926         m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5927         glUseProgram(m_program);
5928         glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5929         glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5930 
5931         glGenBuffers(1, &m_buffer);
5932         glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5933         glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
5934         glBindBuffer(GL_TEXTURE_BUFFER, 0);
5935 
5936         glGenTextures(1, &m_buffer_tex);
5937         glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5938         glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5939         glBindTexture(GL_TEXTURE_BUFFER, 0);
5940 
5941         int width  = getWindowWidth();
5942         int height = getWindowHeight();
5943         scaleDimensionsToMemory(width, height, 1, 2, 16, 16);
5944 
5945         std::vector<vec4> data(width * height);
5946         glGenTextures(1, &m_texture);
5947         glBindTexture(GL_TEXTURE_2D, m_texture);
5948         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5949         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
5950         glBindTexture(GL_TEXTURE_2D, 0);
5951 
5952         glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5953         glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5954 
5955         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5956 
5957         glClear(GL_COLOR_BUFFER_BIT);
5958         glViewport(0, 0, width, height);
5959         glBindVertexArray(m_vao);
5960         glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5961 
5962         if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5963         {
5964             return ERROR;
5965         }
5966         return NO_ERROR;
5967     }
5968 
Cleanup()5969     virtual long Cleanup()
5970     {
5971         glViewport(0, 0, getWindowWidth(), getWindowHeight());
5972         glUseProgram(0);
5973         glDeleteBuffers(1, &m_vbo);
5974         glDeleteBuffers(1, &m_buffer);
5975         glDeleteTextures(1, &m_texture);
5976         glDeleteTextures(1, &m_buffer_tex);
5977         glDeleteProgram(m_program);
5978         glDeleteVertexArrays(1, &m_vao);
5979         return NO_ERROR;
5980     }
5981 };
5982 //-----------------------------------------------------------------------------
5983 // 2.4.1 AdvancedSSOSimple
5984 //-----------------------------------------------------------------------------
5985 class AdvancedSSOSimple : public ShaderImageLoadStoreBase
5986 {
5987     GLuint m_texture;
5988     GLuint m_pipeline[2];
5989     GLuint m_vsp, m_fsp0, m_fsp1;
5990     GLuint m_vao, m_vbo;
5991 
Setup()5992     virtual long Setup()
5993     {
5994         glGenTextures(1, &m_texture);
5995         glGenProgramPipelines(2, m_pipeline);
5996         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5997 
5998         const char *const glsl_vs =
5999             "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6000             "  vec4 gl_Position;" NL "};" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
6001         const char *const glsl_fs0 =
6002             "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL
6003             "  for (int i = 0; i < g_image.length(); ++i) {" NL
6004             "    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL "  }" NL "  discard;" NL "}";
6005         const char *const glsl_fs1 =
6006             "#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL
6007             "  for (int i = 0; i < g_image.length(); ++i) {" NL
6008             "    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL "  }" NL "  discard;" NL "}";
6009         m_vsp  = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6010         m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
6011         m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
6012 
6013         return NO_ERROR;
6014     }
6015 
Run()6016     virtual long Run()
6017     {
6018         glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0);
6019         glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2);
6020         glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4);
6021         glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6);
6022 
6023         glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1);
6024         glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3);
6025         glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5);
6026         glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7);
6027 
6028         glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
6029         glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
6030 
6031         glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
6032         glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
6033 
6034         int width  = getWindowWidth();
6035         int height = getWindowHeight();
6036         scaleDimensionsToMemory(width, height, 8, 8, 16, 16);
6037 
6038         glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6039         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6040         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6041 
6042         glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6043         glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
6044         glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F);
6045         glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
6046         glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
6047         glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F);
6048         glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
6049         glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F);
6050 
6051         glBindVertexArray(m_vao);
6052 
6053         glViewport(0, 0, width, height);
6054         glBindProgramPipeline(m_pipeline[0]);
6055         glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6056 
6057         glBindProgramPipeline(m_pipeline[1]);
6058         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6059 
6060         std::vector<vec4> data(width * height * 8);
6061         glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6062 
6063         for (int layer = 0; layer < 8; ++layer)
6064         {
6065             for (int h = 0; h < height; ++h)
6066             {
6067                 for (int w = 0; w < width; ++w)
6068                 {
6069                     const vec4 c = data[layer * width * height + h * width + w];
6070                     if (layer % 2)
6071                     {
6072                         if (!IsEqual(c, vec4(2.0f)))
6073                         {
6074                             return ERROR;
6075                         }
6076                     }
6077                     else
6078                     {
6079                         if (!IsEqual(c, vec4(1.0f)))
6080                         {
6081                             return ERROR;
6082                         }
6083                     }
6084                 }
6085             }
6086         }
6087         return NO_ERROR;
6088     }
6089 
Cleanup()6090     virtual long Cleanup()
6091     {
6092         glViewport(0, 0, getWindowWidth(), getWindowHeight());
6093         glDeleteBuffers(1, &m_vbo);
6094         glDeleteTextures(1, &m_texture);
6095         glDeleteProgram(m_vsp);
6096         glDeleteProgram(m_fsp0);
6097         glDeleteProgram(m_fsp1);
6098         glDeleteVertexArrays(1, &m_vao);
6099         glDeleteProgramPipelines(2, m_pipeline);
6100         return NO_ERROR;
6101     }
6102 };
6103 //-----------------------------------------------------------------------------
6104 // 2.4.2 AdvancedSSOAtomicCounters
6105 //-----------------------------------------------------------------------------
6106 class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase
6107 {
6108     GLuint m_buffer, m_buffer_tex;
6109     GLuint m_counter_buffer;
6110     GLuint m_transform_buffer;
6111     GLuint m_pipeline;
6112     GLuint m_vao, m_vbo;
6113     GLuint m_vsp, m_fsp;
6114 
Setup()6115     virtual long Setup()
6116     {
6117         m_vao = 0;
6118         m_vbo = 0;
6119         m_vsp = 0;
6120         m_fsp = 0;
6121         glGenBuffers(1, &m_buffer);
6122         glGenTextures(1, &m_buffer_tex);
6123         glGenBuffers(1, &m_counter_buffer);
6124         glGenBuffers(1, &m_transform_buffer);
6125         glGenProgramPipelines(1, &m_pipeline);
6126         return NO_ERROR;
6127     }
6128 
Run()6129     virtual long Run()
6130     {
6131         if (!SupportedInVS(1))
6132             return NOT_SUPPORTED;
6133 
6134         CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
6135         const char *const glsl_vs =
6136             "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6137             "layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL
6138             "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL
6139             "  mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL
6140             "layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL
6141             "  gl_Position = g_transform.mvp * i_position;" NL "  o_color = i_color;" NL
6142             "  const uint index = atomicCounterIncrement(g_counter);" NL
6143             "  imageStore(g_buffer, int(index), gl_Position);" NL "}";
6144         const char *const glsl_fs =
6145             "#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL
6146             "layout(location = 0) out vec4 o_color;" NL "void main() {" NL "  o_color = i_color;" NL "}";
6147         m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6148         m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
6149 
6150         glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6151         glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
6152 
6153         glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6154         glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
6155 
6156         glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
6157         glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
6158 
6159         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer);
6160         vec4 zero(0);
6161         glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW);
6162 
6163         glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer);
6164         mat4 identity(1);
6165         glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW);
6166 
6167         glClear(GL_COLOR_BUFFER_BIT);
6168         glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
6169         glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer);
6170         glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6171         glBindVertexArray(m_vao);
6172         glBindProgramPipeline(m_pipeline);
6173         glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6174 
6175         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6176         {
6177             return ERROR;
6178         }
6179 
6180         std::vector<vec4> data(4);
6181         glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6182         glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]);
6183 
6184         for (int i = 0; i < 4; ++i)
6185         {
6186             if (!IsEqual(data[i], vec4(-1.0f, -1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, -1.0f, 0.0f, 1.0f)) &&
6187                 !IsEqual(data[i], vec4(-1.0f, 1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, 1.0f, 0.0f, 1.0f)))
6188             {
6189                 return ERROR;
6190             }
6191         }
6192 
6193         return NO_ERROR;
6194     }
6195 
Cleanup()6196     virtual long Cleanup()
6197     {
6198         glDeleteBuffers(1, &m_buffer);
6199         glDeleteBuffers(1, &m_vbo);
6200         glDeleteBuffers(1, &m_counter_buffer);
6201         glDeleteBuffers(1, &m_transform_buffer);
6202         glDeleteTextures(1, &m_buffer_tex);
6203         glDeleteProgram(m_vsp);
6204         glDeleteProgram(m_fsp);
6205         glDeleteVertexArrays(1, &m_vao);
6206         glDeleteProgramPipelines(1, &m_pipeline);
6207         return NO_ERROR;
6208     }
6209 };
6210 //-----------------------------------------------------------------------------
6211 // 2.4.3 AdvancedSSOSubroutine
6212 //-----------------------------------------------------------------------------
6213 class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase
6214 {
6215     GLuint m_texture;
6216     GLuint m_attribless_vao;
6217     GLuint m_program;
6218     GLint m_draw_buffer;
6219 
Setup()6220     virtual long Setup()
6221     {
6222         glGenTextures(1, &m_texture);
6223         glGenVertexArrays(1, &m_attribless_vao);
6224 
6225         const char *const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL
6226                                     "const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL
6227                                     "void main() {" NL "  gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}";
6228         const char *const glsl_fs =
6229             "#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL
6230             "writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL
6231             "subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL
6232             "  imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL
6233             "  imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL
6234             "  imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL
6235             "subroutine(Brush) void Brush1(ivec2 coord) {" NL
6236             "  imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL
6237             "  imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL
6238             "  imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL
6239             "  g_brush(ivec2(gl_FragCoord));" NL "}";
6240         m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6241 
6242         return NO_ERROR;
6243     }
6244 
Run()6245     virtual long Run()
6246     {
6247         int width  = getWindowWidth();
6248         int height = getWindowHeight();
6249         scaleDimensionsToMemory(width, height, 3, 3, 16, 16);
6250 
6251         glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1);
6252         glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1);
6253 
6254         glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6255         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6256         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 3, 0, GL_RGBA, GL_FLOAT, NULL);
6257 
6258         glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer);
6259 
6260         glDrawBuffer(GL_NONE);
6261         glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);
6262         glUseProgram(m_program);
6263         glBindVertexArray(m_attribless_vao);
6264 
6265         const GLuint indices[2] = {glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"),
6266                                    glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1")};
6267 
6268         glViewport(0, 0, width, height);
6269         glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]);
6270         glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6271 
6272         std::vector<vec4> data(width * height * 3);
6273         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6274         glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6275 
6276         for (int layer = 0; layer < 3; ++layer)
6277         {
6278             for (int h = 0; h < height; ++h)
6279             {
6280                 for (int w = 0; w < width; ++w)
6281                 {
6282                     const vec4 c = data[layer * width * height + h * width + w];
6283                     if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6284                     {
6285                         m_context.getTestContext().getLog()
6286                             << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6287                             << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6288                         return ERROR;
6289                     }
6290                     else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6291                     {
6292                         m_context.getTestContext().getLog()
6293                             << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6294                             << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6295                         return ERROR;
6296                     }
6297                     else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6298                     {
6299                         m_context.getTestContext().getLog()
6300                             << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6301                             << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6302                         return ERROR;
6303                     }
6304                 }
6305             }
6306         }
6307 
6308         glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]);
6309         glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6310 
6311         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6312         glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6313 
6314         for (int layer = 0; layer < 3; ++layer)
6315         {
6316             for (int h = 0; h < height; ++h)
6317             {
6318                 for (int w = 0; w < width; ++w)
6319                 {
6320                     const vec4 c = data[layer * width * height + h * width + w];
6321                     if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6322                     {
6323                         m_context.getTestContext().getLog()
6324                             << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6325                             << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6326                         return ERROR;
6327                     }
6328                     else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6329                     {
6330                         m_context.getTestContext().getLog()
6331                             << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6332                             << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6333                         return ERROR;
6334                     }
6335                     else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6336                     {
6337                         m_context.getTestContext().getLog()
6338                             << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6339                             << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6340                         return ERROR;
6341                     }
6342                 }
6343             }
6344         }
6345         return NO_ERROR;
6346     }
6347 
Cleanup()6348     virtual long Cleanup()
6349     {
6350         glViewport(0, 0, getWindowWidth(), getWindowHeight());
6351         glDrawBuffer(m_draw_buffer);
6352         glDeleteTextures(1, &m_texture);
6353         glUseProgram(0);
6354         glDeleteProgram(m_program);
6355         glDeleteVertexArrays(1, &m_attribless_vao);
6356         return NO_ERROR;
6357     }
6358 };
6359 //-----------------------------------------------------------------------------
6360 // 2.4.4 AdvancedSSOPerSample
6361 //-----------------------------------------------------------------------------
6362 class AdvancedSSOPerSample : public ShaderImageLoadStoreBase
6363 {
6364     GLuint m_texture;
6365     GLuint m_pipeline;
6366     GLuint m_vao, m_vbo, m_ebo;
6367     GLuint m_vsp, m_store_fsp, m_load_fsp;
6368 
Setup()6369     virtual long Setup()
6370     {
6371         m_vao       = 0;
6372         m_vbo       = 0;
6373         m_ebo       = 0;
6374         m_vsp       = 0;
6375         m_store_fsp = 0;
6376         m_load_fsp  = 0;
6377         glGenTextures(1, &m_texture);
6378         glGenProgramPipelines(1, &m_pipeline);
6379 
6380         return NO_ERROR;
6381     }
6382 
Run()6383     virtual long Run()
6384     {
6385         if (!SupportedSamples(4))
6386             return NOT_SUPPORTED;
6387 
6388         CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6389 
6390         const char *const glsl_vs =
6391             "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6392             "  vec4 gl_Position;" NL "};" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
6393         const char *const glsl_store_fs =
6394             "#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL
6395             "  imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}";
6396         const char *const glsl_load_fs =
6397             "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6398             "layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL
6399             "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != "
6400             "vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6401         m_vsp       = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6402         m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs);
6403         m_load_fsp  = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs);
6404 
6405         int width  = getWindowWidth();
6406         int height = getWindowHeight();
6407         scaleDimensionsToMemory(width, height, 1, 1, /* bpp*samples */ 16 * 4, 16);
6408 
6409         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture);
6410         glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, width, height, GL_FALSE);
6411         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
6412 
6413         glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6414         glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp);
6415 
6416         glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6417 
6418         glClear(GL_COLOR_BUFFER_BIT);
6419         glViewport(0, 0, width, height);
6420         glBindVertexArray(m_vao);
6421         glBindProgramPipeline(m_pipeline);
6422         glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6423 
6424         glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6425 
6426         glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp);
6427         glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6428 
6429         if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
6430         {
6431             return ERROR;
6432         }
6433         return NO_ERROR;
6434     }
6435 
Cleanup()6436     virtual long Cleanup()
6437     {
6438         glViewport(0, 0, getWindowWidth(), getWindowHeight());
6439         glDeleteBuffers(1, &m_vbo);
6440         glDeleteBuffers(1, &m_ebo);
6441         glDeleteTextures(1, &m_texture);
6442         glDeleteProgram(m_vsp);
6443         glDeleteProgram(m_store_fsp);
6444         glDeleteProgram(m_load_fsp);
6445         glDeleteVertexArrays(1, &m_vao);
6446         glDeleteProgramPipelines(1, &m_pipeline);
6447         return NO_ERROR;
6448     }
6449 };
6450 
6451 //-----------------------------------------------------------------------------
6452 // 2.5 AdvancedCopyImage
6453 //-----------------------------------------------------------------------------
6454 class AdvancedCopyImage : public ShaderImageLoadStoreBase
6455 {
6456     GLuint m_texture[2];
6457     GLuint m_program;
6458     GLuint m_vao, m_vbo, m_ebo;
6459 
Setup()6460     virtual long Setup()
6461     {
6462         glGenTextures(2, m_texture);
6463         CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6464 
6465         const char *const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6466                                     "void main() {" NL "  gl_Position = i_position;" NL "}";
6467         const char *const glsl_fs =
6468             "#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL
6469             "layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL
6470             "  ivec2 coord = ivec2(gl_FragCoord);" NL
6471             "  imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL "  discard;" NL "}";
6472         m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6473 
6474         return NO_ERROR;
6475     }
6476 
Run()6477     virtual long Run()
6478     {
6479         int width  = getWindowWidth();
6480         int height = getWindowHeight();
6481         scaleDimensionsToMemory(width, height, 2, 2, 16, 16);
6482 
6483         glUseProgram(m_program);
6484         glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0);
6485         glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1);
6486 
6487         std::vector<vec4> data(width * height, vec4(7.0f));
6488         glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6489         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6490         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
6491 
6492         glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6493         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6494         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
6495 
6496         glBindTexture(GL_TEXTURE_2D, 0);
6497 
6498         glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6499         glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
6500 
6501         glClear(GL_COLOR_BUFFER_BIT);
6502         glViewport(0, 0, width, height);
6503         glBindVertexArray(m_vao);
6504         glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6505 
6506         std::vector<vec4> rdata(width * height);
6507         glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6508         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]);
6509 
6510         for (int h = 0; h < height; ++h)
6511         {
6512             for (int w = 0; w < width; ++w)
6513             {
6514                 if (!IsEqual(rdata[h * width + w], vec4(7.0f)))
6515                 {
6516                     return ERROR;
6517                 }
6518             }
6519         }
6520         return NO_ERROR;
6521     }
6522 
Cleanup()6523     virtual long Cleanup()
6524     {
6525         glViewport(0, 0, getWindowWidth(), getWindowHeight());
6526         glUseProgram(0);
6527         glDeleteBuffers(1, &m_vbo);
6528         glDeleteBuffers(1, &m_ebo);
6529         glDeleteTextures(2, m_texture);
6530         glDeleteProgram(m_program);
6531         glDeleteVertexArrays(1, &m_vao);
6532         return NO_ERROR;
6533     }
6534 };
6535 //-----------------------------------------------------------------------------
6536 // 2.6 AdvancedAllMips
6537 //-----------------------------------------------------------------------------
6538 class AdvancedAllMips : public ShaderImageLoadStoreBase
6539 {
6540     GLuint m_texture;
6541     GLuint m_store_program, m_load_program;
6542     GLuint m_vao, m_vbo, m_ebo;
6543 
Setup()6544     virtual long Setup()
6545     {
6546         glGenTextures(1, &m_texture);
6547         CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6548 
6549         const char *const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6550                                     "void main() {" NL "  gl_Position = i_position;" NL "}";
6551         const char *const glsl_store_fs =
6552             "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6553             "  for (int i = 0; i < 6; ++i) {" NL "    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL "  }" NL
6554             "  discard;" NL "}";
6555         const char *const glsl_load_fs =
6556             "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6557             "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6558             "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  for (int i = 0; i < 6; ++i) {" NL
6559             "    const ivec2 coord = ivec2(gl_FragCoord);" NL "    const vec4 c = imageLoad(g_image[i], coord);" NL
6560             "    if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  }" NL "}";
6561         m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
6562         m_load_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs);
6563 
6564         return NO_ERROR;
6565     }
6566 
Run()6567     virtual long Run()
6568     {
6569         glUseProgram(m_store_program);
6570         glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0);
6571         glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1);
6572         glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2);
6573         glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3);
6574         glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4);
6575         glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5);
6576         glUseProgram(0);
6577 
6578         glUseProgram(m_load_program);
6579         glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0);
6580         glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1);
6581         glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2);
6582         glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3);
6583         glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4);
6584         glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5);
6585         glUseProgram(0);
6586 
6587         glBindTexture(GL_TEXTURE_2D, m_texture);
6588         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
6589         glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
6590         glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6591         glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
6592         glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
6593         glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
6594         glBindTexture(GL_TEXTURE_2D, 0);
6595 
6596         glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6597         glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6598         glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6599         glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6600         glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6601         glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6602 
6603         glViewport(0, 0, 32, 32);
6604         glBindVertexArray(m_vao);
6605 
6606         glClear(GL_COLOR_BUFFER_BIT);
6607         glUseProgram(m_store_program);
6608         glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6609 
6610         glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6611 
6612         glUseProgram(m_load_program);
6613         glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6614 
6615         if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1)))
6616         {
6617             return ERROR;
6618         }
6619         return NO_ERROR;
6620     }
6621 
Cleanup()6622     virtual long Cleanup()
6623     {
6624         glViewport(0, 0, getWindowWidth(), getWindowHeight());
6625         glUseProgram(0);
6626         glDeleteBuffers(1, &m_vbo);
6627         glDeleteBuffers(1, &m_ebo);
6628         glDeleteTextures(1, &m_texture);
6629         glDeleteProgram(m_store_program);
6630         glDeleteProgram(m_load_program);
6631         glDeleteVertexArrays(1, &m_vao);
6632         return NO_ERROR;
6633     }
6634 };
6635 //-----------------------------------------------------------------------------
6636 // 2.7 AdvancedCast
6637 //-----------------------------------------------------------------------------
6638 class AdvancedCast : public ShaderImageLoadStoreBase
6639 {
6640     GLuint m_texture[2];
6641     GLuint m_program;
6642     GLuint m_vao, m_vbo, m_ebo;
6643 
Setup()6644     virtual long Setup()
6645     {
6646         glGenTextures(2, m_texture);
6647         CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6648 
6649         const char *const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6650                                     "void main() {" NL "  gl_Position = i_position;" NL "}";
6651         const char *const glsl_fs =
6652             "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6653             "layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL
6654             "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  ivec2 coord = ivec2(gl_FragCoord);" NL
6655             "  if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6656             "  if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6657             "  if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6658             "  if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6659         m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6660 
6661         return NO_ERROR;
6662     }
6663 
Run()6664     virtual long Run()
6665     {
6666         glUseProgram(m_program);
6667         glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0);
6668         glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1);
6669 
6670         {
6671             std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6672             glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6673             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6674             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6675                          &data[0]);
6676 
6677             glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6678             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6679             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6680                          &data[0]);
6681 
6682             glBindTexture(GL_TEXTURE_2D, 0);
6683         }
6684 
6685         glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
6686         glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
6687 
6688         glClear(GL_COLOR_BUFFER_BIT);
6689         glBindVertexArray(m_vao);
6690         glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6691 
6692         std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6693         glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6694         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6695         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6696 
6697         for (int h = 0; h < getWindowHeight(); ++h)
6698         {
6699             for (int w = 0; w < getWindowWidth(); ++w)
6700             {
6701                 const GLubyte c[4] = {
6702                     data[h * (getWindowWidth() * 4) + w * 4 + 0],
6703                     data[h * (getWindowWidth() * 4) + w * 4 + 1],
6704                     data[h * (getWindowWidth() * 4) + w * 4 + 2],
6705                     data[h * (getWindowWidth() * 4) + w * 4 + 3],
6706                 };
6707                 if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6708                 {
6709                     m_context.getTestContext().getLog()
6710                         << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6711                         << ") should be (1 0 0 0)" << tcu::TestLog::EndMessage;
6712                     return ERROR;
6713                 }
6714             }
6715         }
6716 
6717         glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6718         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6719 
6720         for (int h = 0; h < getWindowHeight(); ++h)
6721         {
6722             for (int w = 0; w < getWindowWidth(); ++w)
6723             {
6724                 const GLubyte c[4] = {
6725                     data[h * (getWindowWidth() * 4) + w * 4 + 0],
6726                     data[h * (getWindowWidth() * 4) + w * 4 + 1],
6727                     data[h * (getWindowWidth() * 4) + w * 4 + 2],
6728                     data[h * (getWindowWidth() * 4) + w * 4 + 3],
6729                 };
6730                 if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6731                 {
6732                     m_context.getTestContext().getLog()
6733                         << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6734                         << ") should be (3 0 0 0)" << tcu::TestLog::EndMessage;
6735                     return ERROR;
6736                 }
6737             }
6738         }
6739 
6740         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6741         {
6742             return ERROR;
6743         }
6744         return NO_ERROR;
6745     }
6746 
Cleanup()6747     virtual long Cleanup()
6748     {
6749         glUseProgram(0);
6750         glDeleteBuffers(1, &m_vbo);
6751         glDeleteBuffers(1, &m_ebo);
6752         glDeleteTextures(2, m_texture);
6753         glDeleteProgram(m_program);
6754         glDeleteVertexArrays(1, &m_vao);
6755         return NO_ERROR;
6756     }
6757 };
6758 
6759 /** Test "imageLoad() and imageStore() for single-byte data alignment" description follows.
6760  *
6761  *  Steps:
6762  *  - create two textures: "source" and "destination". Fill "source"
6763  *  texture with unique values. Fill "destination" texture with zeros,
6764  *  - prepare a program object that will read texel from "source" image at given
6765  *  coordinates and write its value to "destination" image at same
6766  *  coordinates,
6767  *  - bind "source" and "destination" textures as "source" and "destination"
6768  *  image uniforms,
6769  *  - render "full screen" quad (left bottom corner at -1,-1 and right top
6770  *  corner at 1,1),
6771  *  - verify that texel values in "destination" texture match those in
6772  *  "source" texture (use glGetTexImage).
6773  *
6774  *  Test with 2D R8UI textures with following dimensions:
6775  *  - 16x16,
6776  *  - 16x17,
6777  *  - 17x16,
6778  *  - 17x17,
6779  *  - 16x18,
6780  *  - 18x16,
6781  *  - 18x18,
6782  *  - 19x16,
6783  *  - 16x19,
6784  *  - 19x19.
6785  *
6786  *  Note that default data alignment should cause problems with packing/
6787  *  /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters
6788  *  of pixel storage mode have to be changed to one byte alignment.
6789  *
6790  *  Program should consist of vertex and fragment shader. Vertex shader should
6791  *  pass vertex position through. Fragment shader should do imageLoad() and
6792  *  imageStore() operations at coordinates gl_FragCoord.
6793  **/
6794 class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase
6795 {
6796 private:
6797     /* Structures */
6798     struct TextureDimensions
6799     {
6800         GLuint m_width;
6801         GLuint m_height;
6802 
TextureDimensionsgl4cts::__anonf7c7fa4f0111::ImageLoadStoreDataAlignmentTest::TextureDimensions6803         TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height)
6804         {
6805         }
6806     };
6807 
6808     /* Typedefs */
6809     typedef std::deque<TextureDimensions> TextureDimensionsList;
6810 
6811     /* Fields */
6812     GLuint m_destination_texture_id;
6813     GLuint m_program_id;
6814     TextureDimensionsList m_texture_dimensions;
6815     GLuint m_source_texture_id;
6816     GLuint m_vertex_array_object_id;
6817     GLuint m_vertex_buffer_id;
6818 
6819 public:
6820     /* Constructor */
ImageLoadStoreDataAlignmentTest()6821     ImageLoadStoreDataAlignmentTest()
6822         : m_destination_texture_id(0)
6823         , m_program_id(0)
6824         , m_source_texture_id(0)
6825         , m_vertex_array_object_id(0)
6826         , m_vertex_buffer_id(0)
6827     {
6828         /* Nothing to be done here */
6829     }
6830 
6831     /* Methods inherited from SubcaseBase */
Setup()6832     virtual long Setup()
6833     {
6834         /* Shaders code */
6835         const char *const vertex_shader_code = "#version 400 core\n"
6836                                                "#extension GL_ARB_shader_image_load_store : require\n"
6837                                                "\n"
6838                                                "precision highp float;\n"
6839                                                "\n"
6840                                                "in vec4 vs_in_position;\n"
6841                                                "\n"
6842                                                "void main()\n"
6843                                                "{\n"
6844                                                "    gl_Position = vs_in_position;\n"
6845                                                "}\n";
6846 
6847         const char *const fragment_shader_code =
6848             "#version 400 core\n"
6849             "#extension GL_ARB_shader_image_load_store : require\n"
6850             "\n"
6851             "precision highp float;\n"
6852             "\n"
6853             "layout(r8ui) writeonly uniform uimage2D u_destination_image;\n"
6854             "layout(r8ui) readonly  uniform uimage2D u_source_image;\n"
6855             "\n"
6856             "void main()\n"
6857             "{\n"
6858             "    uvec4 loaded_color = imageLoad (u_source_image,      ivec2(gl_FragCoord));\n"
6859             "                         imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
6860             "\n"
6861             "    discard;\n"
6862             "}\n";
6863 
6864         /* Vertex postions for "full screen" quad, made with triangle strip */
6865         static const GLfloat m_vertex_buffer_data[] = {
6866             -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
6867             -1.0f, 1.0f,  0.0f, 1.0f, /* left top */
6868             1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
6869             1.0f,  1.0f,  0.0f, 1.0f, /* right top */
6870         };
6871 
6872         /* Result of BuildProgram operation */
6873         bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
6874 
6875         /* Add all tested texture dimensions */
6876         m_texture_dimensions.push_back(TextureDimensions(16, 16));
6877         m_texture_dimensions.push_back(TextureDimensions(16, 17));
6878         m_texture_dimensions.push_back(TextureDimensions(17, 16));
6879         m_texture_dimensions.push_back(TextureDimensions(17, 17));
6880         m_texture_dimensions.push_back(TextureDimensions(16, 18));
6881         m_texture_dimensions.push_back(TextureDimensions(18, 16));
6882         m_texture_dimensions.push_back(TextureDimensions(18, 18));
6883         m_texture_dimensions.push_back(TextureDimensions(16, 19));
6884         m_texture_dimensions.push_back(TextureDimensions(19, 16));
6885         m_texture_dimensions.push_back(TextureDimensions(19, 19));
6886 
6887         /* Clean previous error */
6888         glGetError();
6889 
6890         /* Set single-byte data alignment */
6891         glPixelStorei(GL_PACK_ALIGNMENT, 1);
6892         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6893         GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei");
6894 
6895         /* Prepare buffer with vertex positions of "full screen" quad" */
6896         glGenBuffers(1, &m_vertex_buffer_id);
6897         GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
6898 
6899         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
6900         GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
6901 
6902         glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
6903         GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
6904 
6905         /* Generate vertex array object */
6906         glGenVertexArrays(1, &m_vertex_array_object_id);
6907         GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
6908 
6909         /* Prepare program object */
6910         m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
6911                                     fragment_shader_code, &is_program_correct);
6912         if (false == is_program_correct)
6913         {
6914             return ERROR;
6915         }
6916 
6917         /* Done */
6918         return NO_ERROR;
6919     }
6920 
Cleanup()6921     virtual long Cleanup()
6922     {
6923         /* Reset OpenGL state */
6924         glBindBuffer(GL_ARRAY_BUFFER, 0);
6925         glBindTexture(GL_TEXTURE_2D, 0);
6926         glBindVertexArray(0);
6927         glUseProgram(0);
6928 
6929         /* Delete program */
6930         if (0 != m_program_id)
6931         {
6932             glDeleteProgram(m_program_id);
6933             m_program_id = 0;
6934         }
6935 
6936         /* Delete textures */
6937         if (0 != m_destination_texture_id)
6938         {
6939             glDeleteTextures(1, &m_destination_texture_id);
6940             m_destination_texture_id = 0;
6941         }
6942 
6943         if (0 != m_source_texture_id)
6944         {
6945             glDeleteTextures(1, &m_source_texture_id);
6946             m_source_texture_id = 0;
6947         }
6948 
6949         /* Delete vertex array object */
6950         if (0 != m_vertex_array_object_id)
6951         {
6952             glDeleteVertexArrays(1, &m_vertex_array_object_id);
6953             m_vertex_array_object_id = 0;
6954         }
6955 
6956         /* Delete buffer */
6957         if (0 != m_vertex_buffer_id)
6958         {
6959             glDeleteBuffers(1, &m_vertex_buffer_id);
6960             m_vertex_buffer_id = 0;
6961         }
6962 
6963         /* Done */
6964         return NO_ERROR;
6965     }
6966 
Run()6967     virtual long Run()
6968     {
6969         bool result = true;
6970 
6971         /* For each dimension */
6972         for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it;
6973              ++it)
6974         {
6975             /* Prepare "source" and "destination" textures */
6976             GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id),
6977                                 "Create2DR8UIDestinationTexture");
6978             GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id),
6979                                 "Create2DR8UISourceTexture");
6980 
6981             /* Copy texture data with imageLoad() and imageStore() operations */
6982             Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id);
6983 
6984             /* Compare "source" and "destination" textures */
6985             if (false ==
6986                 Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height))
6987             {
6988                 m_context.getTestContext().getLog()
6989                     << tcu::TestLog::Message
6990                     << "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height
6991                     << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
6992 
6993                 result = false;
6994             }
6995 
6996             /* Destroy "source" and "destination" textures */
6997             glDeleteTextures(1, &m_destination_texture_id);
6998             glDeleteTextures(1, &m_source_texture_id);
6999 
7000             m_destination_texture_id = 0;
7001             m_source_texture_id      = 0;
7002         }
7003 
7004         if (false == result)
7005         {
7006             return ERROR;
7007         }
7008 
7009         /* Done */
7010         return NO_ERROR;
7011     }
7012 
7013 private:
7014     /* Private methods */
7015 
7016     /** Binds a texture to user-specified image unit and updates relevant sampler uniform
7017      *
7018      * @param program_id   Program object id
7019      * @param texture_id   Texture id
7020      * @param image_unit   Index of image unit
7021      * @param uniform_name Name of image uniform
7022      **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLuint image_unit,const char * uniform_name)7023     void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char *uniform_name)
7024     {
7025         /* Uniform location and invalid value */
7026         static const GLint invalid_uniform_location = -1;
7027         GLint image_uniform_location                = 0;
7028 
7029         /* Get uniform location */
7030         image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7031         GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7032         if (invalid_uniform_location == image_uniform_location)
7033         {
7034             throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__);
7035         }
7036 
7037         /* Bind texture to image unit */
7038         glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI);
7039         GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7040 
7041         /* Set uniform to image unit */
7042         glUniform1i(image_uniform_location, image_unit);
7043         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7044     }
7045 
7046     /** Compare two 2D R8UI textures
7047      *
7048      * @param left_texture_id  Id of "left" texture object
7049      * @param right_texture_id Id of "right" texture object
7050      * @param width            Width of the textures
7051      * @param height           Height of the textures
7052      *
7053      * @return true when texture data is identical, false otherwise
7054      **/
Compare2DR8UITextures(GLuint left_texture_id,GLuint right_texture_id,GLuint width,GLuint height)7055     bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height)
7056     {
7057         /* Size of textures */
7058         const GLuint texture_data_size = width * height;
7059 
7060         /* Storage for texture data */
7061         std::vector<GLubyte> left_texture_data;
7062         std::vector<GLubyte> right_texture_data;
7063 
7064         /* Alocate memory for texture data */
7065         left_texture_data.resize(texture_data_size);
7066         right_texture_data.resize(texture_data_size);
7067 
7068         /* Get "left" texture data */
7069         glBindTexture(GL_TEXTURE_2D, left_texture_id);
7070         GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7071 
7072         glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]);
7073         GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7074 
7075         /* Get "right" texture data */
7076         glBindTexture(GL_TEXTURE_2D, right_texture_id);
7077         GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7078 
7079         glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]);
7080         GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7081 
7082         /* Compare texels */
7083         return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7084     }
7085 
7086     /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7087      *
7088      * @param destination_texture_id Id of "destination" texture object
7089      * @param source_texture_id      Id of "source" texture object
7090      **/
Copy2DR8UITexture(GLuint destination_texture_id,GLuint source_texture_id)7091     void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id)
7092     {
7093         /* Uniform names */
7094         static const char *const destination_image_uniform_name = "u_destination_image";
7095         static const char *const source_image_uniform_name      = "u_source_image";
7096 
7097         /* Attribute name */
7098         static const char *const position_attribute_name = "vs_in_position";
7099 
7100         /* Attribute location and invalid value */
7101         static const GLint invalid_attribute_location = -1;
7102         GLint position_attribute_location             = 0;
7103 
7104         /* Set current program */
7105         glUseProgram(m_program_id);
7106         GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7107 
7108         /* Bind vertex array object */
7109         glBindVertexArray(m_vertex_array_object_id);
7110         GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7111 
7112         /* Bind buffer with quad vertex positions */
7113         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7114         GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7115 
7116         /* Set up position attribute */
7117         position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7118         GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7119         if (invalid_attribute_location == position_attribute_location)
7120         {
7121             throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7122                                      __LINE__);
7123         }
7124 
7125         glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7126                               0 /* stride */, 0);
7127         GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7128 
7129         glEnableVertexAttribArray(position_attribute_location);
7130         GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7131 
7132         /* Set up textures as source and destination images */
7133         BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name);
7134         BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name);
7135 
7136         /* Execute draw */
7137         glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7138         GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7139     }
7140 
7141     /** Create 2D R8UI texture and fills it with zeros
7142      *
7143      * @param width          Width of created texture
7144      * @param height         Height of created texture
7145      * @param out_texture_id Id of created texture, not modified if operation fails
7146      *
7147      * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7148      **/
Create2DR8UIDestinationTexture(GLuint width,GLuint height,GLuint & out_texture_id)7149     GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint &out_texture_id)
7150     {
7151         /* Texture size */
7152         const GLuint texture_size = width * height;
7153 
7154         /* Prepare storage for texture data */
7155         std::vector<GLubyte> texture_data;
7156         texture_data.resize(texture_size);
7157 
7158         /* Set all texels */
7159         for (GLuint i = 0; i < texture_size; ++i)
7160         {
7161             texture_data[i] = 0;
7162         }
7163 
7164         /* Create texture */
7165         return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7166     }
7167 
7168     /** Create 2D R8UI texture and fills it with increasing values, starting from 0
7169      *
7170      * @param width          Width of created texture
7171      * @param height         Height of created texture
7172      * @param out_texture_id Id of created texture, not modified if operation fails
7173      *
7174      * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7175      **/
Create2DR8UISourceTexture(GLuint width,GLuint height,GLuint & out_texture_id)7176     GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint &out_texture_id)
7177     {
7178         /* Texture size */
7179         const GLuint texture_size = width * height;
7180 
7181         /* Value of texel */
7182         GLubyte texel_value = 0;
7183 
7184         /* Prepare storage for texture data */
7185         std::vector<GLubyte> texture_data;
7186         texture_data.resize(texture_size);
7187 
7188         /* Set all texels */
7189         for (GLuint i = 0; i < texture_size; ++i)
7190         {
7191             texture_data[i] = texel_value++;
7192         }
7193 
7194         /* Create texture */
7195         return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7196     }
7197 
7198     /** Create 2D R8UI texture and fills it with user-provided data
7199      *
7200      * @param width          Width of created texture
7201      * @param height         Height of created texture
7202      * @param texture_data   Texture data
7203      * @param out_texture_id Id of created texture, not modified if operation fails
7204      *
7205      * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7206      **/
Create2DR8UITexture(GLuint width,GLuint height,const std::vector<GLubyte> & texture_data,GLuint & out_texture_id)7207     GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte> &texture_data,
7208                                GLuint &out_texture_id)
7209     {
7210         GLenum err        = 0;
7211         GLuint texture_id = 0;
7212 
7213         /* Generate texture */
7214         glGenTextures(1, &texture_id);
7215         err = glGetError();
7216         if (GL_NO_ERROR != err)
7217         {
7218             return err;
7219         }
7220 
7221         /* Bind texture */
7222         glBindTexture(GL_TEXTURE_2D, texture_id);
7223         err = glGetError();
7224         if (GL_NO_ERROR != err)
7225         {
7226             glDeleteTextures(1, &texture_id);
7227             return err;
7228         }
7229 
7230         /* Allocate storage and fill texture */
7231         glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER,
7232                      GL_UNSIGNED_BYTE, &texture_data[0]);
7233         err = glGetError();
7234         if (GL_NO_ERROR != err)
7235         {
7236             glDeleteTextures(1, &texture_id);
7237             return err;
7238         }
7239 
7240         /* Make texture complete */
7241         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7242         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7243         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7244         err = glGetError();
7245         if (GL_NO_ERROR != err)
7246         {
7247             glDeleteTextures(1, &texture_id);
7248             return err;
7249         }
7250 
7251         /* Set out_texture_id */
7252         out_texture_id = texture_id;
7253 
7254         /* Done */
7255         return GL_NO_ERROR;
7256     }
7257 };
7258 
7259 /** Test "imageLoad() and imageStore() for non-layered image bindings" description follows.
7260  *
7261  *  Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest).
7262  *
7263  *  Test non-layered image bindings (BindImageTexture <layered>: false) with:
7264  *  | Type           | Dimensions |
7265  *  | 2D_ARRAY       | 64x64x6    |
7266  *  | 3D             | 64x64x6    |
7267  *  | CUBE_MAP       | 64         |
7268  *  | CUBE_MAP_ARRAY | 64x3       |
7269  *
7270  *  Use RGBA8 format. All layers shall be tested.
7271  *
7272  *  Program should consist of vertex and fragment shader. Vertex shader should
7273  *  pass vertex position through. Fragment shader should do imageLoad() and
7274  *  imageStore() operations at coordinates gl_FragCoord. Fragment shader should
7275  *  use image2D as image type.
7276  **/
7277 class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase
7278 {
7279 private:
7280     /* Structures */
7281     struct TextureShapeDefinition
7282     {
7283         GLuint m_edge;
7284         GLuint m_n_elements;
7285         GLenum m_type;
7286 
TextureShapeDefinitiongl4cts::__anonf7c7fa4f0111::ImageLoadStoreNonLayeredBindingTest::TextureShapeDefinition7287         TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type)
7288             : m_edge(edge)
7289             , m_n_elements(n_elements)
7290             , m_type(type)
7291         {
7292         }
7293     };
7294 
7295     /* Typedefs */
7296     typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList;
7297 
7298     /* Fields */
7299     GLuint m_destination_texture_id;
7300     GLuint m_program_id;
7301     TextureShapeDefinitionList m_texture_shape_definitions;
7302     GLuint m_source_texture_id;
7303     GLuint m_vertex_array_object_id;
7304     GLuint m_vertex_buffer_id;
7305 
7306 public:
7307     /* Constructor */
ImageLoadStoreNonLayeredBindingTest()7308     ImageLoadStoreNonLayeredBindingTest()
7309         : m_destination_texture_id(0)
7310         , m_program_id(0)
7311         , m_source_texture_id(0)
7312         , m_vertex_array_object_id(0)
7313         , m_vertex_buffer_id(0)
7314     {
7315         /* Nothing to be done here */
7316     }
7317 
7318     /* Methods inherited from SubcaseBase */
Setup()7319     virtual long Setup()
7320     {
7321         /* Shaders code */
7322         const char *const vertex_shader_code = "#version 400 core\n"
7323                                                "#extension GL_ARB_shader_image_load_store : require\n"
7324                                                "\n"
7325                                                "precision highp float;\n"
7326                                                "\n"
7327                                                "in vec4 vs_in_position;\n"
7328                                                "\n"
7329                                                "void main()\n"
7330                                                "{\n"
7331                                                "    gl_Position = vs_in_position;\n"
7332                                                "}\n";
7333 
7334         const char *const fragment_shader_code =
7335             "#version 400 core\n"
7336             "#extension GL_ARB_shader_image_load_store : require\n"
7337             "\n"
7338             "precision highp float;\n"
7339             "\n"
7340             "layout(rgba8) writeonly uniform image2D u_destination_image;\n"
7341             "layout(rgba8) readonly  uniform image2D u_source_image;\n"
7342             "\n"
7343             "void main()\n"
7344             "{\n"
7345             "    vec4 loaded_color = imageLoad (u_source_image,      ivec2(gl_FragCoord));\n"
7346             "                        imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
7347             "\n"
7348             "    discard;\n"
7349             "}\n";
7350 
7351         /* Vertex postions for "full screen" quad, defined as a triangle strip */
7352         static const GLfloat m_vertex_buffer_data[] = {
7353             -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7354             -1.0f, 1.0f,  0.0f, 1.0f, /* left top */
7355             1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
7356             1.0f,  1.0f,  0.0f, 1.0f, /* right top */
7357         };
7358 
7359         /* Result of BuildProgram operation */
7360         bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7361 
7362         /* Add all tested texture shapes */
7363         int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7364         m_texture_shape_definitions.push_back(
7365             TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY));
7366         m_texture_shape_definitions.push_back(
7367             TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D));
7368         m_texture_shape_definitions.push_back(
7369             TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP));
7370         m_texture_shape_definitions.push_back(
7371             TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY));
7372 
7373         /* Prepare buffer with vertex positions of "full screen" quad" */
7374         glGenBuffers(1, &m_vertex_buffer_id);
7375         GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7376 
7377         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7378         GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7379 
7380         glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7381         GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7382 
7383         /* Generate vertex array object */
7384         glGenVertexArrays(1, &m_vertex_array_object_id);
7385         GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7386 
7387         /* Prepare program object */
7388         m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */,
7389                                     fragment_shader_code, &is_program_correct);
7390         if (false == is_program_correct)
7391         {
7392             return ERROR;
7393         }
7394 
7395         /* Done */
7396         return NO_ERROR;
7397     }
7398 
Cleanup()7399     virtual long Cleanup()
7400     {
7401         /* Reset OpenGL state */
7402         glBindBuffer(GL_ARRAY_BUFFER, 0);
7403         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
7404         glBindTexture(GL_TEXTURE_3D, 0);
7405         glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
7406         glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
7407         glBindVertexArray(0);
7408         glUseProgram(0);
7409 
7410         /* Delete program */
7411         if (0 != m_program_id)
7412         {
7413             glDeleteProgram(m_program_id);
7414             m_program_id = 0;
7415         }
7416 
7417         /* Delete textures */
7418         if (0 != m_destination_texture_id)
7419         {
7420             glDeleteTextures(1, &m_destination_texture_id);
7421             m_destination_texture_id = 0;
7422         }
7423 
7424         if (0 != m_source_texture_id)
7425         {
7426             glDeleteTextures(1, &m_source_texture_id);
7427             m_source_texture_id = 0;
7428         }
7429 
7430         /* Delete vertex array object */
7431         if (0 != m_vertex_array_object_id)
7432         {
7433             glDeleteVertexArrays(1, &m_vertex_array_object_id);
7434             m_vertex_array_object_id = 0;
7435         }
7436 
7437         /* Delete buffer */
7438         if (0 != m_vertex_buffer_id)
7439         {
7440             glDeleteBuffers(1, &m_vertex_buffer_id);
7441             m_vertex_buffer_id = 0;
7442         }
7443 
7444         /* Done */
7445         return NO_ERROR;
7446     }
7447 
Run()7448     virtual long Run()
7449     {
7450         bool result = true;
7451 
7452         /* For each shape */
7453         for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin();
7454              m_texture_shape_definitions.end() != it; ++it)
7455         {
7456             const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type);
7457 
7458             /* Prepare "source" and "destination" textures */
7459             GLU_EXPECT_NO_ERROR(
7460                 CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id),
7461                 "Create2DR8UIDestinationTexture");
7462             GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id),
7463                                 "Create2DR8UISourceTexture");
7464 
7465             /* Copy texture data with imageLoad() and imageStore() operations */
7466             CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers);
7467 
7468             /* Compare "source" and "destination" textures */
7469             if (false ==
7470                 CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type))
7471             {
7472                 const char *texture_type = "";
7473                 switch (it->m_type)
7474                 {
7475                 case GL_TEXTURE_2D_ARRAY:
7476                     texture_type = "2d array";
7477                     break;
7478                 case GL_TEXTURE_3D:
7479                     texture_type = "3d";
7480                     break;
7481                 case GL_TEXTURE_CUBE_MAP:
7482                     texture_type = "Cube map";
7483                     break;
7484                 case GL_TEXTURE_CUBE_MAP_ARRAY:
7485                     texture_type = "Cube map array";
7486                     break;
7487                 }
7488 
7489                 m_context.getTestContext().getLog()
7490                     << tcu::TestLog::Message
7491                     << "Copy  with imageLoad and imageStore failed for texture type: " << texture_type
7492                     << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
7493 
7494                 result = false;
7495             }
7496 
7497             /* Destroy "source" and "destination" textures */
7498             glDeleteTextures(1, &m_destination_texture_id);
7499             glDeleteTextures(1, &m_source_texture_id);
7500 
7501             m_destination_texture_id = 0;
7502             m_source_texture_id      = 0;
7503         }
7504 
7505         if (false == result)
7506         {
7507             return ERROR;
7508         }
7509 
7510         /* Done */
7511         return NO_ERROR;
7512     }
7513 
7514 private:
7515     /* Private methods */
7516 
7517     /** Binds a texture to user-specified image unit and update relevant sampler uniform
7518      *
7519      * @param program_id   Program object id
7520      * @param texture_id   Texture id
7521      * @param image_unit   Index of image unit
7522      * @param layer        Index of layer bound to unit
7523      * @param uniform_name Name of image uniform
7524      **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLuint image_unit,GLuint layer,const char * uniform_name)7525     void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer,
7526                             const char *uniform_name)
7527     {
7528         static const GLint invalid_uniform_location = -1;
7529         GLint image_uniform_location                = 0;
7530 
7531         /* Get uniform location */
7532         image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7533         GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7534         if (invalid_uniform_location == image_uniform_location)
7535         {
7536             throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
7537         }
7538 
7539         /* Bind texture to image unit */
7540         glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE,
7541                            GL_RGBA8);
7542         GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7543 
7544         /* Set uniform to image unit */
7545         glUniform1i(image_uniform_location, image_unit);
7546         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7547     }
7548 
7549     /** Compare two 2D R8UI textures
7550      *
7551      * @param left_texture_id  Id of "left" texture object
7552      * @param right_texture_id Id of "right" texture object
7553      * @param edge             Length of texture edge
7554      * @param n_layers         Number of layers to compare
7555      * @param type             Type of texture
7556      *
7557      * @return true when texture data is found identical, false otherwise
7558      **/
CompareRGBA8Textures(GLuint left_texture_id,GLuint right_texture_id,GLuint edge,GLuint n_layers,GLenum type)7559     bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers,
7560                               GLenum type)
7561     {
7562         static const GLuint n_components = 4; /* RGBA */
7563         const GLuint texture_data_size   = edge * edge * n_layers * n_components;
7564 
7565         /* Storage for texture data */
7566         std::vector<GLubyte> left_texture_data;
7567         std::vector<GLubyte> right_texture_data;
7568 
7569         ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data);
7570         ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data);
7571 
7572         /* Compare texels */
7573         return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7574     }
7575 
7576     /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7577      *
7578      * @param destination_texture_id Id of "destination" texture object
7579      * @param source_texture_id      Id of "source" texture object
7580      * @param n_layers               Number of layers
7581      **/
CopyRGBA8Texture(GLuint destination_texture_id,GLuint source_texture_id,GLuint n_layers)7582     void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers)
7583     {
7584         for (GLuint layer = 0; layer < n_layers; ++layer)
7585         {
7586             CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer);
7587         }
7588     }
7589 
7590     /** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations
7591      *
7592      * @param destination_texture_id Id of "destination" texture object
7593      * @param source_texture_id      Id of "source" texture object
7594      * @param layer                  Index of layer
7595      **/
CopyRGBA8TextureLayer(GLuint destination_texture_id,GLuint source_texture_id,GLuint layer)7596     void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer)
7597     {
7598         /* Uniform names */
7599         static const char *const destination_image_uniform_name = "u_destination_image";
7600         static const char *const source_image_uniform_name      = "u_source_image";
7601 
7602         /* Attribute name */
7603         static const char *const position_attribute_name = "vs_in_position";
7604 
7605         /* Attribute location and invalid value */
7606         static const GLint invalid_attribute_location = -1;
7607         GLint position_attribute_location             = 0;
7608 
7609         /* Set current program */
7610         glUseProgram(m_program_id);
7611         GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7612 
7613         /* Bind vertex array object */
7614         glBindVertexArray(m_vertex_array_object_id);
7615         GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7616 
7617         /* Bind buffer with quad vertex positions */
7618         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7619         GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7620 
7621         /* Set up vertex attribute array for position attribute */
7622         position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7623         GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7624         if (invalid_attribute_location == position_attribute_location)
7625         {
7626             throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7627                                      __LINE__);
7628         }
7629 
7630         glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7631                               0 /* stride */, 0 /* pointer */);
7632         GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7633 
7634         glEnableVertexAttribArray(position_attribute_location);
7635         GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7636 
7637         /* Set up textures as source and destination image samplers */
7638         BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer,
7639                            destination_image_uniform_name);
7640         BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name);
7641 
7642         /* Execute draw */
7643         glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7644         GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7645     }
7646 
7647     /** Creates RGBA8 texture of given type and fills it with zeros
7648      *
7649      * @param edge           Edge of created texture
7650      * @param n_elements     Number of elements in texture array
7651      * @param target         Target of created texture
7652      * @param out_texture_id Id of created texture, not modified if operation fails
7653      *
7654      * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7655      **/
CreateRGBA8DestinationTexture(GLuint edge,GLuint n_elements,GLenum target,GLuint & out_texture_id)7656     GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint &out_texture_id)
7657     {
7658         /* Constasts to calculate texture size */
7659         static const GLuint n_components = 4; /* RGBA */
7660         const GLuint layer_size          = edge * edge * n_components;
7661         const GLuint n_layers            = GetTotalNumberOfLayers(n_elements, target);
7662         const GLuint texture_size        = layer_size * n_layers;
7663 
7664         /* Prepare storage for texture data */
7665         std::vector<GLubyte> texture_data;
7666         texture_data.resize(texture_size);
7667 
7668         /* Set all texels */
7669         for (GLuint i = 0; i < texture_size; ++i)
7670         {
7671             texture_data[i] = 0;
7672         }
7673 
7674         /* Create texture */
7675         return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7676     }
7677 
7678     /** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa]
7679      *
7680      * @param edge           Edge of created texture
7681      * @param n_elements     Number of elements in texture array
7682      * @param target         Target of created texture
7683      * @param out_texture_id Id of created texture, not modified if operation fails
7684      *
7685      * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7686      **/
CreateRGBA8SourceTexture(GLuint edge,GLuint n_elements,GLenum target,GLuint & out_texture_id)7687     GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint &out_texture_id)
7688     {
7689         /* Constants to calculate texture size */
7690         static const GLuint n_components = 4; /* RGBA */
7691         const GLuint layer_size          = edge * edge * n_components;
7692         const GLuint n_layers            = GetTotalNumberOfLayers(n_elements, target);
7693         const GLuint texture_size        = layer_size * n_layers;
7694 
7695         /* Value of texel */
7696         GLubyte texel[4] = {0, 0, 0, 0xaa};
7697 
7698         /* Prepare storage for texture data */
7699         std::vector<GLubyte> texture_data;
7700         texture_data.resize(texture_size);
7701 
7702         /* Set all texels */
7703         for (GLuint layer = 0; layer < n_layers; ++layer)
7704         {
7705             const GLuint layer_offset = layer_size * layer;
7706 
7707             texel[2] = static_cast<GLubyte>(layer);
7708 
7709             for (GLuint y = 0; y < edge; ++y)
7710             {
7711                 const GLuint line_offset = y * edge * n_components + layer_offset;
7712 
7713                 texel[1] = static_cast<GLubyte>(y);
7714 
7715                 for (GLuint x = 0; x < edge; ++x)
7716                 {
7717                     const GLuint texel_offset = x * n_components + line_offset;
7718                     texel[0]                  = static_cast<GLubyte>(x);
7719 
7720                     for (GLuint component = 0; component < n_components; ++component)
7721                     {
7722                         texture_data[texel_offset + component] = texel[component];
7723                     }
7724                 }
7725             }
7726         }
7727 
7728         /* Create texture */
7729         return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7730     }
7731 
7732     /** Creates RGBA8 texture of given type and fills it provided data
7733      *
7734      * @param edge           Edge of created texture
7735      * @param n_elements     Number of elements in texture array
7736      * @param target         Target of created texture
7737      * @param texture_data   Texture data
7738      * @param out_texture_id Id of created texture, not modified if operation fails
7739      *
7740      * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7741      **/
CreateRGBA8Texture(GLuint edge,GLenum target,GLuint n_layers,const std::vector<GLubyte> & texture_data,GLuint & out_texture_id)7742     GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte> &texture_data,
7743                               GLuint &out_texture_id)
7744     {
7745         GLenum err        = 0;
7746         GLuint texture_id = 0;
7747 
7748         /* Generate texture */
7749         glGenTextures(1, &texture_id);
7750         err = glGetError();
7751         if (GL_NO_ERROR != err)
7752         {
7753             return err;
7754         }
7755 
7756         /* Bind texture */
7757         glBindTexture(target, texture_id);
7758         err = glGetError();
7759         if (GL_NO_ERROR != err)
7760         {
7761             glDeleteTextures(1, &texture_id);
7762             return err;
7763         }
7764 
7765         /* Allocate storage and fill texture */
7766         if (GL_TEXTURE_CUBE_MAP != target)
7767         {
7768             glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA,
7769                          GL_UNSIGNED_BYTE, &texture_data[0]);
7770         }
7771         else
7772         {
7773             const GLuint n_components = 4;
7774             const GLuint layer_size   = edge * edge * n_components;
7775 
7776             glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7777                          GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7778             glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7779                          GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7780             glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7781                          GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7782             glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7783                          GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7784             glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7785                          GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7786             glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7787                          GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7788         }
7789         err = glGetError();
7790         if (GL_NO_ERROR != err)
7791         {
7792             glDeleteTextures(1, &texture_id);
7793             return err;
7794         }
7795 
7796         /* Make texture complete */
7797         glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
7798         glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
7799         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7800         err = glGetError();
7801         if (GL_NO_ERROR != err)
7802         {
7803             glDeleteTextures(1, &texture_id);
7804             return err;
7805         }
7806 
7807         /* Set out_texture_id */
7808         out_texture_id = texture_id;
7809 
7810         /* Done */
7811         return GL_NO_ERROR;
7812     }
7813 
7814     /** Extracts texture data
7815      *
7816      * @param texture_id   Id of texture object
7817      * @param edge         Length of texture edge
7818      * @param n_layers     Number of layers
7819      * @param target       Target of texture
7820      * @param texture_data Extracted texture data
7821      **/
ExtractTextureData(GLuint texture_id,GLuint edge,GLuint n_layers,GLenum target,std::vector<GLubyte> & texture_data)7822     void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target,
7823                             std::vector<GLubyte> &texture_data)
7824     {
7825         static const GLuint n_components = 4; /* RGBA */
7826         const GLuint texture_data_size   = edge * edge * n_layers * n_components;
7827 
7828         /* Alocate memory for texture data */
7829         texture_data.resize(texture_data_size);
7830 
7831         /* Bind texture */
7832         glBindTexture(target, texture_id);
7833         GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7834 
7835         /* Get data */
7836         if (GL_TEXTURE_CUBE_MAP != target)
7837         {
7838             glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
7839         }
7840         else
7841         {
7842             const GLuint layer_size = edge * edge * n_components;
7843 
7844             glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7845             glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7846             glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7847             glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7848             glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7849             glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7850         }
7851 
7852         GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7853     }
7854 
7855     /** Get number of layers per single element for given type of texture
7856      *
7857      * @param target Target of texture
7858      *
7859      * @return Number of layers
7860      **/
GetLayersPerElement(GLenum target)7861     GLuint GetLayersPerElement(GLenum target)
7862     {
7863         switch (target)
7864         {
7865         case GL_TEXTURE_2D_ARRAY:
7866         case GL_TEXTURE_3D:
7867             return 1;
7868         case GL_TEXTURE_CUBE_MAP:
7869         case GL_TEXTURE_CUBE_MAP_ARRAY:
7870             return 6;
7871         default:
7872             throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__);
7873         }
7874     }
7875 
7876     /** Get total number of layers in texture of given type and number of array elements
7877      *
7878      * @param n_elements Number of elements in texture array
7879      * @param target     Target of texture
7880      *
7881      * @return Number of layers
7882      **/
GetTotalNumberOfLayers(GLuint n_elements,GLenum target)7883     GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target)
7884     {
7885         return GetLayersPerElement(target) * n_elements;
7886     }
7887 };
7888 
7889 /** Test "imageLoad() and imageStore() for incomplete textures" description follows.
7890  *
7891  *  Load from incomplete textures should return 0.
7892  *  Store to incomplete textures should be ignored.
7893  *
7894  *  Steps:
7895  *  - create two incomplete textures: "incomplete_source" and
7896  *  "incomplete_destination",
7897  *  - create two complete textures: "complete_source" and
7898  *  "complete_destination",
7899  *  - fill all textures with unique values,
7900  *  - prepare program that will:
7901  *      * load texel from "incomplete_source" and store its value to
7902  *      "complete_destination",
7903  *      * load texel from "complete_source" and store its value to
7904  *      "incomplete_destination".
7905  *  - bind textures to corresponding image uniforms
7906  *  - execute program for all texels,
7907  *  - verify that "incomplete_destination" was not modified and
7908  *  "complete_destination" is filled with zeros.
7909  *
7910  *  Texture is considered incomplete when it has enabled mipmaping (see below)
7911  *  and does not have all mipmap levels defined.  But for the case of Image
7912  *  accessing, it is considered invalid if it is mipmap-incomplete and the
7913  *  level is different to the base level (base-incomplete).
7914  *
7915  *  Creation of incomplete texture:
7916  *  - generate and bind texture object id,
7917  *  - call TexImage2D with <level>: 0,
7918  *  - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make
7919  *  sure, it should be initial value),
7920  *  - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7921  *  - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width,
7922  *  height)).
7923  *
7924  *  Creation of complete texture:
7925  *  - generate and bind texture object id,
7926  *  - call TexImage2D with <level>: 0,
7927  *  - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7928  *  - set GL_TEXTURE_MAX_LEVEL parameter to 0.
7929  *
7930  *  Binding:
7931  *  - Set level == base_level for complete destinations.
7932  *  - Set level != base_level for incomplete destinations that are using
7933  *    mipmap-incomplete textures.
7934  *
7935  *  Test with 2D 64x64 RGBA8 textures.
7936  *
7937  *  Program should consist of vertex and fragment shader. Vertex shader should
7938  *  pass vertex position through. Fragment shader should do imageLoad() and
7939  *  imageStore() operations at coordinates gl_FragCoord.
7940  **/
7941 class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase
7942 {
7943 private:
7944     /* Constants */
7945     /* Magic numbers that will identify textures, which will be used as their
7946      * texel value.
7947      */
7948     static const GLubyte m_complete_destination_magic_number   = 0x11;
7949     static const GLubyte m_complete_source_magic_number        = 0x22;
7950     static const GLubyte m_incomplete_destination_magic_number = 0x33;
7951     static const GLubyte m_incomplete_source_magic_number      = 0x44;
7952 
7953     /* Texture edge */
7954     GLuint m_texture_edge;
7955 
7956     /* Fields */
7957     GLuint m_complete_destination_texture_id;
7958     GLuint m_complete_source_texture_id;
7959     GLuint m_incomplete_destination_texture_id;
7960     GLuint m_incomplete_source_texture_id;
7961     GLuint m_program_id;
7962     GLuint m_vertex_array_object_id;
7963     GLuint m_vertex_buffer_id;
7964 
7965 public:
7966     /* Constructor */
ImageLoadStoreIncompleteTexturesTest()7967     ImageLoadStoreIncompleteTexturesTest()
7968         : m_texture_edge(0)
7969         , m_complete_destination_texture_id(0)
7970         , m_complete_source_texture_id(0)
7971         , m_incomplete_destination_texture_id(0)
7972         , m_incomplete_source_texture_id(0)
7973         , m_program_id(0)
7974         , m_vertex_array_object_id(0)
7975         , m_vertex_buffer_id(0)
7976     {
7977         /* Nothing to be done here */
7978     }
7979 
7980     /* Methods inherited from SubcaseBase */
Setup()7981     virtual long Setup()
7982     {
7983         /* Shaders code */
7984         const char *const vertex_shader_code = "#version 400 core\n"
7985                                                "#extension GL_ARB_shader_image_load_store : require\n"
7986                                                "\n"
7987                                                "precision highp float;\n"
7988                                                "\n"
7989                                                "in vec4 vs_in_position;\n"
7990                                                "\n"
7991                                                "void main()\n"
7992                                                "{\n"
7993                                                "    gl_Position = vs_in_position;\n"
7994                                                "}\n";
7995 
7996         const char *const fragment_shader_code =
7997             "#version 400 core\n"
7998             "#extension GL_ARB_shader_image_load_store : require\n"
7999             "\n"
8000             "precision highp float;\n"
8001             "\n"
8002             "layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n"
8003             "layout(rgba8) readonly  uniform image2D u_complete_source_image;\n"
8004             "layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n"
8005             "layout(rgba8) readonly  uniform image2D u_incomplete_source_image;\n"
8006             "\n"
8007             "void main()\n"
8008             "{\n"
8009             "    vec4 complete_loaded_color   = imageLoad (u_complete_source_image,   ivec2(gl_FragCoord));\n"
8010             "    vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n"
8011 
8012             "    imageStore(u_complete_destination_image,\n"
8013             "               ivec2(gl_FragCoord),\n"
8014             "               incomplete_loaded_color);\n"
8015             "    imageStore(u_incomplete_destination_image,\n"
8016             "               ivec2(gl_FragCoord),\n"
8017             "               complete_loaded_color);\n"
8018             "\n"
8019             "    discard;\n"
8020             "}\n";
8021 
8022         /* Vertex postions for "full screen" quad, made with triangle strip */
8023         static const GLfloat m_vertex_buffer_data[] = {
8024             -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
8025             -1.0f, 1.0f,  0.0f, 1.0f, /* left top */
8026             1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
8027             1.0f,  1.0f,  0.0f, 1.0f, /* right top */
8028         };
8029 
8030         /* Result of BuildProgram operation */
8031         bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
8032 
8033         /* Clean previous error */
8034         glGetError();
8035 
8036         m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
8037 
8038         /* Prepare textures */
8039         GLU_EXPECT_NO_ERROR(
8040             Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id),
8041             "Create2DRGBA8CompleteTexture");
8042         GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id),
8043                             "Create2DRGBA8CompleteTexture");
8044         GLU_EXPECT_NO_ERROR(
8045             Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id),
8046             "Create2DRGBA8IncompleteTexture");
8047         GLU_EXPECT_NO_ERROR(
8048             Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id),
8049             "Create2DRGBA8IncompleteTexture");
8050 
8051         /* Prepare buffer with vertex positions of "full screen" quad" */
8052         glGenBuffers(1, &m_vertex_buffer_id);
8053         GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
8054 
8055         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8056         GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8057 
8058         glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
8059         GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
8060 
8061         /* Generate vertex array object */
8062         glGenVertexArrays(1, &m_vertex_array_object_id);
8063         GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8064 
8065         /* Prepare program object */
8066         m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
8067                                     fragment_shader_code, &is_program_correct);
8068 
8069         if (false == is_program_correct)
8070         {
8071             return ERROR;
8072         }
8073 
8074         /* Done */
8075         return NO_ERROR;
8076     }
8077 
Cleanup()8078     virtual long Cleanup()
8079     {
8080         /* Reset OpenGL state */
8081         glBindBuffer(GL_ARRAY_BUFFER, 0);
8082         glBindTexture(GL_TEXTURE_2D, 0);
8083         glBindVertexArray(0);
8084         glUseProgram(0);
8085 
8086         /* Delete program */
8087         if (0 != m_program_id)
8088         {
8089             glDeleteProgram(m_program_id);
8090             m_program_id = 0;
8091         }
8092 
8093         /* Delete textures */
8094         if (0 != m_complete_destination_texture_id)
8095         {
8096             glDeleteTextures(1, &m_complete_destination_texture_id);
8097             m_complete_destination_texture_id = 0;
8098         }
8099 
8100         if (0 != m_complete_source_texture_id)
8101         {
8102             glDeleteTextures(1, &m_complete_source_texture_id);
8103             m_complete_source_texture_id = 0;
8104         }
8105 
8106         if (0 != m_incomplete_destination_texture_id)
8107         {
8108             glDeleteTextures(1, &m_incomplete_destination_texture_id);
8109             m_incomplete_destination_texture_id = 0;
8110         }
8111 
8112         if (0 != m_incomplete_source_texture_id)
8113         {
8114             glDeleteTextures(1, &m_incomplete_source_texture_id);
8115             m_incomplete_source_texture_id = 0;
8116         }
8117 
8118         /* Delete vertex array object */
8119         if (0 != m_vertex_array_object_id)
8120         {
8121             glDeleteVertexArrays(1, &m_vertex_array_object_id);
8122             m_vertex_array_object_id = 0;
8123         }
8124 
8125         /* Delete buffer */
8126         if (0 != m_vertex_buffer_id)
8127         {
8128             glDeleteBuffers(1, &m_vertex_buffer_id);
8129             m_vertex_buffer_id = 0;
8130         }
8131 
8132         /* Done */
8133         return NO_ERROR;
8134     }
8135 
Run()8136     virtual long Run()
8137     {
8138         bool result = true;
8139 
8140         /* Copy textures data with imageLoad() and imageStore() operations */
8141         Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id,
8142                             m_complete_source_texture_id, m_incomplete_source_texture_id);
8143 
8144         glMemoryBarrier(GL_ALL_BARRIER_BITS);
8145 
8146         /* Verify that store to "incomplete destination" was ignored */
8147         if (true ==
8148             CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number))
8149         {
8150             m_context.getTestContext().getLog()
8151                 << tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture"
8152                 << tcu::TestLog::EndMessage;
8153 
8154             result = false;
8155         }
8156 
8157         /* Verify that load from "incomplete source" returned 0 */
8158         if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id))
8159         {
8160             m_context.getTestContext().getLog()
8161                 << tcu::TestLog::Message
8162                 << "Problem with imageLoad, operation returned non 0 result for incomplete texture"
8163                 << tcu::TestLog::EndMessage;
8164 
8165             result = false;
8166         }
8167 
8168         if (false == result)
8169         {
8170             return ERROR;
8171         }
8172 
8173         /* Done */
8174         return NO_ERROR;
8175     }
8176 
8177 private:
8178     /* Private methods */
8179 
8180     /** Bind texture to image unit and sets image uniform to that unit
8181      *
8182      * @param program_id   Program object id
8183      * @param texture_id   Texture id
8184      * @param level        Texture level
8185      * @param image_unit   Index of image unit
8186      * @param uniform_name Name of image uniform
8187      **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLint level,GLuint image_unit,const char * uniform_name)8188     void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit,
8189                             const char *uniform_name)
8190     {
8191         /* Uniform location and invalid value */
8192         static const GLint invalid_uniform_location = -1;
8193         GLint image_uniform_location                = 0;
8194 
8195         /* Get uniform location */
8196         image_uniform_location = glGetUniformLocation(program_id, uniform_name);
8197         GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
8198         if (invalid_uniform_location == image_uniform_location)
8199         {
8200             throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
8201         }
8202 
8203         /* Bind texture to image unit */
8204         glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8);
8205         GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
8206 
8207         /* Set uniform to image unit */
8208         glUniform1i(image_uniform_location, image_unit);
8209         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
8210     }
8211 
8212     /** Check if texture is filled with black color, zeros
8213      *
8214      * @param texture_id Id of texture object
8215      *
8216      * @return true when texture is fully black, false otherwise
8217      **/
CheckIfTextureIsBlack(GLuint texture_id)8218     bool CheckIfTextureIsBlack(GLuint texture_id)
8219     {
8220         /* Constants to calculate size of texture */
8221         static const GLuint n_components = 4; /* RGBA */
8222         const GLuint texture_data_size   = m_texture_edge * m_texture_edge * n_components;
8223 
8224         /* Storage for texture data */
8225         std::vector<GLubyte> black_texture_data;
8226         std::vector<GLubyte> texture_data;
8227 
8228         /* Allocate memory */
8229         black_texture_data.resize(texture_data_size);
8230         texture_data.resize(texture_data_size);
8231 
8232         /* Set all texels to black */
8233         for (GLuint i = 0; i < texture_data_size; ++i)
8234         {
8235             black_texture_data[i] = 0;
8236         }
8237 
8238         /* Bind texture */
8239         glBindTexture(GL_TEXTURE_2D, texture_id);
8240         GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8241 
8242         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8243         GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8244 
8245         /* Compare texels */
8246         return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size));
8247     }
8248 
8249     /** Check if texture was modified
8250      *
8251      * @param texture_id   Id of texture object
8252      * @param nagic_number Magic number that was to create texture
8253      *
8254      * @return true if texture contents match expected values, false otherwise
8255      **/
CheckIfTextureWasModified(GLuint texture_id,GLubyte magic_number)8256     bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number)
8257     {
8258         /* Constants to calculate size of texture */
8259         static const GLuint n_components = 4; /* RGBA */
8260         const GLuint texture_data_size   = m_texture_edge * m_texture_edge * n_components;
8261 
8262         /* Storage for texture data */
8263         std::vector<GLubyte> expected_texture_data;
8264         std::vector<GLubyte> texture_data;
8265 
8266         /* Allocate memory */
8267         expected_texture_data.resize(texture_data_size);
8268         texture_data.resize(texture_data_size);
8269 
8270         /* Prepare expected texels */
8271         for (GLuint y = 0; y < m_texture_edge; ++y)
8272         {
8273             const GLuint line_offset = y * m_texture_edge * n_components;
8274 
8275             for (GLuint x = 0; x < m_texture_edge; ++x)
8276             {
8277                 const GLuint texel_offset = x * n_components + line_offset;
8278 
8279                 SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y),
8280                          magic_number);
8281             }
8282         }
8283 
8284         /* Bind texture */
8285         glBindTexture(GL_TEXTURE_2D, texture_id);
8286         GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8287 
8288         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8289         GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8290 
8291         /* Compare texels, true when textures are different */
8292         return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size));
8293     }
8294 
8295     /** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations
8296      *
8297      * @param complete_destination_texture_id   Id of "complete destination" texture object
8298      * @param incomplete_destination_texture_id Id of "incomplete destination" texture object
8299      * @param complete_source_texture_id        Id of "complete source" texture object
8300      * @param incomplete_source_texture_id      Id of "incomplete source" texture object
8301      **/
Copy2DRGBA8Textures(GLuint complete_destination_texture_id,GLuint incomplete_destination_texture_id,GLuint complete_source_texture_id,GLuint incomplete_source_texture_id)8302     void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id,
8303                              GLuint complete_source_texture_id, GLuint incomplete_source_texture_id)
8304     {
8305         /* Uniform names */
8306         static const char *const complete_destination_image_uniform_name   = "u_complete_destination_image";
8307         static const char *const complete_source_image_uniform_name        = "u_complete_source_image";
8308         static const char *const incomplete_destination_image_uniform_name = "u_incomplete_destination_image";
8309         static const char *const incomplete_source_image_uniform_name      = "u_incomplete_source_image";
8310 
8311         /* Attribute name */
8312         static const char *const position_attribute_name = "vs_in_position";
8313 
8314         /* Attribute location and invalid value */
8315         static const GLint invalid_attribute_location = -1;
8316         GLint position_attribute_location             = 0;
8317 
8318         /* Set current program */
8319         glUseProgram(m_program_id);
8320         GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
8321 
8322         /* Bind vertex array object */
8323         glBindVertexArray(m_vertex_array_object_id);
8324         GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8325 
8326         /* Bind buffer with quad vertex positions */
8327         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8328         GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8329 
8330         /* Setup position attribute */
8331         position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
8332         GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
8333         if (invalid_attribute_location == position_attribute_location)
8334         {
8335             throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
8336                                      __LINE__);
8337         }
8338 
8339         glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0);
8340         GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
8341 
8342         glEnableVertexAttribArray(position_attribute_location);
8343         GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
8344 
8345         /* Setup textures as source and destination images */
8346         BindTextureToImage(m_program_id, complete_destination_texture_id, 0 /* texture level */, 0 /* image_unit */,
8347                            complete_destination_image_uniform_name);
8348         BindTextureToImage(m_program_id, complete_source_texture_id, 0 /* texture level */, 1 /* image_unit */,
8349                            complete_source_image_uniform_name);
8350         BindTextureToImage(m_program_id, incomplete_destination_texture_id, 2 /* texture level */, 2 /* image_unit */,
8351                            incomplete_destination_image_uniform_name);
8352         BindTextureToImage(m_program_id, incomplete_source_texture_id, 2 /* texture level */, 3 /* image_unit */,
8353                            incomplete_source_image_uniform_name);
8354 
8355         /* Execute draw */
8356         glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
8357         GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
8358     }
8359 
8360     /** Create complete 2D RGBA8 texture.
8361      *
8362      * @param magic_number   Magic number of texture
8363      * @param out_texture_id Id of created texture, not modified if operation fails
8364      *
8365      * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8366      **/
Create2DRGBA8CompleteTexture(GLubyte magic_number,GLuint & out_texture_id)8367     GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint &out_texture_id)
8368     {
8369         /* Constants to calculate size of texture */
8370         static const GLuint n_components = 4; /* RGBA */
8371         const GLuint texture_data_size   = m_texture_edge * m_texture_edge * n_components;
8372 
8373         /* Error code */
8374         GLenum err = 0;
8375 
8376         /* Texture id */
8377         GLuint texture_id = 0;
8378 
8379         /* Prepare storage for texture data */
8380         std::vector<GLubyte> texture_data;
8381         texture_data.resize(texture_data_size);
8382 
8383         /* Prepare texture data */
8384         for (GLuint y = 0; y < m_texture_edge; ++y)
8385         {
8386             const GLuint line_offset = y * m_texture_edge * n_components;
8387 
8388             for (GLuint x = 0; x < m_texture_edge; ++x)
8389             {
8390                 const GLuint texel_offset = x * n_components + line_offset;
8391 
8392                 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8393             }
8394         }
8395 
8396         /* Generate texture */
8397         glGenTextures(1, &texture_id);
8398         err = glGetError();
8399         if (GL_NO_ERROR != err)
8400         {
8401             return err;
8402         }
8403 
8404         /* Bind texture */
8405         glBindTexture(GL_TEXTURE_2D, texture_id);
8406         err = glGetError();
8407         if (GL_NO_ERROR != err)
8408         {
8409             glDeleteTextures(1, &texture_id);
8410             return err;
8411         }
8412 
8413         /* Allocate storage and fill texture */
8414         glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8415                      GL_UNSIGNED_BYTE, &texture_data[0]);
8416         err = glGetError();
8417         if (GL_NO_ERROR != err)
8418         {
8419             glDeleteTextures(1, &texture_id);
8420             return err;
8421         }
8422 
8423         /* Make texture complete */
8424         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8425         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8426         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8427         err = glGetError();
8428         if (GL_NO_ERROR != err)
8429         {
8430             glDeleteTextures(1, &texture_id);
8431             return err;
8432         }
8433 
8434         /* Set out_texture_id */
8435         out_texture_id = texture_id;
8436 
8437         /* Done */
8438         return GL_NO_ERROR;
8439     }
8440 
8441     /** Create incomplete 2D RGBA8 texture
8442      *
8443      * @param magic_number   Magic number of texture
8444      * @param out_texture_id Id of created texture, not modified if operation fails
8445      *
8446      * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8447      **/
Create2DRGBA8IncompleteTexture(GLubyte magic_number,GLuint & out_texture_id)8448     GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint &out_texture_id)
8449     {
8450         /* Constants to calculate size of texture */
8451         static const GLuint n_components = 4; /* RGBA */
8452         const GLuint texture_data_size   = m_texture_edge * m_texture_edge * n_components;
8453 
8454         /* Error code */
8455         GLenum err = 0;
8456 
8457         /* Texture id */
8458         GLuint texture_id = 0;
8459 
8460         /* Prepare storage for texture data */
8461         std::vector<GLubyte> texture_data;
8462         texture_data.resize(texture_data_size);
8463 
8464         /* Prepare texture data */
8465         for (GLuint y = 0; y < m_texture_edge; ++y)
8466         {
8467             const GLuint line_offset = y * m_texture_edge * n_components;
8468 
8469             for (GLuint x = 0; x < m_texture_edge; ++x)
8470             {
8471                 const GLuint texel_offset = x * n_components + line_offset;
8472 
8473                 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8474             }
8475         }
8476 
8477         /* Generate texture */
8478         glGenTextures(1, &texture_id);
8479         err = glGetError();
8480         if (GL_NO_ERROR != err)
8481         {
8482             return err;
8483         }
8484 
8485         /* Bind texture */
8486         glBindTexture(GL_TEXTURE_2D, texture_id);
8487         err = glGetError();
8488         if (GL_NO_ERROR != err)
8489         {
8490             glDeleteTextures(1, &texture_id);
8491             return err;
8492         }
8493 
8494         /* Allocate storage and fill texture */
8495         glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8496                      GL_UNSIGNED_BYTE, &texture_data[0]);
8497         err = glGetError();
8498         if (GL_NO_ERROR != err)
8499         {
8500             glDeleteTextures(1, &texture_id);
8501             return err;
8502         }
8503 
8504         /* Make texture incomplete */
8505         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8506         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7);
8507         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
8508         err = glGetError();
8509         if (GL_NO_ERROR != err)
8510         {
8511             glDeleteTextures(1, &texture_id);
8512             return err;
8513         }
8514 
8515         /* Set out_texture_id */
8516         out_texture_id = texture_id;
8517 
8518         /* Done */
8519         return GL_NO_ERROR;
8520     }
8521 
8522     /** Prepare "unique" texels.
8523      *  Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc].
8524      *
8525      * @param texel        Storage of texel
8526      * @param x_coordinate X coordiante of texel
8527      * @param y_coordinate Y coordinate of texel
8528      * @param magic_number Magic number of texture
8529      **/
SetTexel(GLubyte texel[4],GLubyte x_coordinate,GLubyte y_coordinate,GLubyte magic_number)8530     void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number)
8531     {
8532         texel[0] = x_coordinate;
8533         texel[1] = y_coordinate;
8534         texel[2] = magic_number;
8535         texel[3] = 0xcc;
8536     }
8537 };
8538 
8539 /** Test "Refer to the same image unit using multiple uniforms", description follows.
8540  *
8541  * Steps:
8542  * - prepare program object, see details below,
8543  * - prepare 2D R32I texture, width should be equal to the number of image
8544  * uniforms used by program object, height should be 2, fill first row with
8545  * unique values, fill second row with zeros,
8546  * - bind texture to first image unit,
8547  * - set all image uniforms to first image unit,
8548  * - execute program for a single vertex,
8549  * - verify that:
8550  *     - values in first row were negated,
8551  *     - values from first row were copied to second row,
8552  *
8553  * Repeat steps to test all shader stages that support at least 2 image
8554  * uniforms.
8555  *
8556  * Program has to contain all necessary shader stages. Use boilerplate shaders
8557  * for shader stages that are not important for the test.
8558  *
8559  * Tested shader stage should:
8560  * - Use as many different image formats as possible, image formats compatible
8561  * with R32I:
8562  *     * rg16f
8563  *     * r11f_g11f_b10f
8564  *     * r32f
8565  *     * rgb10_a2ui
8566  *     * rgba8ui
8567  *     * rg16ui
8568  *     * r32ui
8569  *     * rgba8i
8570  *     * rg16i
8571  *     * r32i
8572  *     * rgb10_a2
8573  *     * rgba8
8574  *     * rg16
8575  *     * rgba8_snorm
8576  *     * rg16_snorm.
8577  * - Declare maximum allowed number of image uniforms,
8578  *
8579  *     layout(format) uniform gimage2D u_image;
8580  *
8581  * where <format> is selected image format, <gimage2D> is type of 2D image
8582  * compatible with <format> and <u_image> is unique name of uniform.
8583  * Note that image uniforms cannot be declared as array, due to different image
8584  * formats. Therefore separate uniforms have to be used.
8585  * - Include following code snippet:
8586  * for (int i = 0; i < gl_Max*ImageUniforms; ++i)
8587  * {
8588  *     vec row_1_coord(i,0);
8589  *     vec row_2_coord(i,1);
8590  *
8591  *     row_1_value = imageLoad(u_image[i], row_1_coord);
8592  *     imageStore(u_image[i], row_1_coord, -row_1_value);
8593  *     imageStore(u_image[i], row_2_coord, row_1_value);
8594  * }
8595  * where gl_Max*ImageUniforms is the constant corresponding to tested shader
8596  * stage.
8597  **/
8598 class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase
8599 {
8600 private:
8601     /* Types */
8602     /** Details of image format
8603      *
8604      **/
8605     struct imageFormatDetails
8606     {
8607         typedef bool (*verificationRoutine)(GLint, GLint, GLint);
8608 
8609         const char *m_image_format;
8610         const char *m_image_type;
8611         const char *m_color_type;
8612         GLenum m_image_unit_format;
8613         verificationRoutine m_verification_routine;
8614     };
8615 
8616     template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)>
8617     struct Masks
8618     {
8619         /** Get mask of bits used to store in bit-field
8620          *
8621          * @return Mask
8622          **/
RawMaskgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::Masks8623         static inline T RawMask()
8624         {
8625             static const T mask = ValueMask() << OFFSET;
8626 
8627             return mask;
8628         }
8629 
8630         /** Get mask of bits used to store value.
8631          *
8632          * @return Mask
8633          **/
ValueMaskgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::Masks8634         static inline T ValueMask()
8635         {
8636             static const T mask = (1 << SIZE) - 1;
8637 
8638             return mask;
8639         }
8640 
8641         /** Get offset.
8642          *
8643          * @return offset
8644          **/
Offsetgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::Masks8645         static inline T Offset()
8646         {
8647             return OFFSET;
8648         }
8649     };
8650 
8651     template <typename T, GLuint SIZE, GLuint OFFSET>
8652     struct Masks<T, SIZE, OFFSET, false>
8653     {
8654         /** Get mask of bits used to store in bit-field
8655          *
8656          * @return Mask
8657          **/
RawMaskgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::Masks8658         static inline T RawMask()
8659         {
8660             DE_ASSERT(false && "Shouldn't be called");
8661             return 0;
8662         }
8663 
8664         /** Get mask of bits used to store value.
8665          *
8666          * @return Mask
8667          **/
ValueMaskgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::Masks8668         static inline T ValueMask()
8669         {
8670             DE_ASSERT(false && "Shouldn't be called");
8671             return 0;
8672         }
8673 
8674         /** Get offset.
8675          *
8676          * @return offset
8677          **/
Offsetgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::Masks8678         static inline T Offset()
8679         {
8680             DE_ASSERT(false && "Shouldn't be called");
8681             return 0;
8682         }
8683     };
8684 
8685     /** Template class for accessing integer values stored in bit-fields
8686      *
8687      **/
8688     template <typename T, GLuint SIZE, GLuint OFFSET>
8689     class Integer
8690     {
8691     public:
8692         /** Constructor
8693          *
8694          **/
Integer(T raw)8695         Integer(T raw) : m_raw(raw)
8696         {
8697         }
8698 
8699         /** Extract value from bit-field
8700          *
8701          * @return Value
8702          **/
Get() const8703         T Get() const
8704         {
8705             const T mask = Masks<T, SIZE, OFFSET>::RawMask();
8706 
8707             const T bits   = m_raw & mask;
8708             const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset();
8709 
8710             return result;
8711         }
8712 
8713         /** Extract value from bit-field and negate it
8714          *
8715          * @return Negated value
8716          **/
GetNegated() const8717         T GetNegated() const
8718         {
8719             const T mask  = Masks<T, SIZE, OFFSET>::ValueMask();
8720             const T value = Get();
8721 
8722             return Clamp((~value) + 1) & mask;
8723         }
8724 
Clamp(T n) const8725         T Clamp(T n) const
8726         {
8727             const bool isUnsigned = (T(0) < T(-1));
8728             const T min           = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1)));
8729             const T max           = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L);
8730             const T x             = n > max ? max : n;
8731             return x < min ? min : x;
8732         }
8733 
8734     private:
8735         T m_raw;
8736     };
8737 
8738     /* Enums */
8739     /** Shader stage identification
8740      *
8741      **/
8742     enum shaderStage
8743     {
8744         fragmentShaderStage              = 2,
8745         geometryShaderStage              = 4,
8746         tesselationControlShaderStage    = 8,
8747         tesselationEvalutaionShaderStage = 16,
8748         vertexShaderStage                = 32,
8749     };
8750 
8751     /** Test result
8752      *
8753      **/
8754     enum testResult
8755     {
8756         testFailed       = -1,
8757         testNotSupported = 1,
8758         testPassed       = 0
8759     };
8760 
8761     /* Constants */
8762     static const GLint m_min_required_image_uniforms = 2;
8763 
8764     /* Fields */
8765     GLuint m_program_to_test_fs_stage_id;
8766     GLuint m_program_to_test_gs_stage_id;
8767     GLuint m_program_to_test_tcs_stage_id;
8768     GLuint m_program_to_test_tes_stage_id;
8769     GLuint m_program_to_test_vs_stage_id;
8770     GLuint m_texture_to_test_fs_stage_id;
8771     GLuint m_texture_to_test_gs_stage_id;
8772     GLuint m_texture_to_test_tcs_stage_id;
8773     GLuint m_texture_to_test_tes_stage_id;
8774     GLuint m_texture_to_test_vs_stage_id;
8775     GLuint m_vertex_array_object_id;
8776 
8777 public:
8778     /* Constructor */
ImageLoadStoreMultipleUniformsTest()8779     ImageLoadStoreMultipleUniformsTest()
8780         : m_program_to_test_fs_stage_id(0)
8781         , m_program_to_test_gs_stage_id(0)
8782         , m_program_to_test_tcs_stage_id(0)
8783         , m_program_to_test_tes_stage_id(0)
8784         , m_program_to_test_vs_stage_id(0)
8785         , m_texture_to_test_fs_stage_id(0)
8786         , m_texture_to_test_gs_stage_id(0)
8787         , m_texture_to_test_tcs_stage_id(0)
8788         , m_texture_to_test_tes_stage_id(0)
8789         , m_texture_to_test_vs_stage_id(0)
8790         , m_vertex_array_object_id(0)
8791     {
8792         /* Nothing to be done here */
8793     }
8794 
8795     /* Methods inherited from SubcaseBase */
Setup()8796     virtual long Setup()
8797     {
8798         /* Prepare programs */
8799         m_program_to_test_fs_stage_id  = buildProgramToTestShaderStage(fragmentShaderStage);
8800         m_program_to_test_gs_stage_id  = buildProgramToTestShaderStage(geometryShaderStage);
8801         m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage);
8802         m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage);
8803         m_program_to_test_vs_stage_id  = buildProgramToTestShaderStage(vertexShaderStage);
8804 
8805         /* Prepare textures */
8806         m_texture_to_test_fs_stage_id  = createTextureToTestShaderStage(fragmentShaderStage);
8807         m_texture_to_test_gs_stage_id  = createTextureToTestShaderStage(geometryShaderStage);
8808         m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage);
8809         m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage);
8810         m_texture_to_test_vs_stage_id  = createTextureToTestShaderStage(vertexShaderStage);
8811 
8812         /* Generate vertex array object */
8813         glGenVertexArrays(1, &m_vertex_array_object_id);
8814         GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8815 
8816         /* Bind vertex array object */
8817         glBindVertexArray(m_vertex_array_object_id);
8818         GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8819 
8820         /* Set vertices number for patches */
8821         glPatchParameteri(GL_PATCH_VERTICES, 1);
8822 
8823         /* Done */
8824         return NO_ERROR;
8825     }
8826 
Cleanup()8827     virtual long Cleanup()
8828     {
8829         glUseProgram(0);
8830 
8831         /* Delete programs */
8832         if (0 != m_program_to_test_fs_stage_id)
8833         {
8834             glDeleteProgram(m_program_to_test_fs_stage_id);
8835             m_program_to_test_fs_stage_id = 0;
8836         }
8837 
8838         if (0 != m_program_to_test_gs_stage_id)
8839         {
8840             glDeleteProgram(m_program_to_test_gs_stage_id);
8841             m_program_to_test_gs_stage_id = 0;
8842         }
8843 
8844         if (0 != m_program_to_test_tcs_stage_id)
8845         {
8846             glDeleteProgram(m_program_to_test_tcs_stage_id);
8847             m_program_to_test_tcs_stage_id = 0;
8848         }
8849 
8850         if (0 != m_program_to_test_tes_stage_id)
8851         {
8852             glDeleteProgram(m_program_to_test_tes_stage_id);
8853             m_program_to_test_tes_stage_id = 0;
8854         }
8855 
8856         if (0 != m_program_to_test_vs_stage_id)
8857         {
8858             glDeleteProgram(m_program_to_test_vs_stage_id);
8859             m_program_to_test_vs_stage_id = 0;
8860         }
8861 
8862         /* Delete textures */
8863         if (0 != m_texture_to_test_fs_stage_id)
8864         {
8865             glDeleteTextures(1, &m_texture_to_test_fs_stage_id);
8866             m_texture_to_test_fs_stage_id = 0;
8867         }
8868 
8869         if (0 != m_texture_to_test_gs_stage_id)
8870         {
8871             glDeleteTextures(1, &m_texture_to_test_gs_stage_id);
8872             m_texture_to_test_gs_stage_id = 0;
8873         }
8874 
8875         if (0 != m_texture_to_test_tcs_stage_id)
8876         {
8877             glDeleteTextures(1, &m_texture_to_test_tcs_stage_id);
8878             m_texture_to_test_tcs_stage_id = 0;
8879         }
8880 
8881         if (0 != m_texture_to_test_tes_stage_id)
8882         {
8883             glDeleteTextures(1, &m_texture_to_test_tes_stage_id);
8884             m_texture_to_test_tes_stage_id = 0;
8885         }
8886 
8887         if (0 != m_texture_to_test_vs_stage_id)
8888         {
8889             glDeleteTextures(1, &m_texture_to_test_vs_stage_id);
8890             m_texture_to_test_vs_stage_id = 0;
8891         }
8892 
8893         /* Delete vertex array object id */
8894         if (0 != m_vertex_array_object_id)
8895         {
8896             glDeleteVertexArrays(1, &m_vertex_array_object_id);
8897             m_vertex_array_object_id = 0;
8898         }
8899 
8900         /* Done */
8901         return NO_ERROR;
8902     }
8903 
Run()8904     virtual long Run()
8905     {
8906         bool result = true;
8907 
8908         if (testFailed == testShaderStage(fragmentShaderStage))
8909         {
8910             m_context.getTestContext().getLog()
8911                 << tcu::TestLog::Message << "Problems with fragment shader stage!" << tcu::TestLog::EndMessage;
8912 
8913             result = false;
8914         }
8915 
8916         if (testFailed == testShaderStage(geometryShaderStage))
8917         {
8918             m_context.getTestContext().getLog()
8919                 << tcu::TestLog::Message << "Problems with geometry shader stage!" << tcu::TestLog::EndMessage;
8920 
8921             result = false;
8922         }
8923 
8924         if (testFailed == testShaderStage(tesselationControlShaderStage))
8925         {
8926             m_context.getTestContext().getLog()
8927                 << tcu::TestLog::Message << "Problems with tesselation control shader stage!"
8928                 << tcu::TestLog::EndMessage;
8929 
8930             result = false;
8931         }
8932 
8933         if (testFailed == testShaderStage(tesselationEvalutaionShaderStage))
8934         {
8935             m_context.getTestContext().getLog()
8936                 << tcu::TestLog::Message << "Problems with tesselation evaluation shader stage!"
8937                 << tcu::TestLog::EndMessage;
8938 
8939             result = false;
8940         }
8941 
8942         if (testFailed == testShaderStage(vertexShaderStage))
8943         {
8944             m_context.getTestContext().getLog()
8945                 << tcu::TestLog::Message << "Problems with vertex shader stage!" << tcu::TestLog::EndMessage;
8946 
8947             result = false;
8948         }
8949 
8950         if (false == result)
8951         {
8952             return ERROR;
8953         }
8954 
8955         /* Done */
8956         return NO_ERROR;
8957     }
8958 
8959 private:
8960     /* Static routines */
8961     /** Provide image format details for given index
8962      *
8963      * @param index       Index
8964      * @param out_details Image format detail instance
8965      **/
getImageUniformDeclarationDetails(GLuint index,imageFormatDetails & out_details)8966     static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails &out_details)
8967     {
8968         static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = {
8969             "r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger};
8970 
8971         static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = {
8972             {"rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort>},
8973             {"r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F,
8974              ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint>},
8975             {"r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint>},
8976             {"rgb10_a2", "image2D", "vec4", GL_RGB10_A2,
8977              ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint>},
8978             {"rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint>},
8979             {"rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint>},
8980             {"rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM,
8981              ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte>},
8982             {"rg16_snorm", "image2D", "vec4", GL_RG16_SNORM,
8983              ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort>},
8984             {"rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI,
8985              ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint>},
8986             {"rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI,
8987              ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint>},
8988             {"rg16ui", "uimage2D", "uvec4", GL_RG16UI,
8989              ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint>},
8990             {"r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger},
8991             {"rgba8i", "iimage2D", "ivec4", GL_RGBA8I,
8992              ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint>},
8993             {"rg16i", "iimage2D", "ivec4", GL_RG16I,
8994              ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint>}};
8995 
8996         static const GLuint n_imageUniformFormatDetails =
8997             sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails);
8998 
8999         if (n_imageUniformFormatDetails <= index)
9000         {
9001             out_details = default_format_details;
9002         }
9003         else
9004         {
9005             out_details = format_details[index];
9006         }
9007     }
9008 
9009     /** Write name of image uniform at given index to output stream
9010      *
9011      * @param stream Output stream
9012      * @param index  Index
9013      **/
writeImageUniformNameToStream(std::ostream & stream,GLuint index)9014     static void writeImageUniformNameToStream(std::ostream &stream, GLuint index)
9015     {
9016         /* u_image_0 */
9017         stream << "u_image_" << index;
9018     }
9019 
9020     /** Write name of variable used to store value loaded from image at given index to output stream
9021      *
9022      * @param stream Output stream
9023      * @param index  Index
9024      **/
writeLoadedValueVariableNameToStream(std::ostream & stream,GLuint index)9025     static void writeLoadedValueVariableNameToStream(std::ostream &stream, GLuint index)
9026     {
9027         /* loaded_value_0 */
9028         stream << "loaded_value_" << index;
9029     }
9030 
9031     /** Write name of variable used to store coordinate of texel at given row to output stream
9032      *
9033      * @param stream Output stream
9034      * @param index  Index of image uniform
9035      * @param row    Row of image
9036      **/
writeCoordinatesVariableNameToStream(std::ostream & stream,GLuint index,GLuint row)9037     static void writeCoordinatesVariableNameToStream(std::ostream &stream, GLuint index, GLuint row)
9038     {
9039         /* row_0_coordinates_0 */
9040         stream << "row_" << row << "_coordinates_" << index;
9041     }
9042 
9043     struct imageUniformDeclaration
9044     {
imageUniformDeclarationgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::imageUniformDeclaration9045         imageUniformDeclaration(GLuint index) : m_index(index)
9046         {
9047         }
9048 
9049         GLuint m_index;
9050     };
9051 
9052     /** Write declaration of image uniform at given index to output stream
9053      *
9054      * @param stream                   Output stream
9055      * @param imageUniformDeclaration  Declaration details
9056      *
9057      * @return stream
9058      **/
operator <<(std::ostream & stream,const imageUniformDeclaration & declaration)9059     friend std::ostream &operator<<(std::ostream &stream, const imageUniformDeclaration &declaration)
9060     {
9061         ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9062         getImageUniformDeclarationDetails(declaration.m_index, format_details);
9063 
9064         /* layout(r32f) uniform image2D u_image_0; */
9065         stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " ";
9066 
9067         ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index);
9068 
9069         stream << ";";
9070 
9071         return stream;
9072     }
9073 
9074     struct imageLoadCall
9075     {
imageLoadCallgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::imageLoadCall9076         imageLoadCall(GLuint index) : m_index(index)
9077         {
9078         }
9079 
9080         GLuint m_index;
9081     };
9082 
9083     /* Stream operators */
9084     /** Write code that execute imageLoad routine for image at given index to output stream
9085      *
9086      * @param stream Output stream
9087      * @param load   imageLoad call details
9088      *
9089      * @return stream
9090      **/
operator <<(std::ostream & stream,const imageLoadCall & load)9091     friend std::ostream &operator<<(std::ostream &stream, const imageLoadCall &load)
9092     {
9093         ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9094         getImageUniformDeclarationDetails(load.m_index, format_details);
9095 
9096         /* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */
9097         stream << format_details.m_color_type << " ";
9098 
9099         writeLoadedValueVariableNameToStream(stream, load.m_index);
9100 
9101         stream << " = imageLoad(";
9102 
9103         writeImageUniformNameToStream(stream, load.m_index);
9104 
9105         stream << ", ";
9106 
9107         writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */);
9108 
9109         stream << ");";
9110 
9111         return stream;
9112     }
9113 
9114     struct imageStoreCall
9115     {
imageStoreCallgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::imageStoreCall9116         imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row)
9117         {
9118         }
9119 
9120         GLuint m_index;
9121         GLuint m_row;
9122     };
9123 
9124     /** Write code that execute imageStore to image at given index to output stream
9125      *
9126      * @param stream Output stream
9127      * @param store  imageStore call details
9128      *
9129      * @return stream
9130      **/
operator <<(std::ostream & stream,const imageStoreCall & store)9131     friend std::ostream &operator<<(std::ostream &stream, const imageStoreCall &store)
9132     {
9133         /* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */
9134         stream << "imageStore(";
9135 
9136         writeImageUniformNameToStream(stream, store.m_index);
9137 
9138         stream << ", ";
9139 
9140         writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row);
9141 
9142         if (0 == store.m_row)
9143         {
9144             stream << ", -";
9145         }
9146         else
9147         {
9148             stream << ", ";
9149         }
9150 
9151         writeLoadedValueVariableNameToStream(stream, store.m_index);
9152         stream << ");";
9153 
9154         return stream;
9155     }
9156 
9157     struct coordinatesVariableDeclaration
9158     {
coordinatesVariableDeclarationgl4cts::__anonf7c7fa4f0111::ImageLoadStoreMultipleUniformsTest::coordinatesVariableDeclaration9159         coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row)
9160         {
9161         }
9162         GLuint m_index;
9163         GLuint m_row;
9164     };
9165 
9166     /** Write declaration of variable for coordinate at given row to output stream
9167      *
9168      * @param stream      Output stream
9169      * @param declaration Declaration details
9170      *
9171      * @return stream
9172      **/
operator <<(std::ostream & stream,const coordinatesVariableDeclaration & declaration)9173     friend std::ostream &operator<<(std::ostream &stream, const coordinatesVariableDeclaration &declaration)
9174     {
9175         stream << "const ivec2 ";
9176 
9177         writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row);
9178 
9179         stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");";
9180 
9181         return stream;
9182     }
9183 
9184     /* Methods */
9185     /** Build program to test specified shader stage
9186      *
9187      * Throws exception in case of any failure
9188      *
9189      * @param stage Stage id
9190      *
9191      * @return Program id
9192      **/
buildProgramToTestShaderStage(shaderStage stage)9193     GLuint buildProgramToTestShaderStage(shaderStage stage)
9194     {
9195         static const char *const boilerplate_fragment_shader_code =
9196             "#version 400 core\n"
9197             "#extension GL_ARB_shader_image_load_store : require\n"
9198             "\n"
9199             "precision highp float;\n"
9200             "\n"
9201             "void main()\n"
9202             "{\n"
9203             "    discard;\n"
9204             "}\n";
9205 
9206         static const char *const boilerplate_tesselation_evaluation_shader_code =
9207             "#version 400 core\n"
9208             "#extension GL_ARB_shader_image_load_store : require\n"
9209             "\n"
9210             "precision highp float;\n"
9211             "\n"
9212             "layout(quads, equal_spacing, ccw) in;\n"
9213             "\n"
9214             "void main()\n"
9215             "{\n"
9216             "\n"
9217             "}\n";
9218 
9219         static const char *const boilerplate_vertex_shader_code =
9220             "#version 400 core\n"
9221             "#extension GL_ARB_shader_image_load_store : require\n"
9222             "\n"
9223             "precision highp float;\n"
9224             "\n"
9225             "layout(location = 0) in vec4 i_position;\n"
9226             "\n"
9227             "void main()\n"
9228             "{\n"
9229             "  gl_Position = i_position;\n"
9230             "}\n";
9231 
9232         const char *fragment_shader_code               = boilerplate_fragment_shader_code;
9233         const char *geometry_shader_code               = 0;
9234         bool is_program_built                          = true;
9235         GLuint program_object_id                       = 0;
9236         const char *tesselation_control_shader_code    = 0;
9237         const char *tesselation_evaluation_shader_code = 0;
9238         std::string tested_shader_stage_code;
9239         const char *vertex_shader_code = boilerplate_vertex_shader_code;
9240 
9241         /* Get source code for tested shader stage */
9242         prepareShaderForTestedShaderStage(stage, tested_shader_stage_code);
9243 
9244         if (true == tested_shader_stage_code.empty())
9245         {
9246             return 0;
9247         }
9248 
9249         /* Set up source code for all required stages */
9250         switch (stage)
9251         {
9252         case fragmentShaderStage:
9253             fragment_shader_code = tested_shader_stage_code.c_str();
9254             break;
9255 
9256         case geometryShaderStage:
9257             geometry_shader_code = tested_shader_stage_code.c_str();
9258             break;
9259 
9260         case tesselationControlShaderStage:
9261             tesselation_control_shader_code    = tested_shader_stage_code.c_str();
9262             tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code;
9263             break;
9264 
9265         case tesselationEvalutaionShaderStage:
9266             tesselation_evaluation_shader_code = tested_shader_stage_code.c_str();
9267             break;
9268 
9269         case vertexShaderStage:
9270             vertex_shader_code = tested_shader_stage_code.c_str();
9271             break;
9272 
9273         default:
9274             TCU_FAIL("Invalid shader stage");
9275         }
9276 
9277         /* Build program */
9278         program_object_id =
9279             BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
9280                          geometry_shader_code, fragment_shader_code, &is_program_built);
9281 
9282         /* Check if program was built */
9283         if (false == is_program_built)
9284         {
9285             throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
9286         }
9287 
9288         /* Done */
9289         return program_object_id;
9290     }
9291 
9292     /** Create texture to test given shader stage
9293      *
9294      * Throws exception in case of any failure
9295      *
9296      * @param stage Stage id
9297      *
9298      * @return Texture id
9299      **/
createTextureToTestShaderStage(shaderStage stage)9300     GLuint createTextureToTestShaderStage(shaderStage stage)
9301     {
9302         GLenum error                   = glGetError();
9303         const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9304         GLuint texture_id              = 0;
9305         std::vector<GLint> texture_data;
9306 
9307         const GLsizei height = 2;
9308         const GLsizei width  = max_image_uniforms;
9309 
9310         if (m_min_required_image_uniforms > max_image_uniforms)
9311         {
9312             return 0;
9313         }
9314 
9315         /* Generate texture id */
9316         glGenTextures(1, &texture_id);
9317         GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
9318 
9319         /* Bind texture */
9320         glBindTexture(GL_TEXTURE_2D, texture_id);
9321         error = glGetError();
9322         if (GL_NO_ERROR != error)
9323         {
9324             glDeleteTextures(1, &texture_id);
9325             GLU_EXPECT_NO_ERROR(error, "BindTexture");
9326         }
9327 
9328         /* Prepare storage for texture data */
9329         texture_data.resize(width * height);
9330         for (GLint i = 0; i < max_image_uniforms; ++i)
9331         {
9332             texture_data[i]         = getExpectedValue(i);
9333             texture_data[i + width] = 0;
9334         }
9335 
9336         /* Create first level of texture */
9337         glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT,
9338                      &texture_data[0]);
9339         error = glGetError();
9340         if (GL_NO_ERROR != error)
9341         {
9342             glDeleteTextures(1, &texture_id);
9343             GLU_EXPECT_NO_ERROR(error, "TexImage2D");
9344         }
9345 
9346         /* Make texture complete */
9347         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
9348         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
9349         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9350         error = glGetError();
9351         if (GL_NO_ERROR != error)
9352         {
9353             glDeleteTextures(1, &texture_id);
9354             GLU_EXPECT_NO_ERROR(error, "TexParameteri");
9355         }
9356 
9357         /* Done */
9358         return texture_id;
9359     }
9360 
9361     /** Get value of texel for image at given index
9362      *
9363      * @param index Index of image uniform
9364      *
9365      * @return Value of texel
9366      **/
getExpectedValue(GLint index)9367     GLint getExpectedValue(GLint index)
9368     {
9369         // To fix denorm issues with r32f, rg16f and r11f_g11f_b10f
9370         // we set one bit in the exponent of each component of those pixel format
9371         return 0x40104200 + index;
9372     }
9373 
9374     /** Get name of uniform at given index
9375      *
9376      * @param index    Index of uniform
9377      * @param out_name Name of uniform
9378      **/
getImageUniformName(GLuint index,std::string & out_name)9379     void getImageUniformName(GLuint index, std::string &out_name)
9380     {
9381         std::stringstream stream;
9382 
9383         writeImageUniformNameToStream(stream, index);
9384 
9385         out_name = stream.str();
9386     }
9387 
9388     /** Get maximum number of image uniforms allowed for given shader stage
9389      *
9390      * @param stage Stage id
9391      *
9392      * @return Maximum allowed image uniforms
9393      **/
getMaximumImageUniformsForStage(shaderStage stage)9394     GLint getMaximumImageUniformsForStage(shaderStage stage)
9395     {
9396         GLint max_image_uniforms = 0;
9397         GLenum pname             = 0;
9398 
9399         switch (stage)
9400         {
9401         case fragmentShaderStage:
9402             pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS;
9403             break;
9404 
9405         case geometryShaderStage:
9406             pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
9407             break;
9408 
9409         case tesselationControlShaderStage:
9410             pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
9411             break;
9412 
9413         case tesselationEvalutaionShaderStage:
9414             pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
9415             break;
9416 
9417         case vertexShaderStage:
9418             pname = GL_MAX_VERTEX_IMAGE_UNIFORMS;
9419             break;
9420 
9421         default:
9422             TCU_FAIL("Invalid shader stage");
9423         }
9424 
9425         glGetIntegerv(pname, &max_image_uniforms);
9426         GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
9427 
9428         return max_image_uniforms;
9429     }
9430 
9431     /** Prepare source for tested shader stage
9432      *
9433      * @param stage    Stage id
9434      * @param out_code Source code
9435      **/
prepareShaderForTestedShaderStage(shaderStage stage,std::string & out_code)9436     void prepareShaderForTestedShaderStage(shaderStage stage, std::string &out_code)
9437     {
9438         GLint max_image_uniforms             = getMaximumImageUniformsForStage(stage);
9439         const char *stage_specific_layout    = "";
9440         const char *stage_specific_predicate = "true";
9441         std::stringstream stream;
9442 
9443         if (m_min_required_image_uniforms > max_image_uniforms)
9444         {
9445             return;
9446         }
9447 
9448         /* Expected result follows
9449          *
9450          * #version 400 core
9451          * #extension GL_ARB_shader_image_load_store : require
9452          *
9453          * precision highp float;
9454          *
9455          * stage_specific_layout goes here
9456          *
9457          * Uniform declarations go here
9458          *
9459          * void main()
9460          * {
9461          *     const ivec2 row_0_coordinates(0, 0);
9462          *     const ivec2 row_1_coordinates(0, 1);
9463          *
9464          *     For each index <0, GL_MAX_*_IMAGE_UNIFORMS>
9465          *
9466          *     vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates);
9467          *
9468          *     imageStore(u_image_0, row_0_coordinates, -loaded_value_0);
9469          *     imageStore(u_image_0, row_1_coordinates, loaded_value_0);
9470          * }
9471          */
9472 
9473         /* Get piece of code specific for stage */
9474         switch (stage)
9475         {
9476         case fragmentShaderStage:
9477             break;
9478 
9479         case geometryShaderStage:
9480             stage_specific_layout = "layout(points) in;\n"
9481                                     "layout(points, max_vertices = 1) out;\n"
9482                                     "\n";
9483             break;
9484 
9485         case tesselationControlShaderStage:
9486             stage_specific_layout    = "layout(vertices = 4) out;\n"
9487                                        "\n";
9488             stage_specific_predicate = "gl_InvocationID == 0";
9489             break;
9490 
9491         case tesselationEvalutaionShaderStage:
9492             stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n"
9493                                     "\n";
9494             break;
9495 
9496         case vertexShaderStage:
9497             break;
9498 
9499         default:
9500             TCU_FAIL("Invalid shader stage");
9501         }
9502 
9503         /* Preamble */
9504         stream << "#version 400 core\n"
9505                   "#extension GL_ARB_shader_image_load_store : require\n"
9506                   "\n"
9507                   "precision highp float;\n"
9508                   "\n"
9509                << stage_specific_layout;
9510 
9511         /* Image uniforms declarations */
9512         for (GLint i = 0; i < max_image_uniforms; ++i)
9513         {
9514             stream << imageUniformDeclaration(i) << "\n";
9515         }
9516 
9517         /* Main opening */
9518         stream << "\n"
9519                   "void main()\n"
9520                   "{\n";
9521 
9522         stream << "    if (" << stage_specific_predicate << ")\n";
9523         stream << "    {\n";
9524 
9525         /* imageLoad and imageStores for each uniform */
9526         for (GLint i = 0; i < max_image_uniforms; ++i)
9527         {
9528             stream << "        " << coordinatesVariableDeclaration(i, 0) << "\n"
9529                    << "        " << coordinatesVariableDeclaration(i, 1) << "\n"
9530                    << "\n"
9531                    << "        " << imageLoadCall(i) << "\n"
9532                    << "\n"
9533                    << "        " << imageStoreCall(i, 0) << "\n"
9534                    << "        " << imageStoreCall(i, 1) << "\n";
9535 
9536             if (max_image_uniforms > i + 1)
9537             {
9538                 stream << "\n";
9539             }
9540         }
9541 
9542         stream << "    }\n";
9543 
9544         /* Main closing */
9545         stream << "}\n\n";
9546 
9547         /* Done */
9548         out_code = stream.str();
9549     }
9550 
9551     /** Test given shader stage
9552      *
9553      * @param stage Stage id
9554      *
9555      * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms;
9556      *         testFailed when test result is negative;
9557      *         m_test_passed when test result is positive;
9558      **/
testShaderStage(shaderStage stage)9559     testResult testShaderStage(shaderStage stage)
9560     {
9561         std::string image_uniform_name;
9562         static const GLint invalid_uniform_location = -1;
9563         const GLint max_image_uniforms              = getMaximumImageUniformsForStage(stage);
9564         GLenum primitive_mode                       = GL_POINTS;
9565         GLuint program_id                           = 0;
9566         testResult result                           = testPassed;
9567         std::vector<GLint> texture_data;
9568         GLuint texture_id = 0;
9569 
9570         static const GLuint height = 2;
9571         const GLuint width         = max_image_uniforms;
9572 
9573         const GLuint positive_value_index       = width;
9574         static const GLuint negated_value_index = 0;
9575 
9576         if (m_min_required_image_uniforms > max_image_uniforms)
9577         {
9578             return testNotSupported;
9579         }
9580 
9581         /* Select program and texture ids for given stage */
9582         switch (stage)
9583         {
9584         case fragmentShaderStage:
9585             program_id = m_program_to_test_fs_stage_id;
9586             texture_id = m_texture_to_test_fs_stage_id;
9587             break;
9588 
9589         case geometryShaderStage:
9590             program_id = m_program_to_test_gs_stage_id;
9591             texture_id = m_texture_to_test_gs_stage_id;
9592             break;
9593 
9594         case tesselationControlShaderStage:
9595             primitive_mode = GL_PATCHES;
9596             program_id     = m_program_to_test_tcs_stage_id;
9597             texture_id     = m_texture_to_test_tcs_stage_id;
9598             break;
9599 
9600         case tesselationEvalutaionShaderStage:
9601             primitive_mode = GL_PATCHES;
9602             program_id     = m_program_to_test_tes_stage_id;
9603             texture_id     = m_texture_to_test_tes_stage_id;
9604             break;
9605 
9606         case vertexShaderStage:
9607             program_id = m_program_to_test_vs_stage_id;
9608             texture_id = m_texture_to_test_vs_stage_id;
9609             break;
9610 
9611         default:
9612             TCU_FAIL("Invalid shader stage");
9613         }
9614 
9615         /* Set program */
9616         glUseProgram(program_id);
9617         GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
9618 
9619         /* Bind texture to image units */
9620         for (GLint i = 0; i < max_image_uniforms; ++i)
9621         {
9622             imageFormatDetails format_details;
9623             getImageUniformDeclarationDetails(i, format_details);
9624 
9625             glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9626                                GL_READ_WRITE, format_details.m_image_unit_format);
9627             GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9628         }
9629 
9630         /* Set all image uniforms to corresponding image units */
9631         for (GLint i = 0; i < max_image_uniforms; ++i)
9632         {
9633             /* Get name */
9634             getImageUniformName(i, image_uniform_name);
9635 
9636             /* Get location */
9637             GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str());
9638             GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
9639 
9640             if (invalid_uniform_location == image_uniform_location)
9641             {
9642                 throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__,
9643                                          __LINE__);
9644             }
9645 
9646             /* Set uniform value */
9647             glUniform1i(image_uniform_location, i /* image_unit */);
9648             GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
9649         }
9650 
9651         /* Execute draw */
9652         glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */);
9653         GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
9654 
9655         glMemoryBarrier(GL_ALL_BARRIER_BITS);
9656 
9657         texture_data.resize(width * height);
9658 
9659         /* Get texture data */
9660         glBindTexture(GL_TEXTURE_2D, texture_id);
9661         GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
9662 
9663         glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]);
9664         GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
9665 
9666         /* Verify each image uniform */
9667         for (GLint i = 0; i < max_image_uniforms; ++i)
9668         {
9669             imageFormatDetails format_details;
9670             getImageUniformDeclarationDetails(i, format_details);
9671 
9672             if (false == format_details.m_verification_routine(getExpectedValue(i),
9673                                                                texture_data[positive_value_index + i],
9674                                                                texture_data[negated_value_index + i]))
9675             {
9676                 m_context.getTestContext().getLog()
9677                     << tcu::TestLog::Message << "Invalid result!"
9678                     << " Image format: " << format_details.m_image_format << " Original value: "
9679                     << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i)
9680                     << " Copied value: "
9681                     << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9682                     << texture_data[positive_value_index + i] << " Negated value: "
9683                     << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9684                     << texture_data[negated_value_index + i] << tcu::TestLog::EndMessage;
9685 
9686                 result = testFailed;
9687             }
9688         }
9689 
9690         /* Done */
9691         return result;
9692     }
9693 
9694     /** Verifies if original_value, positive_value and negated_value match
9695      *
9696      * @tparam T Type used during verification process, it should match float values by size
9697      *
9698      * @param original_value Original value of texel, used when creating a texture
9699      * @param positive_value Value stored by shader as read
9700      * @param negated_value  Value stored by shader after negation
9701      *
9702      * @return true if values match, false otherwise
9703      **/
9704     template <typename T>
verifyFloat(GLint original_value,GLint positive_value,GLint negated_value)9705     static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value)
9706     {
9707         if (original_value != positive_value)
9708         {
9709             return false;
9710         }
9711 
9712         static const GLuint n_elements     = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9713         static const GLuint sign_bit_index = sizeof(T) * 8 - 1;         /* 7, 15, 31 */
9714         static const T sign_bit_mask       = 1 << sign_bit_index;       /* 0x80.. */
9715         static const T sign_bit_inv_mask   = (T)~sign_bit_mask;         /* 0x7f.. */
9716 
9717         const T *positive_elements = (T *)&positive_value;
9718         const T *negated_elements  = (T *)&negated_value;
9719 
9720         for (GLuint i = 0; i < n_elements; ++i)
9721         {
9722             const T positive_element = positive_elements[i];
9723             const T negated_element  = negated_elements[i];
9724 
9725             const T positive_sign_bit = positive_element & sign_bit_mask;
9726             const T negated_sign_bit  = negated_element & sign_bit_mask;
9727 
9728             const T positive_data = positive_element & sign_bit_inv_mask;
9729             const T negated_data  = negated_element & sign_bit_inv_mask;
9730 
9731             /* Compare data bits */
9732             if (positive_data != negated_data)
9733             {
9734                 return false;
9735             }
9736 
9737             /* Verify that sign bit is inverted */
9738             if (positive_sign_bit == negated_sign_bit)
9739             {
9740                 return false;
9741             }
9742         }
9743 
9744         return true;
9745     }
9746 
9747     /** Verifies if original_value, positive_value and negated_value match
9748      *
9749      * @tparam T Type used during verification process, it should match float values by size
9750      *
9751      * @param original_value Original value of texel, used when creating a texture
9752      * @param positive_value Value stored by shader as read
9753      * @param negated_value  Value stored by shader after negation
9754      *
9755      * @return true if values match, false otherwise
9756      **/
9757     template <typename T>
verifyFloatSignedNorm(GLint original_value,GLint positive_value,GLint negated_value)9758     static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value)
9759     {
9760         if (original_value != positive_value)
9761         {
9762             return false;
9763         }
9764 
9765         static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9766 
9767         const T *positive_elements = (T *)&positive_value;
9768         const T *negated_elements  = (T *)&negated_value;
9769 
9770         for (GLuint i = 0; i < n_elements; ++i)
9771         {
9772             const T positive_element = positive_elements[i];
9773             const T negated_element  = negated_elements[i];
9774 
9775             /* Compare data bits */
9776             if (positive_element != -negated_element)
9777             {
9778                 return false;
9779             }
9780         }
9781 
9782         return true;
9783     }
9784 
9785     /** Verifies if original_value, positive_value and negated_value match
9786      *
9787      * @tparam R Number of bits for red channel
9788      * @tparam G Number of bits for green channel
9789      * @tparam B Number of bits for blue channel
9790      * @tparam A Number of bits for alpha channel
9791      *
9792      * @param original_value Original value of texel, used when creating a texture
9793      * @param positive_value Value stored by shader as read
9794      * @param negated_value  Value stored by shader after negation
9795      *
9796      * @return true if values match, false otherwise
9797      **/
9798     template <GLuint R, GLuint G, GLuint B, GLuint A, typename T>
verifyInteger(GLint original_value,GLint positive_value,GLint negated_value)9799     static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9800     {
9801         if (original_value != positive_value)
9802         {
9803             return false;
9804         }
9805 
9806         Integer<T, R, 0> positive_red(positive_value);
9807         Integer<T, R, 0> negated_red(negated_value);
9808 
9809         Integer<T, G, R> positive_green(positive_value);
9810         Integer<T, G, R> negated_green(negated_value);
9811 
9812         Integer<T, B, R + G> positive_blue(positive_value);
9813         Integer<T, B, R + G> negated_blue(negated_value);
9814 
9815         Integer<T, A, R + G + B> positive_alpha(positive_value);
9816         Integer<T, A, R + G + B> negated_alpha(negated_value);
9817 
9818         if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) ||
9819             ((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) ||
9820             ((0 != G) && (positive_green.GetNegated() != negated_green.Get())) ||
9821             ((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get())))
9822         {
9823             return false;
9824         }
9825 
9826         return true;
9827     }
9828 
9829     /** Verifies if original_value, positive_value and negated_value match
9830      *
9831      * @param original_value Original value of texel, used when creating a texture
9832      * @param positive_value Value stored by shader as read
9833      * @param negated_value  Value stored by shader after negation
9834      *
9835      * @return true if values match, false otherwise
9836      **/
verifyInteger(GLint original_value,GLint positive_value,GLint negated_value)9837     static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9838     {
9839         if (original_value != positive_value)
9840         {
9841             return false;
9842         }
9843 
9844         if (positive_value != -negated_value)
9845         {
9846             return false;
9847         }
9848 
9849         return true;
9850     }
9851 
9852     /** Verifies if original_value, positive_value and negated_value match
9853      *
9854      * @param original_value Original value of texel, used when creating a texture
9855      * @param positive_value Value stored by shader as read
9856      * @param negated_value  Value stored by shader after negation
9857      *
9858      * @return true if values match, false otherwise
9859      **/
9860     template <typename T>
verifyFloatUnsigned(GLint original_value,GLint positive_value,GLint negated_value)9861     static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value)
9862     {
9863         if (original_value != positive_value)
9864         {
9865             return false;
9866         }
9867 
9868         if (0 != negated_value)
9869         {
9870             return false;
9871         }
9872 
9873         return true;
9874     }
9875 };
9876 
9877 /** Test "Early fragment tests" description follows.
9878  *
9879  *  BasicGLSLEarlyFragTests verifies that:
9880  *  - early z test is applied when enabled,
9881  *  - early z test is not applied when disabled.
9882  *
9883  *  Proposed modifications:
9884  *  - verify that early z test does not discard all fragments when enabled,
9885  *  - verify that early stencil test is applied when enabled,
9886  *  - verify that early stencil test does not discard all fragments when
9887  *  enabled,
9888  *  - verify that early stencil test is not applied when disabled.
9889  *
9890  *  Steps:
9891  *  - prepare 2 programs that store 1.0 at red channel to image in fragment
9892  *  shader stage:
9893  *      a) one program should enable early fragment tests
9894  *      ("layout(early_fragment_tests) in;"),
9895  *      b) second program should disable early fragment tests,
9896  *  - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL
9897  *  depth-stencil attachments,
9898  *  - prepare 2D texture 64x64 R32F,
9899  *  - enable depth test,
9900  *  - verify that early z test is applied when enabled:
9901  *      - use program enabling early fragment tests,
9902  *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9903  *      - fill texture with zeros,
9904  *      - bind texture to image uniform,
9905  *      - draw "full screen" quad (left bottom corner at -1,-1 and right top
9906  *      corner at 1,1) at z: 0.75
9907  *      - verify that texture is still filled with zeros,
9908  *  - verify that early z test does not discard all fragments:
9909  *      - use program enabling early fragment tests,
9910  *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9911  *      - fill texture with zeros,
9912  *      - bind texture to image uniform,
9913  *      - draw "full screen" quad at z: 0.25
9914  *      - verify that texture is now filled with 1.0,
9915  *  -verify that early z test is not applied when disabled:
9916  *      - use program disabling early fragment tests,
9917  *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9918  *      - fill texture with zeros,
9919  *      - bind texture to image uniform,
9920  *      - draw "full screen" quad at z: 0.75
9921  *      - verify that texture is now filled with 1.0.
9922  *  - disable depth test
9923  *  - enable stencil test
9924  *  - verify that early stencil test is applied when enabled:
9925  *      - use program enabling early fragment tests,
9926  *      - clean frame buffer with color: 0, stencil: 0 and depth 1,
9927  *      - fill texture with zeros,
9928  *      - set stencil test to:
9929  *          - <func> to GL_LESS,
9930  *          - <ref> to 128,
9931  *          - <mask> 0xffffffff,
9932  *      - bind texture to image uniform,
9933  *      - draw "full screen" quad at z: 0,
9934  *      - verify that texture is still filled with zeros,
9935  *  - verify that early stencil test does not discard all fragments:
9936  *      - use program enabling early fragment tests,
9937  *      - clean frame buffer with color: 0, stencil: 128 and depth 1,
9938  *      - fill texture with zeros,
9939  *      - set stencil test to:
9940  *          - <func> to GL_LESS,
9941  *          - <ref> to 0,
9942  *          - <mask> 0xffffffff,
9943  *      - bind texture to image uniform,
9944  *      - draw "full screen" quad at z: 0,
9945  *      - verify that texture is now filled with 1.0,
9946  *  - verify that early stencil test is not applied when disabled:
9947  *      - use program disabling early fragment tests,
9948  *      - clean frame buffer with color: 0, stencil: 0 and depth 1,
9949  *      - fill texture with zeros,
9950  *      - set stencil test to:
9951  *          - <func> to GL_LESS,
9952  *          - <ref> to 128,
9953  *          - <mask> 0xffffffff,
9954  *      - bind texture to image uniform,
9955  *      - draw "full screen" quad at z: 0,
9956  *      - verify that texture is now filled with 1.0
9957  **/
9958 class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase
9959 {
9960 private:
9961     /* Constants */
9962     GLuint m_image_edge;
9963     static const GLint m_invalid_uniform_location = -1;
9964 
9965     /* Types */
9966     /** Store id and uniform locations for a single program object
9967      *
9968      **/
9969     struct programDetails
9970     {
9971         GLint m_depth_uniform_location;
9972         GLint m_image_uniform_location;
9973         GLuint m_program_id;
9974 
programDetailsgl4cts::__anonf7c7fa4f0111::ImageLoadStoreEarlyFragmentTestsTest::programDetails9975         programDetails()
9976             : m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9977             , m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9978             , m_program_id(0)
9979         {
9980             /* Nothing to be done here */
9981         }
9982     };
9983 
9984     /* Fileds */
9985     /* Storage for texture data */
9986     std::vector<GLfloat> m_clean_texture_data;
9987     std::vector<GLfloat> m_extracted_texture_data;
9988 
9989     /* Program details */
9990     programDetails m_disabled_early_tests;
9991     programDetails m_enabled_early_tests;
9992 
9993     /* Ids of GL objects */
9994     GLuint m_color_renderbuffer_id;
9995     GLuint m_depth_stencil_renderbuffer_id;
9996     GLuint m_framebuffer_id;
9997     GLuint m_texture_id;
9998     GLuint m_vertex_array_object_id;
9999 
10000 public:
10001     /* Constructor */
ImageLoadStoreEarlyFragmentTestsTest()10002     ImageLoadStoreEarlyFragmentTestsTest()
10003         : m_image_edge(0)
10004         , m_color_renderbuffer_id(0)
10005         , m_depth_stencil_renderbuffer_id(0)
10006         , m_framebuffer_id(0)
10007         , m_texture_id(0)
10008         , m_vertex_array_object_id(0)
10009     {
10010         /* Nothing to be done here */
10011     }
10012 
10013     /* Methods inherited from SubcaseBase */
Cleanup()10014     virtual long Cleanup()
10015     {
10016         /* Restore defaults */
10017         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
10018         glBindRenderbuffer(GL_RENDERBUFFER, 0);
10019         glBindTexture(GL_TEXTURE_2D, 0);
10020         glBindVertexArray(0);
10021         glDisable(GL_DEPTH_TEST);
10022         glDisable(GL_STENCIL_TEST);
10023         glUseProgram(0);
10024 
10025         /* Delete objects */
10026         if (0 != m_disabled_early_tests.m_program_id)
10027         {
10028             glDeleteProgram(m_disabled_early_tests.m_program_id);
10029             m_disabled_early_tests.m_program_id = 0;
10030         }
10031 
10032         if (0 != m_enabled_early_tests.m_program_id)
10033         {
10034             glDeleteProgram(m_enabled_early_tests.m_program_id);
10035             m_enabled_early_tests.m_program_id = 0;
10036         }
10037 
10038         if (0 != m_color_renderbuffer_id)
10039         {
10040             glDeleteRenderbuffers(1, &m_color_renderbuffer_id);
10041             m_color_renderbuffer_id = 0;
10042         }
10043 
10044         if (0 != m_depth_stencil_renderbuffer_id)
10045         {
10046             glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10047             m_depth_stencil_renderbuffer_id = 0;
10048         }
10049 
10050         if (0 != m_framebuffer_id)
10051         {
10052             glDeleteFramebuffers(1, &m_framebuffer_id);
10053             m_framebuffer_id = 0;
10054         }
10055 
10056         if (0 != m_texture_id)
10057         {
10058             glDeleteTextures(1, &m_texture_id);
10059             m_texture_id = 0;
10060         }
10061 
10062         if (0 != m_vertex_array_object_id)
10063         {
10064             glDeleteVertexArrays(1, &m_vertex_array_object_id);
10065             m_vertex_array_object_id = 0;
10066         }
10067 
10068         /* Done */
10069         return NO_ERROR;
10070     }
10071 
Run()10072     virtual long Run()
10073     {
10074         bool result = true;
10075 
10076         /* Bind texture to first image unit */
10077         glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
10078                            GL_READ_WRITE, GL_R32F);
10079         GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
10080 
10081         /* Run tests for depth test */
10082         if (false == testEarlyZ())
10083         {
10084             result = false;
10085         }
10086 
10087         /* Run tests for stencil test */
10088         if (false == testEarlyStencil())
10089         {
10090             result = false;
10091         }
10092 
10093         /* Return ERROR if any problem was found */
10094         if (false == result)
10095         {
10096             return ERROR;
10097         }
10098 
10099         /* Done */
10100         return NO_ERROR;
10101     }
10102 
Setup()10103     virtual long Setup()
10104     {
10105         m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
10106 
10107         /* Prepare storage for texture data */
10108         m_clean_texture_data.resize(m_image_edge * m_image_edge);
10109         m_extracted_texture_data.resize(m_image_edge * m_image_edge);
10110 
10111         /* Prepare programs, framebuffer and texture */
10112         buildPrograms();
10113         createFramebuffer();
10114         createTexture();
10115 
10116         /* Generate vertex array object */
10117         glGenVertexArrays(1, &m_vertex_array_object_id);
10118         GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
10119 
10120         /* Bind vertex array object */
10121         glBindVertexArray(m_vertex_array_object_id);
10122         GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
10123 
10124         /* Set clear color */
10125         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
10126         GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor");
10127 
10128         /* Done */
10129         return NO_ERROR;
10130     }
10131 
10132 private:
10133     /** Build two programs: with enabled and disabled early fragment tests
10134      *
10135      **/
buildPrograms()10136     void buildPrograms()
10137     {
10138         static const char *const fragment_shader_with_disabled_early_tests =
10139             "#version 400 core\n"
10140             "#extension GL_ARB_shader_image_load_store : require\n"
10141             "\n"
10142             "precision highp float;\n"
10143             "\n"
10144             "layout(r32f) uniform image2D u_image;\n"
10145             "\n"
10146             "void main()\n"
10147             "{\n"
10148             "    vec4 color = vec4(1.0, 0, 0, 0);\n"
10149             "\n"
10150             "    imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10151             "\n"
10152             "    discard;\n"
10153             "}\n\n";
10154 
10155         static const char *const fragment_shader_with_enabled_early_tests =
10156             "#version 400 core\n"
10157             "#extension GL_ARB_shader_image_load_store : require\n"
10158             "\n"
10159             "precision highp float;\n"
10160             "\n"
10161             "layout(early_fragment_tests) in;\n"
10162             "\n"
10163             "layout(r32f) uniform image2D u_image;\n"
10164             "\n"
10165             "void main()\n"
10166             "{\n"
10167             "    vec4 color = vec4(1.0, 0, 0, 0);\n"
10168             "\n"
10169             "    imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10170             "\n"
10171             "    discard;\n"
10172             "}\n\n";
10173 
10174         static const char *const geometry_shader_code = "#version 400 core\n"
10175                                                         "#extension GL_ARB_shader_image_load_store : require\n"
10176                                                         "\n"
10177                                                         "precision highp float;\n"
10178                                                         "\n"
10179                                                         "layout(points)                           in;\n"
10180                                                         "layout(triangle_strip, max_vertices = 4) out;\n"
10181                                                         "\n"
10182                                                         "uniform float u_depth;\n"
10183                                                         "\n"
10184                                                         "void main()\n"
10185                                                         "{\n"
10186                                                         "    // Left-bottom\n"
10187                                                         "    gl_Position = vec4(-1, -1, u_depth, 1);\n"
10188                                                         "    EmitVertex();\n"
10189                                                         "\n"
10190                                                         "    // Left-top\n"
10191                                                         "    gl_Position = vec4(-1,  1, u_depth, 1);\n"
10192                                                         "    EmitVertex();\n"
10193                                                         "\n"
10194                                                         "    // Right-bottom\n"
10195                                                         "    gl_Position = vec4( 1, -1, u_depth, 1);\n"
10196                                                         "    EmitVertex();\n"
10197                                                         "\n"
10198                                                         "    // Right-top\n"
10199                                                         "    gl_Position = vec4( 1,  1, u_depth, 1);\n"
10200                                                         "    EmitVertex();\n"
10201                                                         "}\n\n";
10202 
10203         static const char *const vertex_shader_code = "#version 400 core\n"
10204                                                       "#extension GL_ARB_shader_image_load_store : require\n"
10205                                                       "\n"
10206                                                       "precision highp float;\n"
10207                                                       "\n"
10208                                                       "void main()\n"
10209                                                       "{\n"
10210                                                       "}\n\n";
10211 
10212         prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code,
10213                               m_disabled_early_tests);
10214 
10215         prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code,
10216                               m_enabled_early_tests);
10217     }
10218 
10219     /** Fill texture with zeros
10220      *
10221      **/
cleanTexture()10222     void cleanTexture()
10223     {
10224         glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge,
10225                         GL_RED, GL_FLOAT, &m_clean_texture_data[0]);
10226         GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D");
10227     }
10228 
10229     /** Create and bind (draw) framebuffer with color and depth-stencil attachments
10230      *
10231      **/
createFramebuffer()10232     void createFramebuffer()
10233     {
10234         /* Generate render buffers */
10235         glGenRenderbuffers(1, &m_color_renderbuffer_id);
10236         GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10237 
10238         glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10239         GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10240 
10241         /* Generate and bind framebuffer object */
10242         glGenFramebuffers(1, &m_framebuffer_id);
10243         GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers");
10244 
10245         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
10246         GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer");
10247 
10248         /* Prepare color render buffer */
10249         glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id);
10250         GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10251 
10252         glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge);
10253         GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10254 
10255         /* Set up color attachment */
10256         glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id);
10257         GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10258 
10259         /* Prepare depth-stencil render buffer */
10260         glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id);
10261         GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10262 
10263         glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge);
10264         GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10265 
10266         /* Set up depth-stencil attachment */
10267         glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10268                                   m_depth_stencil_renderbuffer_id);
10269         GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10270     }
10271 
10272     /** Create 2D R32F texture
10273      *
10274      **/
createTexture()10275     void createTexture()
10276     {
10277         glGenTextures(1, &m_texture_id);
10278         GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
10279 
10280         glBindTexture(GL_TEXTURE_2D, m_texture_id);
10281         GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
10282 
10283         glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge);
10284         GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D");
10285     }
10286 
10287     /** Extracts red channel from texture and verify if all texels are set to specified value
10288      *
10289      * @param value Expected value
10290      *
10291      * @return true if all texel match expected value, false otherwise
10292      **/
isTextureFilledWithValue(GLfloat value)10293     bool isTextureFilledWithValue(GLfloat value)
10294     {
10295         glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]);
10296         GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
10297 
10298         for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i)
10299         {
10300             if (value != m_extracted_texture_data[i])
10301             {
10302                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i
10303                                                     << " has invalid value: " << m_extracted_texture_data[i]
10304                                                     << " expected: " << value << tcu::TestLog::EndMessage;
10305 
10306                 return false;
10307             }
10308         }
10309 
10310         return true;
10311     }
10312 
10313     /** Build program, extract location of uniforms and store results in programDetails instance
10314      *
10315      * Throws tcu::InternalError if uniforms are inactive
10316      *
10317      * @param fragment_shader_code Source of fragment shader
10318      * @param geometry_shader_code Source of geometry shader
10319      * @param vertex_shader_code   Source of vertex shader
10320      * @param out_program_details  Instance of programDetails
10321      **/
prepareProgramDetails(const char * fragment_shader_code,const char * geometry_shader_code,const char * vertex_shader_code,programDetails & out_program_details)10322     void prepareProgramDetails(const char *fragment_shader_code, const char *geometry_shader_code,
10323                                const char *vertex_shader_code, programDetails &out_program_details)
10324     {
10325         static const char *const depth_uniform_name = "u_depth";
10326         static const char *const image_uniform_name = "u_image";
10327         bool is_program_built                       = true;
10328 
10329         GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code,
10330                                          fragment_shader_code, &is_program_built);
10331 
10332         if (false == is_program_built)
10333         {
10334             throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
10335         }
10336 
10337         /* Get depth uniform location */
10338         GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name);
10339         GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10340 
10341         if (m_invalid_uniform_location == depth_uniform_location)
10342         {
10343             throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10344         }
10345 
10346         /* Get image uniform location */
10347         GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name);
10348         GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10349 
10350         if (m_invalid_uniform_location == image_uniform_location)
10351         {
10352             throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10353         }
10354 
10355         /* Store results */
10356         out_program_details.m_depth_uniform_location = depth_uniform_location;
10357         out_program_details.m_image_uniform_location = image_uniform_location;
10358         out_program_details.m_program_id             = program_id;
10359     }
10360 
10361     /** Test if early fragment stencil test works as expected.
10362      *
10363      * @return true if successful, false otherwise
10364      **/
testEarlyStencil()10365     bool testEarlyStencil()
10366     {
10367         bool result = true;
10368 
10369         glEnable(GL_STENCIL_TEST);
10370         GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10371 
10372         glClearDepthf(1.0f);
10373         GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10374 
10375         /* verify that early stencil test is applied when enabled */
10376         {
10377             glUseProgram(m_enabled_early_tests.m_program_id);
10378             GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10379 
10380             glClearStencil(0);
10381             GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10382 
10383             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10384             GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10385 
10386             cleanTexture();
10387 
10388             glStencilFunc(GL_LESS, 128, 0xffffffff);
10389             GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10390 
10391             glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10392             GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10393 
10394             glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10395             GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10396 
10397             glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10398             GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10399 
10400             glMemoryBarrier(GL_ALL_BARRIER_BITS);
10401             GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10402 
10403             if (false == isTextureFilledWithValue(0.0f))
10404             {
10405                 m_context.getTestContext().getLog()
10406                     << tcu::TestLog::Message << "Problem with early stencil test. It is not applied"
10407                     << tcu::TestLog::EndMessage;
10408 
10409                 result = false;
10410             }
10411         }
10412 
10413         /* verify that early stencil test does not discard all fragments */
10414         {
10415             glClearStencil(128);
10416             GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10417 
10418             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10419             GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10420 
10421             cleanTexture();
10422 
10423             glStencilFunc(GL_LESS, 0, 0xffffffff);
10424             GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10425 
10426             glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10427             GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10428 
10429             glMemoryBarrier(GL_ALL_BARRIER_BITS);
10430             GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10431 
10432             if (false == isTextureFilledWithValue(1.0f))
10433             {
10434                 m_context.getTestContext().getLog()
10435                     << tcu::TestLog::Message
10436                     << "Problem with early stencil test. It discards fragments, that shall be drawn"
10437                     << tcu::TestLog::EndMessage;
10438 
10439                 result = false;
10440             }
10441         }
10442 
10443         /* verify that early stencil test is not applied when disabled */
10444         {
10445             glUseProgram(m_disabled_early_tests.m_program_id);
10446             GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10447 
10448             glClearStencil(0);
10449             GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10450 
10451             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10452             GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10453 
10454             cleanTexture();
10455 
10456             glStencilFunc(GL_LESS, 128, 0xffffffff);
10457             GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10458 
10459             glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10460             GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10461 
10462             glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10463             GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10464 
10465             glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10466             GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10467 
10468             glMemoryBarrier(GL_ALL_BARRIER_BITS);
10469             GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10470 
10471             if (false == isTextureFilledWithValue(1.0f))
10472             {
10473                 m_context.getTestContext().getLog()
10474                     << tcu::TestLog::Message << "Problem with early stencil test. It is applied when disabled"
10475                     << tcu::TestLog::EndMessage;
10476 
10477                 result = false;
10478             }
10479         }
10480 
10481         glDisable(GL_STENCIL_TEST);
10482         GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10483 
10484         /* Done */
10485         return result;
10486     }
10487 
10488     /** Test if early fragment depth test works as expected.
10489      *
10490      * @return true if successful, false otherwise
10491      **/
testEarlyZ()10492     bool testEarlyZ()
10493     {
10494         bool result = true;
10495 
10496         glEnable(GL_DEPTH_TEST);
10497         GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10498 
10499         glClearDepthf(0.5f);
10500         GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10501 
10502         glClearStencil(0);
10503         GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10504 
10505         /* verify that early z test is applied when enabled */
10506         {
10507             glUseProgram(m_enabled_early_tests.m_program_id);
10508             GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10509 
10510             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10511             GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10512 
10513             cleanTexture();
10514 
10515             glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10516             GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10517 
10518             glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10519             GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10520 
10521             glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10522             GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10523 
10524             glMemoryBarrier(GL_ALL_BARRIER_BITS);
10525             GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10526 
10527             if (false == isTextureFilledWithValue(0.0f))
10528             {
10529                 m_context.getTestContext().getLog()
10530                     << tcu::TestLog::Message << "Problem with early z test. It is not applied"
10531                     << tcu::TestLog::EndMessage;
10532 
10533                 result = false;
10534             }
10535         }
10536 
10537         /* verify that early z test does not discard all fragments */
10538         {
10539             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10540             GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10541 
10542             cleanTexture();
10543 
10544             glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10545             GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10546 
10547             glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */);
10548             GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10549 
10550             glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10551             GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10552 
10553             glMemoryBarrier(GL_ALL_BARRIER_BITS);
10554             GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10555 
10556             if (false == isTextureFilledWithValue(1.0f))
10557             {
10558                 m_context.getTestContext().getLog()
10559                     << tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn"
10560                     << tcu::TestLog::EndMessage;
10561 
10562                 result = false;
10563             }
10564         }
10565 
10566         /* verify that early z test is not applied when disabled */
10567         {
10568             glUseProgram(m_disabled_early_tests.m_program_id);
10569             GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10570 
10571             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10572             GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10573 
10574             cleanTexture();
10575 
10576             glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10577             GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10578 
10579             glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10580             GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10581 
10582             glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10583             GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10584 
10585             glMemoryBarrier(GL_ALL_BARRIER_BITS);
10586             GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10587 
10588             if (false == isTextureFilledWithValue(1.0f))
10589             {
10590                 m_context.getTestContext().getLog()
10591                     << tcu::TestLog::Message << "Problem with early z test. It is applied when disabled"
10592                     << tcu::TestLog::EndMessage;
10593 
10594                 result = false;
10595             }
10596         }
10597 
10598         glDisable(GL_DEPTH_TEST);
10599         GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10600 
10601         /* Done */
10602         return result;
10603     }
10604 };
10605 
10606 //-----------------------------------------------------------------------------
10607 // 4.1 NegativeUniform
10608 //-----------------------------------------------------------------------------
10609 class NegativeUniform : public ShaderImageLoadStoreBase
10610 {
10611     GLuint m_program;
10612 
Setup()10613     virtual long Setup()
10614     {
10615         m_program = 0;
10616         return NO_ERROR;
10617     }
10618 
Run()10619     virtual long Run()
10620     {
10621         const char *glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
10622                               "  gl_Position = i_position;" NL "}";
10623         const char *glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
10624                               "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(0.0));" NL
10625                               "  discard;" NL "}";
10626         m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
10627 
10628         GLint max_image_units;
10629         glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
10630         glUseProgram(m_program);
10631 
10632         glUniform1i(glGetUniformLocation(m_program, "g_image"), -1);
10633         if (glGetError() != GL_INVALID_VALUE)
10634         {
10635             m_context.getTestContext().getLog()
10636                 << tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero."
10637                 << tcu::TestLog::EndMessage;
10638             return ERROR;
10639         }
10640         glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units);
10641         if (glGetError() != GL_INVALID_VALUE)
10642         {
10643             m_context.getTestContext().getLog()
10644                 << tcu::TestLog::Message
10645                 << "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of "
10646                 << "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
10647             return ERROR;
10648         }
10649 
10650         GLint i = -3;
10651         glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10652         if (glGetError() != GL_INVALID_VALUE)
10653         {
10654             m_context.getTestContext().getLog()
10655                 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10656                 << tcu::TestLog::EndMessage;
10657             return ERROR;
10658         }
10659         i = max_image_units + 1;
10660         glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10661         if (glGetError() != GL_INVALID_VALUE)
10662         {
10663             m_context.getTestContext().getLog() << tcu::TestLog::Message
10664                                                 << "glUniform1iv should generate INVALID_VALUE when <value> is greater "
10665                                                    "than or equal to the value of MAX_IMAGE_UNITS."
10666                                                 << tcu::TestLog::EndMessage;
10667             return ERROR;
10668         }
10669 
10670         glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
10671         if (glGetError() != GL_INVALID_OPERATION)
10672         {
10673             m_context.getTestContext().getLog()
10674                 << tcu::TestLog::Message
10675                 << "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable."
10676                 << tcu::TestLog::EndMessage;
10677             return ERROR;
10678         }
10679         glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
10680         if (glGetError() != GL_INVALID_OPERATION)
10681         {
10682             m_context.getTestContext().getLog()
10683                 << tcu::TestLog::Message
10684                 << "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable."
10685                 << tcu::TestLog::EndMessage;
10686             return ERROR;
10687         }
10688 
10689         {
10690             glUseProgram(0);
10691 
10692             glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1);
10693             if (glGetError() != GL_INVALID_VALUE)
10694             {
10695                 m_context.getTestContext().getLog()
10696                     << tcu::TestLog::Message
10697                     << "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero."
10698                     << tcu::TestLog::EndMessage;
10699                 return ERROR;
10700             }
10701             glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units);
10702             if (glGetError() != GL_INVALID_VALUE)
10703             {
10704                 m_context.getTestContext().getLog()
10705                     << tcu::TestLog::Message
10706                     << "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the "
10707                        "value of MAX_IMAGE_UNITS."
10708                     << tcu::TestLog::EndMessage;
10709                 return ERROR;
10710             }
10711 
10712             GLint ii = -3;
10713             glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10714             if (glGetError() != GL_INVALID_VALUE)
10715             {
10716                 m_context.getTestContext().getLog()
10717                     << tcu::TestLog::Message
10718                     << "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10719                     << tcu::TestLog::EndMessage;
10720                 return ERROR;
10721             }
10722             ii = max_image_units + 1;
10723             glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10724             if (glGetError() != GL_INVALID_VALUE)
10725             {
10726                 m_context.getTestContext().getLog() << tcu::TestLog::Message
10727                                                     << "glProgramUniform1iv should generate INVALID_VALUE when <value> "
10728                                                        "is greater than or equal to the value of MAX_IMAGE_UNITS."
10729                                                     << tcu::TestLog::EndMessage;
10730                 return ERROR;
10731             }
10732 
10733             glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
10734             if (glGetError() != GL_INVALID_OPERATION)
10735             {
10736                 m_context.getTestContext().getLog() << tcu::TestLog::Message
10737                                                     << "glProgramUniform1ui should generate INVALID_OPERATION if the "
10738                                                        "location refers to an image variable."
10739                                                     << tcu::TestLog::EndMessage;
10740                 return ERROR;
10741             }
10742             glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
10743             if (glGetError() != GL_INVALID_OPERATION)
10744             {
10745                 m_context.getTestContext().getLog() << tcu::TestLog::Message
10746                                                     << "glProgramUniform2i should generate INVALID_OPERATION if the "
10747                                                        "location refers to an image variable."
10748                                                     << tcu::TestLog::EndMessage;
10749                 return ERROR;
10750             }
10751         }
10752 
10753         return NO_ERROR;
10754     }
10755 
Cleanup()10756     virtual long Cleanup()
10757     {
10758         glUseProgram(0);
10759         glDeleteProgram(m_program);
10760         return NO_ERROR;
10761     }
10762 };
10763 //-----------------------------------------------------------------------------
10764 // 4.2 NegativeBind
10765 //-----------------------------------------------------------------------------
10766 class NegativeBind : public ShaderImageLoadStoreBase
10767 {
Setup()10768     virtual long Setup()
10769     {
10770         return NO_ERROR;
10771     }
10772 
Run()10773     virtual long Run()
10774     {
10775         glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10776         if (glGetError() != GL_INVALID_VALUE)
10777         {
10778             m_context.getTestContext().getLog() << tcu::TestLog::Message
10779                                                 << "BindImageTexture should generate INVALID_VALUE if <unit> is "
10780                                                    "greater than or equal to the value of MAX_IMAGE_UNITS."
10781                                                 << tcu::TestLog::EndMessage;
10782             return ERROR;
10783         }
10784 
10785         glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10786         if (glGetError() != GL_INVALID_VALUE)
10787         {
10788             m_context.getTestContext().getLog() << tcu::TestLog::Message
10789                                                 << "BindImageTexture should generate INVALID_VALUE if <texture> is not "
10790                                                    "the name of an existing texture object."
10791                                                 << tcu::TestLog::EndMessage;
10792             return ERROR;
10793         }
10794 
10795         glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234);
10796         if (glGetError() != GL_INVALID_VALUE)
10797         {
10798             m_context.getTestContext().getLog()
10799                 << tcu::TestLog::Message
10800                 << "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format."
10801                 << tcu::TestLog::EndMessage;
10802             return ERROR;
10803         }
10804         return NO_ERROR;
10805     }
10806 
Cleanup()10807     virtual long Cleanup()
10808     {
10809         return NO_ERROR;
10810     }
10811 };
10812 //-----------------------------------------------------------------------------
10813 // 4.3 NegativeCompileErrors
10814 //-----------------------------------------------------------------------------
10815 class NegativeCompileErrors : public ShaderImageLoadStoreBase
10816 {
Run()10817     virtual long Run()
10818     {
10819         if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10820                      "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
10821                      "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10822             return ERROR;
10823 
10824         if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10825                      "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
10826                      "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10827             return ERROR;
10828 
10829         if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL
10830                      "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
10831                      "  imageStore(g_image, ivec2(0), i_color);" NL "  o_color = i_color;" NL "}"))
10832             return ERROR;
10833 
10834         if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL
10835                      "void main() {" NL "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10836             return ERROR;
10837 
10838         if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10839                      "readonly uniform image2D g_image;" NL "void main() {" NL
10840                      "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10841             return ERROR;
10842 
10843         if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10844                      "layout(rg16i) uniform image1D g_image;" NL "void main() {" NL "  o_color = vec4(1.0);" NL "}"))
10845             return ERROR;
10846 
10847         if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10848                      "layout(rg16) uniform iimage2D g_image;" NL "void main() {" NL "  o_color = vec4(1.0);" NL "}"))
10849             return ERROR;
10850 
10851         if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10852                      "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL
10853                      "  imageAtomicAdd(g_image, ivec2(1), 10);" NL "  o_color = vec4(1.0);" NL "}"))
10854             return ERROR;
10855 
10856         if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10857                      "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL
10858                      "  imageAtomicAdd(g_image, ivec2(1), 1u);" NL "  o_color = vec4(1.0);" NL "}"))
10859             return ERROR;
10860 
10861         if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10862                      "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL
10863                      "  imageStore(g_image, ivec3(1), ivec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
10864             return ERROR;
10865 
10866         if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10867                      "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL
10868                      "  imageStore(g_image, ivec3(0), uvec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
10869             return ERROR;
10870 
10871         if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10872                      "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL
10873                      "  return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL "  o_color = Load(g_image);" NL
10874                      "}"))
10875             return ERROR;
10876 
10877         return NO_ERROR;
10878     }
10879 
Compile(const std::string & source)10880     bool Compile(const std::string &source)
10881     {
10882         const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
10883 
10884         const char *const src = source.c_str();
10885         glShaderSource(sh, 1, &src, NULL);
10886         glCompileShader(sh);
10887 
10888         GLchar log[1024];
10889         glGetShaderInfoLog(sh, sizeof(log), NULL, log);
10890         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
10891                                             << log << tcu::TestLog::EndMessage;
10892 
10893         GLint status;
10894         glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
10895         glDeleteShader(sh);
10896 
10897         if (status == GL_TRUE)
10898         {
10899             m_context.getTestContext().getLog()
10900                 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
10901             return false;
10902         }
10903 
10904         return true;
10905     }
10906 };
10907 //-----------------------------------------------------------------------------
10908 // 4.4 NegativeLinkErrors
10909 //-----------------------------------------------------------------------------
10910 class NegativeLinkErrors : public ShaderImageLoadStoreBase
10911 {
Run()10912     virtual long Run()
10913     {
10914         if (!SupportedInVS(1))
10915             return NOT_SUPPORTED;
10916 
10917         if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10918                   "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10919                   "  imageStore(g_image, gl_VertexID, vec4(0));" NL "  gl_Position = i_position;" NL "}",
10920                   "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10921                   "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL
10922                   "  imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
10923             return ERROR;
10924 
10925         if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10926                   "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10927                   "  imageStore(g_image, gl_VertexID, vec4(0));" NL "  gl_Position = i_position;" NL "}",
10928                   "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10929                   "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL
10930                   "  imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
10931             return ERROR;
10932 
10933         return NO_ERROR;
10934     }
10935 
Link(const std::string & vs,const std::string & fs)10936     bool Link(const std::string &vs, const std::string &fs)
10937     {
10938         const GLuint p = glCreateProgram();
10939 
10940         const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
10941         glAttachShader(p, vsh);
10942         glDeleteShader(vsh);
10943         const char *const vssrc = vs.c_str();
10944         glShaderSource(vsh, 1, &vssrc, NULL);
10945         glCompileShader(vsh);
10946 
10947         const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
10948         glAttachShader(p, fsh);
10949         glDeleteShader(fsh);
10950         const char *const fssrc = fs.c_str();
10951         glShaderSource(fsh, 1, &fssrc, NULL);
10952         glCompileShader(fsh);
10953 
10954         GLint status;
10955         glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
10956         if (status == GL_FALSE)
10957         {
10958             glDeleteProgram(p);
10959             m_context.getTestContext().getLog()
10960                 << tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
10961             return false;
10962         }
10963         glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
10964         if (status == GL_FALSE)
10965         {
10966             glDeleteProgram(p);
10967             m_context.getTestContext().getLog()
10968                 << tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
10969             return false;
10970         }
10971 
10972         glLinkProgram(p);
10973 
10974         GLchar log[1024];
10975         glGetProgramInfoLog(p, sizeof(log), NULL, log);
10976         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
10977                                             << log << tcu::TestLog::EndMessage;
10978 
10979         glGetProgramiv(p, GL_LINK_STATUS, &status);
10980         glDeleteProgram(p);
10981 
10982         if (status == GL_TRUE)
10983         {
10984             m_context.getTestContext().getLog()
10985                 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
10986             return false;
10987         }
10988 
10989         return true;
10990     }
10991 };
10992 
10993 /** Negative Test "Active image uniform limits", description follows.
10994  *
10995  *  Program that exceeds resource limits should not compile and/or link.
10996  *
10997  *  Steps:
10998  *  - try to compile and link a program that uses too many image uniforms in
10999  *  fragment shader stage,
11000  *  - try to compile and link a program that uses too many image uniforms in
11001  *  vertex shader stage,
11002  *  - try to compile and link a program that uses too many image uniforms in
11003  *  tessellation control shader stage,
11004  *  - try to compile and link a program that uses too many image uniforms in
11005  *  tessellation evaluation shader stage,
11006  *  - try to compile and link a program that uses too many image uniforms in
11007  *  geometry shader stage,
11008  *  - try to compile and link a program that uses too many image uniforms in all
11009  *  shader stages combined, any single stage should not exceed its limits, this
11010  *  step might be impossible to fulfill.
11011  *
11012  *  Test should use the following declaration of image uniforms:
11013  *  layout(r32i) uniform iimage2D u_image[N_UNIFORMS];
11014  *
11015  *  For cases where limit for single stage is tested, N_UNIFORMS should be
11016  *  defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant
11017  *  corresponding to tested shader stage.
11018  *
11019  *  For case where limit for combined stages is tested:
11020  *  - u_image name should be appended with the name of shader stage, like
11021  *  u_image_vertex,
11022  *  - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where
11023  *  gl_Max*ImageUniforms is constant corresponding to tested shader stage,
11024  *  - compilation and linking shall succeed, when sum of all
11025  *  gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to
11026  *  gl_MaxCombinedImageUniforms.
11027  *
11028  *  All defined image uniforms have to be active. Each shader stage that declare
11029  *  image uniforms should include following code snippet:
11030  *  value = 1;
11031  *  for (int i = 0; i < N_UNIFORMS; ++i)
11032  *  {
11033  *      value = imageAtomicAdd(u_image[i], coord, value);
11034  *  }
11035  **/
11036 class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase
11037 {
11038 private:
11039     /* Fields */
11040     /* Results */
11041     bool m_result_for_combined;
11042     bool m_result_for_fragment_shader;
11043     bool m_result_for_geometry_shader;
11044     bool m_result_for_tesselation_control_shader;
11045     bool m_result_for_tesselatioon_evaluation_shader;
11046     bool m_result_for_vertex_shader;
11047 
11048 public:
11049     /* Constructor */
ImageLoadStoreUniformLimitsTest()11050     ImageLoadStoreUniformLimitsTest()
11051         : m_result_for_combined(false)
11052         , m_result_for_fragment_shader(false)
11053         , m_result_for_geometry_shader(false)
11054         , m_result_for_tesselation_control_shader(false)
11055         , m_result_for_tesselatioon_evaluation_shader(false)
11056         , m_result_for_vertex_shader(false)
11057     {
11058         /* Nothing to be done */
11059     }
11060 
11061     /* Methods inherited from SubcaseBase */
Cleanup()11062     virtual long Cleanup()
11063     {
11064         /* Done */
11065         return NO_ERROR;
11066     }
11067 
Run()11068     virtual long Run()
11069     {
11070         m_context.getTestContext().getLog() << tcu::TestLog::Message
11071                                             << "This test tries to build invalid programs, expect error messages about "
11072                                                "exceeded number of active image uniforms"
11073                                             << tcu::TestLog::EndMessage;
11074 
11075         testFragmentShaderStage();
11076         testGeometryShaderStage();
11077         testTesselationControlShaderStage();
11078         testTesselationEvaluationShaderStage();
11079         testVertexShaderStage();
11080         testCombinedShaderStages();
11081 
11082         /* Return error if any stage failed */
11083         if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) ||
11084             (false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) ||
11085             (false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader))
11086         {
11087             return ERROR;
11088         }
11089 
11090         /* Done */
11091         return NO_ERROR;
11092     }
11093 
Setup()11094     virtual long Setup()
11095     {
11096         /* Done */
11097         return NO_ERROR;
11098     }
11099 
11100 private:
11101     /** Test fragment shader stage
11102      *
11103      **/
testFragmentShaderStage()11104     void testFragmentShaderStage()
11105     {
11106         static const char *const fragment_shader_code =
11107             "#version 400 core\n"
11108             "#extension GL_ARB_shader_image_load_store : require\n"
11109             "\n"
11110             "precision highp float;\n"
11111             "\n"
11112             "#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n"
11113             "\n"
11114             "flat in ivec2 vs_fs_coord;\n"
11115             "\n"
11116             "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11117             "\n"
11118             "void main()\n"
11119             "{\n"
11120             "    int value = 1;\n"
11121             "\n"
11122             "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11123             "    {\n"
11124             "        value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n"
11125             "    }\n"
11126             "\n"
11127             "    discard;\n"
11128             "}\n\n";
11129 
11130         static const char *const vertex_shader_code = "#version 400 core\n"
11131                                                       "#extension GL_ARB_shader_image_load_store : require\n"
11132                                                       "\n"
11133                                                       "precision highp float;\n"
11134                                                       "\n"
11135                                                       "     in  ivec2 vs_in_coord;\n"
11136                                                       "flat out ivec2 vs_fs_coord;\n"
11137                                                       "\n"
11138                                                       "void main()\n"
11139                                                       "{\n"
11140                                                       "    vs_fs_coord = vs_in_coord;\n"
11141                                                       "}\n\n";
11142 
11143         m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11144                                                         0 /* tesselation_control_shader_code */,
11145                                                         0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11146 
11147         if (false == m_result_for_fragment_shader)
11148         {
11149             m_context.getTestContext().getLog()
11150                 << tcu::TestLog::Message
11151                 << "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully."
11152                 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11153                 << fragment_shader_code << tcu::TestLog::EndMessage;
11154         }
11155     }
11156 
11157     /** Test geometry shader stage
11158      *
11159      **/
testGeometryShaderStage()11160     void testGeometryShaderStage()
11161     {
11162         static const char *const fragment_shader_code = "#version 400 core\n"
11163                                                         "#extension GL_ARB_shader_image_load_store : require\n"
11164                                                         "\n"
11165                                                         "precision highp float;\n"
11166                                                         "\n"
11167                                                         "void main()\n"
11168                                                         "{\n"
11169                                                         "    discard;\n"
11170                                                         "}\n\n";
11171 
11172         static const char *const geometry_shader_code =
11173             "#version 400 core\n"
11174             "#extension GL_ARB_shader_image_load_store : require\n"
11175             "\n"
11176             "precision highp float;\n"
11177             "\n"
11178             "layout(points)                   in;\n"
11179             "layout(points, max_vertices = 1) out;\n"
11180             "\n"
11181             "#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n"
11182             "\n"
11183             "in ivec2 vs_gs_coord[];\n"
11184             "\n"
11185             "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11186             "\n"
11187             "void main()\n"
11188             "{\n"
11189             "    int value = 1;\n"
11190             "\n"
11191             "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11192             "    {\n"
11193             "        value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\n"
11194             "    }\n"
11195             "}\n\n";
11196 
11197         static const char *const vertex_shader_code = "#version 400 core\n"
11198                                                       "#extension GL_ARB_shader_image_load_store : require\n"
11199                                                       "\n"
11200                                                       "precision highp float;\n"
11201                                                       "\n"
11202                                                       "in  ivec2 vs_in_coord;\n"
11203                                                       "out ivec2 vs_gs_coord;\n"
11204                                                       "\n"
11205                                                       "void main()\n"
11206                                                       "{\n"
11207                                                       "    vs_gs_coord = vs_in_coord;\n"
11208                                                       "}\n\n";
11209 
11210         m_result_for_geometry_shader =
11211             !doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */,
11212                              0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11213 
11214         if (false == m_result_for_geometry_shader)
11215         {
11216             m_context.getTestContext().getLog()
11217                 << tcu::TestLog::Message
11218                 << "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully."
11219                 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11220                 << geometry_shader_code << tcu::TestLog::EndMessage;
11221         }
11222     }
11223 
11224     /** Test tesselation control shader stage
11225      *
11226      **/
testTesselationControlShaderStage()11227     void testTesselationControlShaderStage()
11228     {
11229         static const char *const fragment_shader_code = "#version 400 core\n"
11230                                                         "#extension GL_ARB_shader_image_load_store : require\n"
11231                                                         "\n"
11232                                                         "precision highp float;\n"
11233                                                         "\n"
11234                                                         "void main()\n"
11235                                                         "{\n"
11236                                                         "    discard;\n"
11237                                                         "}\n\n";
11238 
11239         static const char *const tesselation_control_shader_code =
11240             "#version 400 core\n"
11241             "#extension GL_ARB_shader_image_load_store : require\n"
11242             "\n"
11243             "precision highp float;\n"
11244             "\n"
11245             "layout(vertices = 4) out;\n"
11246             "\n"
11247             "#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n"
11248             "\n"
11249             "in ivec2 vs_tcs_coord[];\n"
11250             "\n"
11251             "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11252             "\n"
11253             "void main()\n"
11254             "{\n"
11255             "    int value = 1;\n"
11256             "\n"
11257             "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11258             "    {\n"
11259             "        value = imageAtomicAdd(u_image[i], vs_tcs_coord[0], value);\n"
11260             "    }\n"
11261             "}\n\n";
11262 
11263         static const char *const tesselation_evaluation_shader_code =
11264             "#version 400 core\n"
11265             "#extension GL_ARB_shader_image_load_store : require\n"
11266             "\n"
11267             "precision highp float;\n"
11268             "\n"
11269             "layout(quads, equal_spacing, ccw) in;\n"
11270             "\n"
11271             "void main()\n"
11272             "{\n"
11273             "}\n";
11274 
11275         static const char *const vertex_shader_code = "#version 400 core\n"
11276                                                       "#extension GL_ARB_shader_image_load_store : require\n"
11277                                                       "\n"
11278                                                       "precision highp float;\n"
11279                                                       "\n"
11280                                                       "in  ivec2 vs_in_coord;\n"
11281                                                       "out ivec2 vs_tcs_coord;\n"
11282                                                       "\n"
11283                                                       "void main()\n"
11284                                                       "{\n"
11285                                                       "    vs_tcs_coord = vs_in_coord;\n"
11286                                                       "}\n\n";
11287 
11288         m_result_for_tesselation_control_shader =
11289             !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code,
11290                              tesselation_evaluation_shader_code, vertex_shader_code);
11291 
11292         if (false == m_result_for_tesselation_control_shader)
11293         {
11294             m_context.getTestContext().getLog()
11295                 << tcu::TestLog::Message
11296                 << "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully."
11297                 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11298                 << tesselation_control_shader_code << tcu::TestLog::EndMessage;
11299         }
11300     }
11301 
11302     /** Test teselation evaluation shader stage
11303      *
11304      **/
testTesselationEvaluationShaderStage()11305     void testTesselationEvaluationShaderStage()
11306     {
11307         static const char *const fragment_shader_code = "#version 400 core\n"
11308                                                         "#extension GL_ARB_shader_image_load_store : require\n"
11309                                                         "\n"
11310                                                         "precision highp float;\n"
11311                                                         "\n"
11312                                                         "void main()\n"
11313                                                         "{\n"
11314                                                         "    discard;\n"
11315                                                         "}\n\n";
11316 
11317         static const char *const tesselation_evaluation_shader_code =
11318             "#version 400 core\n"
11319             "#extension GL_ARB_shader_image_load_store : require\n"
11320             "\n"
11321             "precision highp float;\n"
11322             "\n"
11323             "layout(quads, equal_spacing, ccw) in;\n"
11324             "\n"
11325             "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n"
11326             "\n"
11327             "in ivec2 vs_tes_coord[];\n"
11328             "\n"
11329             "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11330             "\n"
11331             "void main()\n"
11332             "{\n"
11333             "    int value = 1;\n"
11334             "\n"
11335             "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11336             "    {\n"
11337             "        value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n"
11338             "    }\n"
11339             "}\n\n";
11340 
11341         static const char *const vertex_shader_code = "#version 400 core\n"
11342                                                       "#extension GL_ARB_shader_image_load_store : require\n"
11343                                                       "\n"
11344                                                       "precision highp float;\n"
11345                                                       "\n"
11346                                                       "in  ivec2 vs_in_coord;\n"
11347                                                       "out ivec2 vs_tes_coord;\n"
11348                                                       "\n"
11349                                                       "void main()\n"
11350                                                       "{\n"
11351                                                       "    vs_tes_coord = vs_in_coord;\n"
11352                                                       "}\n\n";
11353 
11354         m_result_for_tesselatioon_evaluation_shader = !doesProgramLink(
11355             fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */,
11356             tesselation_evaluation_shader_code, vertex_shader_code);
11357 
11358         if (false == m_result_for_tesselatioon_evaluation_shader)
11359         {
11360             m_context.getTestContext().getLog()
11361                 << tcu::TestLog::Message
11362                 << "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully."
11363                 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11364                 << tesselation_evaluation_shader_code << tcu::TestLog::EndMessage;
11365         }
11366     }
11367 
11368     /** Test vertex shader stage
11369      *
11370      **/
testVertexShaderStage()11371     void testVertexShaderStage()
11372     {
11373         static const char *const fragment_shader_code = "#version 400 core\n"
11374                                                         "#extension GL_ARB_shader_image_load_store : require\n"
11375                                                         "\n"
11376                                                         "precision highp float;\n"
11377                                                         "\n"
11378                                                         "void main()\n"
11379                                                         "{\n"
11380                                                         "    discard;\n"
11381                                                         "}\n\n";
11382 
11383         static const char *const vertex_shader_code =
11384             "#version 400 core\n"
11385             "#extension GL_ARB_shader_image_load_store : require\n"
11386             "\n"
11387             "precision highp float;\n"
11388             "\n"
11389             "in ivec2 vs_in_coord;\n"
11390             "\n"
11391             "#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n"
11392             "\n"
11393             "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11394             "\n"
11395             "void main()\n"
11396             "{\n"
11397             "    int value = 1;\n"
11398             "\n"
11399             "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11400             "    {\n"
11401             "        value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11402             "    }\n"
11403             "}\n\n";
11404 
11405         m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11406                                                       0 /* tesselation_control_shader_code */,
11407                                                       0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11408 
11409         if (false == m_result_for_vertex_shader)
11410         {
11411             m_context.getTestContext().getLog()
11412                 << tcu::TestLog::Message
11413                 << "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully."
11414                 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11415                 << vertex_shader_code << tcu::TestLog::EndMessage;
11416         }
11417     }
11418 
11419     /** Test combined shader stages
11420      *
11421      **/
testCombinedShaderStages()11422     void testCombinedShaderStages()
11423     {
11424         std::string fragment_shader_code = "#version 400 core\n"
11425                                            "#extension GL_ARB_shader_image_load_store : require\n"
11426                                            "\n"
11427                                            "precision highp float;\n"
11428                                            "\n"
11429                                            "#define N_UNIFORMS gl_MaxFragmentImageUniforms\n"
11430                                            "\n"
11431                                            "flat in ivec2 gs_fs_coord;\n"
11432                                            "\n"
11433                                            "layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n"
11434                                            "\n"
11435                                            "void main()\n"
11436                                            "{\n"
11437                                            "    int value = 1;\n"
11438                                            "\n"
11439                                            "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11440                                            "    {\n"
11441                                            "        value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n"
11442                                            "    }\n"
11443                                            "\n"
11444                                            "    discard;\n"
11445                                            "}\n\n";
11446 
11447         std::string geometry_shader_code =
11448             "#version 400 core\n"
11449             "#extension GL_ARB_shader_image_load_store : require\n"
11450             "\n"
11451             "precision highp float;\n"
11452             "\n"
11453             "layout(points)                   in;\n"
11454             "layout(points, max_vertices = 1) out;\n"
11455             "\n"
11456             "#define N_UNIFORMS gl_MaxGeometryImageUniforms\n"
11457             "\n"
11458             "flat in  ivec2 tes_gs_coord[];\n"
11459             "flat out ivec2 gs_fs_coord;\n"
11460             "\n"
11461             "#ifdef IMAGES\n"
11462             "layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n"
11463             "#endif\n"
11464             "\n"
11465             "void main()\n"
11466             "{\n"
11467             "#ifdef IMAGES\n"
11468             "    int value = 1;\n"
11469             "\n"
11470             "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11471             "    {\n"
11472             "        value = imageAtomicAdd(u_image_geometry[i], tes_gs_coord[0], value);\n"
11473             "    }\n"
11474             "\n"
11475             "#endif\n"
11476             "    gs_fs_coord = tes_gs_coord[0];\n"
11477             "    EmitVertex();\n"
11478             "}\n\n";
11479 
11480         std::string tesselation_control_shader_code =
11481             "#version 400 core\n"
11482             "#extension GL_ARB_shader_image_load_store : require\n"
11483             "\n"
11484             "precision highp float;\n"
11485             "\n"
11486             "layout(vertices = 4) out;\n"
11487             "\n"
11488             "#define N_UNIFORMS gl_MaxTessControlImageUniforms\n"
11489             "\n"
11490             "flat in  ivec2 vs_tcs_coord[];\n"
11491             "flat out ivec2 tcs_tes_coord[];\n"
11492             "\n"
11493             "#ifdef IMAGES\n"
11494             "layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n"
11495             "#endif\n"
11496             "\n"
11497             "void main()\n"
11498             "{\n"
11499             "#ifdef IMAGES\n"
11500             "    int value = 1;\n"
11501             "\n"
11502             "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11503             "    {\n"
11504             "        value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n"
11505             "    }\n"
11506             "\n"
11507             "#endif\n"
11508             "    tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n"
11509             "}\n\n";
11510 
11511         std::string tesselation_evaluation_shader_code =
11512             "#version 400 core\n"
11513             "#extension GL_ARB_shader_image_load_store : require\n"
11514             "\n"
11515             "precision highp float;\n"
11516             "\n"
11517             "layout(quads, equal_spacing, ccw) in;\n"
11518             "\n"
11519             "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n"
11520             "\n"
11521             "flat in  ivec2 tcs_tes_coord[];\n"
11522             "flat out ivec2 tes_gs_coord;\n"
11523             "\n"
11524             "#ifdef IMAGES\n"
11525             "layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n"
11526             "#endif\n"
11527             "\n"
11528             "void main()\n"
11529             "{\n"
11530             "#ifdef IMAGES\n"
11531             "    int value = 1;\n"
11532             "\n"
11533             "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11534             "    {\n"
11535             "        value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n"
11536             "    }\n"
11537             "\n"
11538             "#endif\n"
11539             "    tes_gs_coord = tcs_tes_coord[0];\n"
11540             "}\n\n";
11541 
11542         std::string vertex_shader_code = "#version 400 core\n"
11543                                          "#extension GL_ARB_shader_image_load_store : require\n"
11544                                          "\n"
11545                                          "precision highp float;\n"
11546                                          "\n"
11547                                          "     in  ivec2 vs_in_coord;\n"
11548                                          "flat out ivec2 vs_tcs_coord;\n"
11549                                          "\n"
11550                                          "#define N_UNIFORMS gl_MaxVertexImageUniforms\n"
11551                                          "\n"
11552                                          "#ifdef IMAGES\n"
11553                                          "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11554                                          "#endif\n"
11555                                          "\n"
11556                                          "void main()\n"
11557                                          "{\n"
11558                                          "#ifdef IMAGES\n"
11559                                          "    int value = 1;\n"
11560                                          "\n"
11561                                          "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11562                                          "    {\n"
11563                                          "        value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11564                                          "    }\n"
11565                                          "\n"
11566                                          "#endif\n"
11567                                          "    vs_tcs_coord = vs_tcs_coord;\n"
11568                                          "}\n\n";
11569 
11570         /* Active image uniform limits */
11571         GLint max_combined_image_uniforms               = 0;
11572         GLint max_fragment_image_uniforms               = 0;
11573         GLint max_geometry_image_uniforms               = 0;
11574         GLint max_tesselation_control_image_uniforms    = 0;
11575         GLint max_tesselation_evaluation_image_uniforms = 0;
11576         GLint max_vertex_image_uniforms                 = 0;
11577 
11578         /* Get limit values */
11579         glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms);
11580         glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms);
11581         glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms);
11582         glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms);
11583         glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms);
11584         glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms);
11585         GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
11586 
11587         if (max_vertex_image_uniforms)
11588             vertex_shader_code.insert(18, "#define IMAGES\n");
11589         if (max_geometry_image_uniforms)
11590             geometry_shader_code.insert(18, "#define IMAGES\n");
11591         if (max_tesselation_control_image_uniforms)
11592             tesselation_control_shader_code.insert(18, "#define IMAGES\n");
11593         if (max_tesselation_evaluation_image_uniforms)
11594             tesselation_evaluation_shader_code.insert(18, "#define IMAGES\n");
11595 
11596         /* Check if program builds */
11597         m_result_for_combined = !doesProgramLink(
11598             fragment_shader_code.c_str(), geometry_shader_code.c_str(), tesselation_control_shader_code.c_str(),
11599             tesselation_evaluation_shader_code.c_str(), vertex_shader_code.c_str());
11600 
11601         /* Result depends on the limit values */
11602         if (max_combined_image_uniforms >=
11603             (max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms +
11604              max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms))
11605         {
11606             /* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */
11607             m_result_for_combined = !m_result_for_combined;
11608 
11609             if (false == m_result_for_combined)
11610             {
11611                 m_context.getTestContext().getLog()
11612                     << tcu::TestLog::Message << "There was an error while building a program."
11613                     << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11614                     << vertex_shader_code << "\nTesselation control shader code:\n"
11615                     << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11616                     << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11617                     << geometry_shader_code << "\nFragment shader code:\n"
11618                     << fragment_shader_code << tcu::TestLog::EndMessage;
11619             }
11620         }
11621         else
11622         {
11623             /* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */
11624             if (false == m_result_for_combined)
11625             {
11626                 m_context.getTestContext().getLog()
11627                     << tcu::TestLog::Message
11628                     << "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully."
11629                     << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11630                     << vertex_shader_code << "\nTesselation control shader code:\n"
11631                     << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11632                     << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11633                     << geometry_shader_code << "\nFragment shader code:\n"
11634                     << fragment_shader_code << tcu::TestLog::EndMessage;
11635             }
11636         }
11637     }
11638 
11639     /** Check if program builds successfully
11640      *
11641      * @param fragment_shader_code               Source code for fragment shader stage
11642      * @param geometry_shader_code               Source code for geometry shader stage
11643      * @param tesselation_control_shader_code    Source code for tesselation control shader stage
11644      * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage
11645      * @param vertex_shader_code                 Source code for vertex shader stage
11646      *
11647      * @return true if program was built without errors, false otherwise
11648      **/
doesProgramLink(const char * fragment_shader_code,const char * geometry_shader_code,const char * tesselation_control_shader_code,const char * tesselation_evaluation_shader_code,const char * vertex_shader_code)11649     bool doesProgramLink(const char *fragment_shader_code, const char *geometry_shader_code,
11650                          const char *tesselation_control_shader_code, const char *tesselation_evaluation_shader_code,
11651                          const char *vertex_shader_code)
11652     {
11653         bool is_program_built = true;
11654         GLuint program_id     = 0;
11655 
11656         program_id =
11657             BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
11658                          geometry_shader_code, fragment_shader_code, &is_program_built);
11659 
11660         if (0 != program_id)
11661         {
11662             glDeleteProgram(program_id);
11663         }
11664 
11665         return is_program_built;
11666     }
11667 };
11668 } // namespace
11669 
ShaderImageLoadStoreTests(deqp::Context & context)11670 ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context &context)
11671     : TestCaseGroup(context, "shader_image_load_store", "")
11672 {
11673 }
11674 
~ShaderImageLoadStoreTests(void)11675 ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
11676 {
11677 }
11678 
init()11679 void ShaderImageLoadStoreTests::init()
11680 {
11681     using namespace deqp;
11682     addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
11683     addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
11684     addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
11685     addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
11686     addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>));
11687     addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>));
11688     addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages",
11689                              TestSubcase::Create<BasicAllFormatsStoreGeometryStages>));
11690     addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages",
11691                              TestSubcase::Create<BasicAllFormatsLoadGeometryStages>));
11692     addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
11693                              TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
11694     addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>));
11695     addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>));
11696     addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>));
11697     addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>));
11698     addChild(
11699         new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
11700     addChild(
11701         new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>));
11702     addChild(
11703         new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>));
11704     addChild(
11705         new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>));
11706     addChild(
11707         new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
11708     addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
11709     addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>));
11710     addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>));
11711     addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
11712     addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>));
11713     addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
11714     addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
11715     addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
11716     addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
11717     addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>));
11718     addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>));
11719     addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
11720     addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>));
11721     addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
11722     addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation",
11723                              TestSubcase::Create<AdvancedMemoryDependentInvocation>));
11724     addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>));
11725     addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
11726     addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>));
11727     addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>));
11728     addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>));
11729     addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>));
11730     addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>));
11731     addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>));
11732     addChild(
11733         new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>));
11734     addChild(
11735         new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>));
11736     addChild(
11737         new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>));
11738     addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>));
11739     addChild(
11740         new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>));
11741     addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
11742     addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
11743     addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
11744     addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
11745     addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>));
11746 }
11747 } // namespace gl4cts
11748